@@ -119,8 +119,8 @@ void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT,
119119 getThunkArgTypes (FT, AttrList, TT, Out, Arm64ArgTypes, X64ArgTypes,
120120 HasSretPtr);
121121
122- Arm64Ty = FunctionType::get (Arm64RetTy, Arm64ArgTypes,
123- TT == ThunkType::Entry && FT-> isVarArg ());
122+ Arm64Ty = FunctionType::get (Arm64RetTy, Arm64ArgTypes, false );
123+
124124 X64Ty = FunctionType::get (X64RetTy, X64ArgTypes, false );
125125}
126126
@@ -158,13 +158,13 @@ void AArch64Arm64ECCallLowering::getThunkArgTypes(
158158 X64ArgTypes.push_back (I64Ty);
159159 }
160160
161+ // x4
162+ Arm64ArgTypes.push_back (PtrTy);
163+ X64ArgTypes.push_back (PtrTy);
164+ // x5
165+ Arm64ArgTypes.push_back (I64Ty);
161166 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
168168 // have proper isel for varargs
169169 X64ArgTypes.push_back (I64Ty);
170170 }
@@ -473,10 +473,11 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
473473
474474 bool TransformDirectToSRet = X64RetType->isVoidTy () && !RetTy->isVoidTy ();
475475 unsigned ThunkArgOffset = TransformDirectToSRet ? 2 : 1 ;
476+ unsigned PassthroughArgSize = F->isVarArg () ? 5 : Thunk->arg_size ();
476477
477478 // Translate arguments to call.
478479 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) {
480481 Value *Arg = Thunk->getArg (i);
481482 Type *ArgTy = Arm64Ty->getParamType (i - ThunkArgOffset);
482483 if (ArgTy->isArrayTy () || ArgTy->isStructTy () ||
@@ -493,6 +494,22 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
493494 Args.push_back (Arg);
494495 }
495496
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+
496513 // Call the function passed to the thunk.
497514 Value *Callee = Thunk->getArg (0 );
498515 Callee = IRB.CreateBitCast (Callee, PtrTy);
0 commit comments