Skip to content

Commit e90c108

Browse files
bylawsdpaoliello
authored andcommitted
[AArch64] Skip over shadow space for ARM64EC entry thunk variadic calls (#80994)
When in an entry thunk the x64 SP is passed in x4 but this cannot be directly passed through since x64 varargs calls have a 32 byte shadow store at SP followed by the in-stack parameters. ARM64EC varargs calls on the other hand expect x4 to point to the first in-stack parameter.
1 parent 780b4dc commit e90c108

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp

+26-9
Original file line numberDiff line numberDiff line change
@@ -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);

llvm/lib/Target/AArch64/AArch64CallingConvention.td

+3
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ def CC_AArch64_Arm64EC_VarArg : CallingConv<[
213213
// address is passed in X9.
214214
let Entry = 1 in
215215
def CC_AArch64_Arm64EC_Thunk : CallingConv<[
216+
// ARM64EC-specific: the InReg attribute can be used to access the x64 sp passed into entry thunks in x4 from the IR.
217+
CCIfInReg<CCIfType<[i64], CCAssignToReg<[X4]>>>,
218+
216219
// Byval aggregates are passed by pointer
217220
CCIfByVal<CCPassIndirect<i64>>,
218221

llvm/test/CodeGen/AArch64/arm64ec-entry-thunks.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ define void @has_varargs(...) nounwind {
147147
; CHECK-NEXT: add x29, sp, #160
148148
; CHECK-NEXT: .seh_add_fp 160
149149
; CHECK-NEXT: .seh_endprologue
150-
; CHECK-NEXT: mov x4, sp
150+
; CHECK-NEXT: add x4, x4, #32
151151
; CHECK-NEXT: mov x5, xzr
152152
; CHECK-NEXT: blr x9
153153
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_ret

0 commit comments

Comments
 (0)