@@ -43,6 +43,8 @@ static cl::opt<bool> GenerateThunks("arm64ec-generate-thunks", cl::Hidden,
43
43
44
44
namespace {
45
45
46
+ enum class ThunkType { GuestExit, Entry, Exit };
47
+
46
48
class AArch64Arm64ECCallLowering : public ModulePass {
47
49
public:
48
50
static char ID;
@@ -69,14 +71,14 @@ class AArch64Arm64ECCallLowering : public ModulePass {
69
71
Type *I64Ty;
70
72
Type *VoidTy;
71
73
72
- void getThunkType (FunctionType *FT, AttributeList AttrList, bool EntryThunk ,
74
+ void getThunkType (FunctionType *FT, AttributeList AttrList, ThunkType TT ,
73
75
raw_ostream &Out, FunctionType *&Arm64Ty,
74
76
FunctionType *&X64Ty);
75
77
void getThunkRetType (FunctionType *FT, AttributeList AttrList,
76
78
raw_ostream &Out, Type *&Arm64RetTy, Type *&X64RetTy,
77
79
SmallVectorImpl<Type *> &Arm64ArgTypes,
78
80
SmallVectorImpl<Type *> &X64ArgTypes, bool &HasSretPtr);
79
- void getThunkArgTypes (FunctionType *FT, AttributeList AttrList,
81
+ void getThunkArgTypes (FunctionType *FT, AttributeList AttrList, ThunkType TT,
80
82
raw_ostream &Out,
81
83
SmallVectorImpl<Type *> &Arm64ArgTypes,
82
84
SmallVectorImpl<Type *> &X64ArgTypes, bool HasSretPtr);
@@ -89,10 +91,11 @@ class AArch64Arm64ECCallLowering : public ModulePass {
89
91
90
92
void AArch64Arm64ECCallLowering::getThunkType (FunctionType *FT,
91
93
AttributeList AttrList,
92
- bool EntryThunk , raw_ostream &Out,
94
+ ThunkType TT , raw_ostream &Out,
93
95
FunctionType *&Arm64Ty,
94
96
FunctionType *&X64Ty) {
95
- Out << (EntryThunk ? " $ientry_thunk$cdecl$" : " $iexit_thunk$cdecl$" );
97
+ Out << (TT == ThunkType::Entry ? " $ientry_thunk$cdecl$"
98
+ : " $iexit_thunk$cdecl$" );
96
99
97
100
Type *Arm64RetTy;
98
101
Type *X64RetTy;
@@ -102,23 +105,25 @@ void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT,
102
105
103
106
// The first argument to a thunk is the called function, stored in x9.
104
107
// For exit thunks, we pass the called function down to the emulator;
105
- // for entry thunks, we just call the Arm64 function directly.
106
- if (!EntryThunk )
108
+ // for entry/guest exit thunks, we just call the Arm64 function directly.
109
+ if (TT == ThunkType::Exit )
107
110
Arm64ArgTypes.push_back (PtrTy);
108
111
X64ArgTypes.push_back (PtrTy);
109
112
110
113
bool HasSretPtr = false ;
111
114
getThunkRetType (FT, AttrList, Out, Arm64RetTy, X64RetTy, Arm64ArgTypes,
112
115
X64ArgTypes, HasSretPtr);
113
116
114
- getThunkArgTypes (FT, AttrList, Out, Arm64ArgTypes, X64ArgTypes, HasSretPtr);
117
+ getThunkArgTypes (FT, AttrList, TT, Out, Arm64ArgTypes, X64ArgTypes,
118
+ HasSretPtr);
115
119
116
- Arm64Ty = FunctionType::get (Arm64RetTy, Arm64ArgTypes, false );
120
+ Arm64Ty = FunctionType::get (Arm64RetTy, Arm64ArgTypes,
121
+ TT == ThunkType::Entry && FT->isVarArg ());
117
122
X64Ty = FunctionType::get (X64RetTy, X64ArgTypes, false );
118
123
}
119
124
120
125
void AArch64Arm64ECCallLowering::getThunkArgTypes (
121
- FunctionType *FT, AttributeList AttrList, raw_ostream &Out,
126
+ FunctionType *FT, AttributeList AttrList, ThunkType TT, raw_ostream &Out,
122
127
SmallVectorImpl<Type *> &Arm64ArgTypes,
123
128
SmallVectorImpl<Type *> &X64ArgTypes, bool HasSretPtr) {
124
129
@@ -151,14 +156,16 @@ void AArch64Arm64ECCallLowering::getThunkArgTypes(
151
156
X64ArgTypes.push_back (I64Ty);
152
157
}
153
158
154
- // x4
155
- Arm64ArgTypes.push_back (PtrTy);
156
- X64ArgTypes.push_back (PtrTy);
157
- // x5
158
- Arm64ArgTypes.push_back (I64Ty);
159
- // FIXME: x5 isn't actually passed/used by the x64 side; revisit once we
160
- // have proper isel for varargs
161
- X64ArgTypes.push_back (I64Ty);
159
+ 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
166
+ // have proper isel for varargs
167
+ X64ArgTypes.push_back (I64Ty);
168
+ }
162
169
return ;
163
170
}
164
171
@@ -339,8 +346,7 @@ Function *AArch64Arm64ECCallLowering::buildExitThunk(FunctionType *FT,
339
346
SmallString<256 > ExitThunkName;
340
347
llvm::raw_svector_ostream ExitThunkStream (ExitThunkName);
341
348
FunctionType *Arm64Ty, *X64Ty;
342
- getThunkType (FT, Attrs, /* EntryThunk*/ false , ExitThunkStream, Arm64Ty,
343
- X64Ty);
349
+ getThunkType (FT, Attrs, ThunkType::Exit, ExitThunkStream, Arm64Ty, X64Ty);
344
350
if (Function *F = M->getFunction (ExitThunkName))
345
351
return F;
346
352
@@ -443,7 +449,7 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
443
449
SmallString<256 > EntryThunkName;
444
450
llvm::raw_svector_ostream EntryThunkStream (EntryThunkName);
445
451
FunctionType *Arm64Ty, *X64Ty;
446
- getThunkType (F->getFunctionType (), F->getAttributes (), /* EntryThunk */ true ,
452
+ getThunkType (F->getFunctionType (), F->getAttributes (), ThunkType::Entry ,
447
453
EntryThunkStream, Arm64Ty, X64Ty);
448
454
if (Function *F = M->getFunction (EntryThunkName))
449
455
return F;
@@ -518,7 +524,7 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
518
524
Function *AArch64Arm64ECCallLowering::buildGuestExitThunk (Function *F) {
519
525
llvm::raw_null_ostream NullThunkName;
520
526
FunctionType *Arm64Ty, *X64Ty;
521
- getThunkType (F->getFunctionType (), F->getAttributes (), /* EntryThunk */ true ,
527
+ getThunkType (F->getFunctionType (), F->getAttributes (), ThunkType::GuestExit ,
522
528
NullThunkName, Arm64Ty, X64Ty);
523
529
auto MangledName = getArm64ECMangledFunctionName (F->getName ().str ());
524
530
assert (MangledName && " Can't guest exit to function that's already native" );
0 commit comments