Skip to content

Commit

Permalink
[AArch64] Fix generated types for ARM64EC variadic entry thunk targets (
Browse files Browse the repository at this point in the history
#80595)

ISel handles filling in x4/x5 when calling variadic functions as they
don't correspond to the 5th/6th X64 arguments but rather to the end of
the shadow space on the stack and the size in bytes of all stack
parameters (ignored and written as 0 for calls from entry thunks).

Will PR a follow up with ISel handling after this is merged.
  • Loading branch information
bylaws authored and dpaoliello committed Mar 11, 2024
1 parent d7a9810 commit 42c599a
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 23 deletions.
48 changes: 27 additions & 21 deletions llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ static cl::opt<bool> GenerateThunks("arm64ec-generate-thunks", cl::Hidden,

namespace {

enum class ThunkType { GuestExit, Entry, Exit };

class AArch64Arm64ECCallLowering : public ModulePass {
public:
static char ID;
Expand All @@ -69,14 +71,14 @@ class AArch64Arm64ECCallLowering : public ModulePass {
Type *I64Ty;
Type *VoidTy;

void getThunkType(FunctionType *FT, AttributeList AttrList, bool EntryThunk,
void getThunkType(FunctionType *FT, AttributeList AttrList, ThunkType TT,
raw_ostream &Out, FunctionType *&Arm64Ty,
FunctionType *&X64Ty);
void getThunkRetType(FunctionType *FT, AttributeList AttrList,
raw_ostream &Out, Type *&Arm64RetTy, Type *&X64RetTy,
SmallVectorImpl<Type *> &Arm64ArgTypes,
SmallVectorImpl<Type *> &X64ArgTypes, bool &HasSretPtr);
void getThunkArgTypes(FunctionType *FT, AttributeList AttrList,
void getThunkArgTypes(FunctionType *FT, AttributeList AttrList, ThunkType TT,
raw_ostream &Out,
SmallVectorImpl<Type *> &Arm64ArgTypes,
SmallVectorImpl<Type *> &X64ArgTypes, bool HasSretPtr);
Expand All @@ -89,10 +91,11 @@ class AArch64Arm64ECCallLowering : public ModulePass {

void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT,
AttributeList AttrList,
bool EntryThunk, raw_ostream &Out,
ThunkType TT, raw_ostream &Out,
FunctionType *&Arm64Ty,
FunctionType *&X64Ty) {
Out << (EntryThunk ? "$ientry_thunk$cdecl$" : "$iexit_thunk$cdecl$");
Out << (TT == ThunkType::Entry ? "$ientry_thunk$cdecl$"
: "$iexit_thunk$cdecl$");

Type *Arm64RetTy;
Type *X64RetTy;
Expand All @@ -102,23 +105,25 @@ void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT,

// The first argument to a thunk is the called function, stored in x9.
// For exit thunks, we pass the called function down to the emulator;
// for entry thunks, we just call the Arm64 function directly.
if (!EntryThunk)
// for entry/guest exit thunks, we just call the Arm64 function directly.
if (TT == ThunkType::Exit)
Arm64ArgTypes.push_back(PtrTy);
X64ArgTypes.push_back(PtrTy);

bool HasSretPtr = false;
getThunkRetType(FT, AttrList, Out, Arm64RetTy, X64RetTy, Arm64ArgTypes,
X64ArgTypes, HasSretPtr);

getThunkArgTypes(FT, AttrList, Out, Arm64ArgTypes, X64ArgTypes, HasSretPtr);
getThunkArgTypes(FT, AttrList, TT, Out, Arm64ArgTypes, X64ArgTypes,
HasSretPtr);

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

void AArch64Arm64ECCallLowering::getThunkArgTypes(
FunctionType *FT, AttributeList AttrList, raw_ostream &Out,
FunctionType *FT, AttributeList AttrList, ThunkType TT, raw_ostream &Out,
SmallVectorImpl<Type *> &Arm64ArgTypes,
SmallVectorImpl<Type *> &X64ArgTypes, bool HasSretPtr) {

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

// 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
// have proper isel for varargs
X64ArgTypes.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
// have proper isel for varargs
X64ArgTypes.push_back(I64Ty);
}
return;
}

Expand Down Expand Up @@ -339,8 +346,7 @@ Function *AArch64Arm64ECCallLowering::buildExitThunk(FunctionType *FT,
SmallString<256> ExitThunkName;
llvm::raw_svector_ostream ExitThunkStream(ExitThunkName);
FunctionType *Arm64Ty, *X64Ty;
getThunkType(FT, Attrs, /*EntryThunk*/ false, ExitThunkStream, Arm64Ty,
X64Ty);
getThunkType(FT, Attrs, ThunkType::Exit, ExitThunkStream, Arm64Ty, X64Ty);
if (Function *F = M->getFunction(ExitThunkName))
return F;

Expand Down Expand Up @@ -443,7 +449,7 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
SmallString<256> EntryThunkName;
llvm::raw_svector_ostream EntryThunkStream(EntryThunkName);
FunctionType *Arm64Ty, *X64Ty;
getThunkType(F->getFunctionType(), F->getAttributes(), /*EntryThunk*/ true,
getThunkType(F->getFunctionType(), F->getAttributes(), ThunkType::Entry,
EntryThunkStream, Arm64Ty, X64Ty);
if (Function *F = M->getFunction(EntryThunkName))
return F;
Expand Down Expand Up @@ -518,7 +524,7 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
Function *AArch64Arm64ECCallLowering::buildGuestExitThunk(Function *F) {
llvm::raw_null_ostream NullThunkName;
FunctionType *Arm64Ty, *X64Ty;
getThunkType(F->getFunctionType(), F->getAttributes(), /*EntryThunk*/ true,
getThunkType(F->getFunctionType(), F->getAttributes(), ThunkType::GuestExit,
NullThunkName, Arm64Ty, X64Ty);
auto MangledName = getArm64ECMangledFunctionName(F->getName().str());
assert(MangledName && "Can't guest exit to function that's already native");
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/AArch64/arm64ec-entry-thunks.ll
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ define void @has_varargs(...) nounwind {
; CHECK-NEXT: add x29, sp, #160
; CHECK-NEXT: .seh_add_fp 160
; CHECK-NEXT: .seh_endprologue
; CHECK-NEXT: ldp x8, x5, [x4, #32]
; CHECK-NEXT: mov x4, x8
; CHECK-NEXT: mov x4, sp
; CHECK-NEXT: mov x5, xzr
; CHECK-NEXT: blr x9
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_ret
; CHECK-NEXT: ldr x0, [x8, :lo12:__os_arm64x_dispatch_ret]
Expand Down

0 comments on commit 42c599a

Please sign in to comment.