@@ -117,8 +117,8 @@ void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT,
117
117
getThunkArgTypes (FT, AttrList, TT, Out, Arm64ArgTypes, X64ArgTypes,
118
118
HasSretPtr);
119
119
120
- Arm64Ty = FunctionType::get (Arm64RetTy, Arm64ArgTypes,
121
- TT == ThunkType::Entry && FT-> isVarArg ());
120
+ Arm64Ty = FunctionType::get (Arm64RetTy, Arm64ArgTypes, false );
121
+
122
122
X64Ty = FunctionType::get (X64RetTy, X64ArgTypes, false );
123
123
}
124
124
@@ -156,13 +156,13 @@ void AArch64Arm64ECCallLowering::getThunkArgTypes(
156
156
X64ArgTypes.push_back (I64Ty);
157
157
}
158
158
159
+ // x4
160
+ Arm64ArgTypes.push_back (PtrTy);
161
+ X64ArgTypes.push_back (PtrTy);
162
+ // x5
163
+ Arm64ArgTypes.push_back (I64Ty);
159
164
if (TT != ThunkType::Entry) {
160
- // x4
161
- Arm64ArgTypes.push_back (PtrTy);
162
- X64ArgTypes.push_back (PtrTy);
163
- // x5
164
- Arm64ArgTypes.push_back (I64Ty);
165
- // FIXME: x5 isn't actually passed/used by the x64 side; revisit once we
165
+ // FIXME: x5 isn't actually used by the x64 side; revisit once we
166
166
// have proper isel for varargs
167
167
X64ArgTypes.push_back (I64Ty);
168
168
}
@@ -471,10 +471,11 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
471
471
472
472
bool TransformDirectToSRet = X64RetType->isVoidTy () && !RetTy->isVoidTy ();
473
473
unsigned ThunkArgOffset = TransformDirectToSRet ? 2 : 1 ;
474
+ unsigned PassthroughArgSize = F->isVarArg () ? 5 : Thunk->arg_size ();
474
475
475
476
// Translate arguments to call.
476
477
SmallVector<Value *> Args;
477
- for (unsigned i = ThunkArgOffset, e = Thunk-> arg_size () ; i != e; ++i) {
478
+ for (unsigned i = ThunkArgOffset, e = PassthroughArgSize ; i != e; ++i) {
478
479
Value *Arg = Thunk->getArg (i);
479
480
Type *ArgTy = Arm64Ty->getParamType (i - ThunkArgOffset);
480
481
if (ArgTy->isArrayTy () || ArgTy->isStructTy () ||
@@ -491,6 +492,22 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
491
492
Args.push_back (Arg);
492
493
}
493
494
495
+ if (F->isVarArg ()) {
496
+ // The 5th argument to variadic entry thunks is used to model the x64 sp
497
+ // which is passed to the thunk in x4, this can be passed to the callee as
498
+ // the variadic argument start address after skipping over the 32 byte
499
+ // shadow store.
500
+
501
+ // The EC thunk CC will assign any argument marked as InReg to x4.
502
+ Thunk->addParamAttr (5 , Attribute::InReg);
503
+ Value *Arg = Thunk->getArg (5 );
504
+ Arg = IRB.CreatePtrAdd (Arg, IRB.getInt64 (0x20 ));
505
+ Args.push_back (Arg);
506
+
507
+ // Pass in a zero variadic argument size (in x5).
508
+ Args.push_back (IRB.getInt64 (0 ));
509
+ }
510
+
494
511
// Call the function passed to the thunk.
495
512
Value *Callee = Thunk->getArg (0 );
496
513
Callee = IRB.CreateBitCast (Callee, PtrTy);
0 commit comments