Skip to content

Commit 6112420

Browse files
committed
[AArch64] Skip over shadow space for ARM64EC entry thunk variadic calls
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 5c84054 commit 6112420

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp

Lines changed: 26 additions & 9 deletions
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

Lines changed: 3 additions & 0 deletions
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<[iPTR], CCAssignToReg<[X4]>>>,
218+
216219
// Byval aggregates are passed by pointer
217220
CCIfByVal<CCPassIndirect<i64>>,
218221

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

Lines changed: 1 addition & 1 deletion
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)