3030
3131#include " AirCCallSpecial.h"
3232#include " AirCode.h"
33+ #include " B3ArgumentRegValue.h"
34+ #include " B3AtomicValue.h"
35+ #include " B3BasicBlockInlines.h"
36+ #include " B3BreakCriticalEdges.h"
3337#include " B3CCallValue.h"
3438#include " B3Procedure.h"
3539
@@ -38,10 +42,10 @@ namespace JSC { namespace B3 { namespace Air {
3842namespace {
3943
4044template <typename BankInfo>
41- void marshallCCallArgumentImpl (Vector<Arg>& result, unsigned & argumentCount, unsigned & stackOffset, Value* child )
45+ void marshallCCallArgumentImpl (Vector<Arg>& result, unsigned & argumentCount, unsigned & stackOffset, Type childType )
4246{
43- const auto registerCount = cCallArgumentRegisterCount (child );
44- if (is32Bit () && child-> type () == Int64)
47+ const auto registerCount = cCallArgumentRegisterCount (childType );
48+ if (is32Bit () && childType == Int64)
4549 argumentCount = WTF ::roundUpToMultipleOf<2 >(argumentCount);
4650
4751 if (argumentCount < BankInfo::numberOfArgumentRegisters) {
@@ -57,10 +61,10 @@ void marshallCCallArgumentImpl(Vector<Arg>& result, unsigned& argumentCount, uns
5761 // In the rare case when the Arg width does not match the argument width
5862 // (32-bit arm passing a 64-bit argument), we respect the width needed
5963 // for each stack access:
60- slotSize = bytesForWidth (cCallArgumentRegisterWidth (child-> type () ));
64+ slotSize = bytesForWidth (cCallArgumentRegisterWidth (childType ));
6165
6266 // but the logical stack slot uses the natural alignment of the argument
63- slotAlignment = sizeofType (child-> type () );
67+ slotAlignment = sizeofType (childType );
6468
6569 } else {
6670 // On other platforms, arguments are always aligned to machine word
@@ -76,14 +80,15 @@ void marshallCCallArgumentImpl(Vector<Arg>& result, unsigned& argumentCount, uns
7680 }
7781}
7882
79- void marshallCCallArgument (Vector<Arg> &result, unsigned & gpArgumentCount, unsigned & fpArgumentCount, unsigned & stackOffset, Value* child)
83+
84+ void marshallCCallArgument (Vector<Arg> &result, unsigned & gpArgumentCount, unsigned & fpArgumentCount, unsigned & stackOffset, Type childType)
8085{
81- switch (bankForType (child-> type () )) {
86+ switch (bankForType (childType )) {
8287 case GP :
83- marshallCCallArgumentImpl<GPRInfo>(result, gpArgumentCount, stackOffset, child );
88+ marshallCCallArgumentImpl<GPRInfo>(result, gpArgumentCount, stackOffset, childType );
8489 return ;
8590 case FP :
86- marshallCCallArgumentImpl<FPRInfo>(result, fpArgumentCount, stackOffset, child );
91+ marshallCCallArgumentImpl<FPRInfo>(result, fpArgumentCount, stackOffset, childType );
8792 return ;
8893 }
8994 RELEASE_ASSERT_NOT_REACHED ();
@@ -99,7 +104,7 @@ Vector<Arg> computeCCallingConvention(Code& code, CCallValue* value)
99104 unsigned fpArgumentCount = 0 ;
100105 unsigned stackOffset = 0 ;
101106 for (unsigned i = 1 ; i < value->numChildren (); ++i)
102- marshallCCallArgument (result, gpArgumentCount, fpArgumentCount, stackOffset, value->child (i));
107+ marshallCCallArgument (result, gpArgumentCount, fpArgumentCount, stackOffset, value->child (i)-> type () );
103108 code.requestCallArgAreaSizeInBytes (WTF ::roundUpToMultipleOf<stackAlignmentBytes ()>(stackOffset));
104109 return result;
105110}
@@ -129,9 +134,9 @@ size_t cCallResultCount(Code& code, CCallValue* value)
129134 }
130135}
131136
132- size_t cCallArgumentRegisterCount (const Value* value )
137+ size_t cCallArgumentRegisterCount (Type type )
133138{
134- switch (value-> type () .kind ()) {
139+ switch (type.kind ()) {
135140 case Void:
136141 return 0 ;
137142 case Int64:
@@ -203,6 +208,91 @@ Inst buildCCall(Code& code, Value* origin, const Vector<Arg>& arguments)
203208 return inst;
204209}
205210
211+ #if CPU(ARM_THUMB2)
212+ Value* ArgumentValueList::makeStitch (B3 ::BasicBlock*, Value* hi, Value* low) const
213+ {
214+ return block->appendNew <Value>(procedure, Stitch, Origin (), hi, low);
215+ }
216+ #endif
217+
218+ Value* ArgumentValueList::makeCCallValue (B3 ::BasicBlock* block, Type type, Air::Arg arg) const
219+ {
220+ if (arg.isTmp () && arg.tmp ().isReg ()) {
221+ Value* val = block->appendNew <ArgumentRegValue>(procedure, Origin (), arg.reg ());
222+ if constexpr (!is32Bit ()) {
223+ if (type == Int32)
224+ val = block->appendNew <Value>(procedure, Trunc, Origin (), val);
225+ }
226+
227+ if (type == Float)
228+ val = block->appendNew <Value>(procedure, Trunc, Origin (), val);
229+
230+ return val;
231+ }
232+
233+ // we really shouldn't be using this except on arm32, so, assert just in
234+ // case, since the details are likely wrong for other architectures, and
235+ // it's not expected to end up here on 64-bit
236+ RELEASE_ASSERT (isARM_THUMB2 () && arg.isCallArg ());
237+
238+ return block->appendNew <MemoryValue>(procedure,
239+ Load,
240+ type,
241+ Origin (),
242+ block->appendNew <Value>(procedure, FramePointer, Origin ()),
243+ arg.offset () + 2 * sizeof (void *)
244+ );
245+ }
246+
247+ Value* ArgumentValueList::makeCCallValue (B3 ::BasicBlock* block, size_t idx) const
248+ {
249+ unsigned firstUnderlyingArg = argUnderlyingCounts[idx];
250+ unsigned argCount = 0 ;
251+ if (idx + 1 < types.size ())
252+ argCount = argUnderlyingCounts[idx + 1 ] - firstUnderlyingArg;
253+ else
254+ argCount = underlyingArgs.size () - firstUnderlyingArg;
255+ RELEASE_ASSERT (firstUnderlyingArg < underlyingArgs.size ());
256+ RELEASE_ASSERT (firstUnderlyingArg + argCount <= underlyingArgs.size ());
257+
258+ switch (types[idx].kind ()) {
259+ case Int32:
260+ case Float:
261+ case Double:
262+ RELEASE_ASSERT (argCount == 1 );
263+ return makeCCallValue (block, types[idx], underlyingArgs[firstUnderlyingArg]);
264+
265+ case Int64:
266+ RELEASE_ASSERT (argCount == sizeof (uint64_t ) / sizeof (uintptr_t ));
267+ #if CPU(ARM_THUMB2)
268+ return makeStitch (block, makeCCallValue (block, types[idx], underlyingArgs[firstUnderlyingArg + 1 ]),
269+ makeCCallValue (block, types[idx], underlyingArgs[firstUnderlyingArg]));
270+ #else
271+ return makeCCallValue (block, types[idx], underlyingArgs[firstUnderlyingArg]);
272+ #endif
273+
274+ default :
275+ RELEASE_ASSERT_NOT_REACHED ();
276+ return nullptr ;
277+ }
278+ }
279+
280+ ArgumentValueList computeCCallArguments (Procedure& procedure, B3 ::BasicBlock* block, const Vector<Type>& types)
281+ {
282+ Vector<Air::Arg> underlyingArgs;
283+ Vector<unsigned > argUnderlyingCounts;
284+ unsigned gpArgumentCount = 0 ;
285+ unsigned fpArgumentCount = 0 ;
286+ unsigned stackOffset = 0 ;
287+
288+ for (auto type : types) {
289+ argUnderlyingCounts.append (underlyingArgs.size ());
290+ marshallCCallArgument (underlyingArgs, gpArgumentCount, fpArgumentCount, stackOffset, type);
291+ }
292+
293+ return ArgumentValueList { procedure, block, types, WTFMove (underlyingArgs), WTFMove (argUnderlyingCounts) };
294+ }
295+
206296} } } // namespace JSC::B3::Air
207297
208298#endif // ENABLE(B3_JIT)
0 commit comments