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