[llvm] [AArch64] Skip over shadow space for ARM64EC entry thunk variadic calls (PR #80994)
Billy Laws via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 23 08:55:39 PST 2024
https://github.com/bylaws updated https://github.com/llvm/llvm-project/pull/80994
>From 4350ae4ae761b5aa5c2097d32e93fa4e3ea88392 Mon Sep 17 00:00:00 2001
From: Billy Laws <blaws05 at gmail.com>
Date: Sat, 17 Feb 2024 23:07:30 +0000
Subject: [PATCH] [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.
---
.../AArch64/AArch64Arm64ECCallLowering.cpp | 35 ++++++++++++++-----
.../AArch64/AArch64CallingConvention.td | 3 ++
2 files changed, 29 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
index c62582ac01a4cf..55c5bbc66a3f4f 100644
--- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
@@ -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);
}
@@ -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);
}
@@ -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() ||
@@ -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);
diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.td b/llvm/lib/Target/AArch64/AArch64CallingConvention.td
index 78ea4a5180f703..8e67f0f5c8815f 100644
--- a/llvm/lib/Target/AArch64/AArch64CallingConvention.td
+++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.td
@@ -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>>,
More information about the llvm-commits
mailing list