@@ -117,8 +117,8 @@ void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT,
117117 getThunkArgTypes (FT, AttrList, TT, Out, Arm64ArgTypes, X64ArgTypes,
118118 HasSretPtr);
119119
120- Arm64Ty = FunctionType::get (Arm64RetTy, Arm64ArgTypes,
121- TT == ThunkType::Entry && FT-> isVarArg ());
120+ Arm64Ty = FunctionType::get (Arm64RetTy, Arm64ArgTypes, false );
121+
122122 X64Ty = FunctionType::get (X64RetTy, X64ArgTypes, false );
123123}
124124
@@ -156,13 +156,13 @@ void AArch64Arm64ECCallLowering::getThunkArgTypes(
156156 X64ArgTypes.push_back (I64Ty);
157157 }
158158
159+ // x4
160+ Arm64ArgTypes.push_back (PtrTy);
161+ X64ArgTypes.push_back (PtrTy);
162+ // x5
163+ Arm64ArgTypes.push_back (I64Ty);
159164 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
166166 // have proper isel for varargs
167167 X64ArgTypes.push_back (I64Ty);
168168 }
@@ -471,10 +471,11 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
471471
472472 bool TransformDirectToSRet = X64RetType->isVoidTy () && !RetTy->isVoidTy ();
473473 unsigned ThunkArgOffset = TransformDirectToSRet ? 2 : 1 ;
474+ unsigned PassthroughArgSize = F->isVarArg () ? 5 : Thunk->arg_size ();
474475
475476 // Translate arguments to call.
476477 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) {
478479 Value *Arg = Thunk->getArg (i);
479480 Type *ArgTy = Arm64Ty->getParamType (i - ThunkArgOffset);
480481 if (ArgTy->isArrayTy () || ArgTy->isStructTy () ||
@@ -491,6 +492,22 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
491492 Args.push_back (Arg);
492493 }
493494
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+
494511 // Call the function passed to the thunk.
495512 Value *Callee = Thunk->getArg (0 );
496513 Callee = IRB.CreateBitCast (Callee, PtrTy);
0 commit comments