Skip to content

Commit

Permalink
[AArch64] Skip over shadow space for ARM64EC entry thunk variadic cal…
Browse files Browse the repository at this point in the history
…ls (llvm#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.
  • Loading branch information
bylaws authored and dpaoliello committed Mar 11, 2024
1 parent 42c599a commit 89d5432
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 10 deletions.
35 changes: 26 additions & 9 deletions llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT,
getThunkArgTypes(FT, AttrList, TT, Out, Arm64ArgTypes, X64ArgTypes,
HasSretPtr);

Arm64Ty = FunctionType::get(Arm64RetTy, Arm64ArgTypes,
TT == ThunkType::Entry && FT->isVarArg());
Arm64Ty = FunctionType::get(Arm64RetTy, Arm64ArgTypes, false);

X64Ty = FunctionType::get(X64RetTy, X64ArgTypes, false);
}

Expand Down Expand Up @@ -156,13 +156,13 @@ void AArch64Arm64ECCallLowering::getThunkArgTypes(
X64ArgTypes.push_back(I64Ty);
}

// x4
Arm64ArgTypes.push_back(PtrTy);
X64ArgTypes.push_back(PtrTy);
// x5
Arm64ArgTypes.push_back(I64Ty);
if (TT != ThunkType::Entry) {
// x4
Arm64ArgTypes.push_back(PtrTy);
X64ArgTypes.push_back(PtrTy);
// x5
Arm64ArgTypes.push_back(I64Ty);
// FIXME: x5 isn't actually passed/used by the x64 side; revisit once we
// FIXME: x5 isn't actually used by the x64 side; revisit once we
// have proper isel for varargs
X64ArgTypes.push_back(I64Ty);
}
Expand Down Expand Up @@ -471,10 +471,11 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {

bool TransformDirectToSRet = X64RetType->isVoidTy() && !RetTy->isVoidTy();
unsigned ThunkArgOffset = TransformDirectToSRet ? 2 : 1;
unsigned PassthroughArgSize = F->isVarArg() ? 5 : Thunk->arg_size();

// Translate arguments to call.
SmallVector<Value *> Args;
for (unsigned i = ThunkArgOffset, e = Thunk->arg_size(); i != e; ++i) {
for (unsigned i = ThunkArgOffset, e = PassthroughArgSize; i != e; ++i) {
Value *Arg = Thunk->getArg(i);
Type *ArgTy = Arm64Ty->getParamType(i - ThunkArgOffset);
if (ArgTy->isArrayTy() || ArgTy->isStructTy() ||
Expand All @@ -491,6 +492,22 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
Args.push_back(Arg);
}

if (F->isVarArg()) {
// The 5th argument to variadic entry thunks is used to model the x64 sp
// which is passed to the thunk in x4, this can be passed to the callee as
// the variadic argument start address after skipping over the 32 byte
// shadow store.

// The EC thunk CC will assign any argument marked as InReg to x4.
Thunk->addParamAttr(5, Attribute::InReg);
Value *Arg = Thunk->getArg(5);
Arg = IRB.CreatePtrAdd(Arg, IRB.getInt64(0x20));
Args.push_back(Arg);

// Pass in a zero variadic argument size (in x5).
Args.push_back(IRB.getInt64(0));
}

// Call the function passed to the thunk.
Value *Callee = Thunk->getArg(0);
Callee = IRB.CreateBitCast(Callee, PtrTy);
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/AArch64/AArch64CallingConvention.td
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ def CC_AArch64_Arm64EC_VarArg : CallingConv<[
// address is passed in X9.
let Entry = 1 in
def CC_AArch64_Arm64EC_Thunk : CallingConv<[
// ARM64EC-specific: the InReg attribute can be used to access the x64 sp passed into entry thunks in x4 from the IR.
CCIfInReg<CCIfType<[i64], CCAssignToReg<[X4]>>>,

// Byval aggregates are passed by pointer
CCIfByVal<CCPassIndirect<i64>>,

Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/AArch64/arm64ec-entry-thunks.ll
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ define void @has_varargs(...) nounwind {
; CHECK-NEXT: add x29, sp, #160
; CHECK-NEXT: .seh_add_fp 160
; CHECK-NEXT: .seh_endprologue
; CHECK-NEXT: mov x4, sp
; CHECK-NEXT: add x4, x4, #32
; CHECK-NEXT: mov x5, xzr
; CHECK-NEXT: blr x9
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_ret
Expand Down

0 comments on commit 89d5432

Please sign in to comment.