Skip to content

Commit

Permalink
[AArch64] Skip over shadow space for ARM64EC entry thunk variadic calls
Browse files Browse the repository at this point in the history
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 committed Feb 24, 2024
1 parent 7318585 commit 3405ea3
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 @@ -119,8 +119,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 @@ -158,13 +158,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 @@ -473,10 +473,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 @@ -493,6 +494,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 3405ea3

Please sign in to comment.