Skip to content

Commit 6158df2

Browse files
authored
TargetABI: Add base rewriteFunctionType() implementation (#4799)
1 parent c3c82c9 commit 6158df2

13 files changed

+44
-175
lines changed

gen/abi/aarch64.cpp

+3-12
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,7 @@ struct AArch64TargetABI : TargetABI {
8484
bool passByVal(TypeFunction *, Type *) override { return false; }
8585

8686
void rewriteFunctionType(IrFuncTy &fty) override {
87-
if (!skipReturnValueRewrite(fty)) {
88-
rewriteArgument(fty, *fty.ret, /*isReturnVal=*/true);
89-
}
90-
91-
for (auto arg : fty.args) {
92-
if (!arg->byref)
93-
rewriteArgument(fty, *arg, /*isReturnVal=*/false);
94-
}
87+
TargetABI::rewriteFunctionType(fty);
9588

9689
// remove 0-sized args (static arrays with 0 elements) and, for Darwin,
9790
// empty POD structs too
@@ -122,15 +115,13 @@ struct AArch64TargetABI : TargetABI {
122115
}
123116

124117
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
125-
return rewriteArgument(fty, arg, /*isReturnVal=*/false);
126-
}
127-
128-
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg, bool isReturnVal) {
129118
Type *t = arg.type->toBasetype();
130119

131120
if (!isAggregate(t))
132121
return;
133122

123+
const bool isReturnVal = &arg == fty.ret;
124+
134125
// compiler magic: pass va_list args implicitly by reference
135126
if (!isReturnVal && isAAPCS64VaList(t)) {
136127
arg.byref = true;

gen/abi/abi.cpp

+10-30
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,16 @@ bool TargetABI::preferPassByRef(Type *t) {
164164

165165
//////////////////////////////////////////////////////////////////////////////
166166

167+
void TargetABI::rewriteFunctionType(IrFuncTy &fty) {
168+
if (!skipReturnValueRewrite(fty))
169+
rewriteArgument(fty, *fty.ret);
170+
171+
for (auto arg : fty.args) {
172+
if (!arg->byref)
173+
rewriteArgument(fty, *arg);
174+
}
175+
}
176+
167177
void TargetABI::rewriteVarargs(IrFuncTy &fty,
168178
std::vector<IrFuncTyArg *> &args) {
169179
for (auto arg : args) {
@@ -231,10 +241,6 @@ struct UnknownTargetABI : TargetABI {
231241
bool passByVal(TypeFunction *, Type *t) override {
232242
return DtoIsInMemoryOnly(t);
233243
}
234-
235-
void rewriteFunctionType(IrFuncTy &) override {
236-
// why?
237-
}
238244
};
239245

240246
//////////////////////////////////////////////////////////////////////////////
@@ -305,32 +311,6 @@ struct IntrinsicABI : TargetABI {
305311
remove_padding.applyTo(arg, abiTy);
306312
}
307313
}
308-
309-
void rewriteFunctionType(IrFuncTy &fty) override {
310-
if (!fty.arg_sret) {
311-
Type *rt = fty.ret->type->toBasetype();
312-
if (rt->ty == TY::Tstruct) {
313-
Logger::println("Intrinsic ABI: Transforming return type");
314-
rewriteArgument(fty, *fty.ret);
315-
}
316-
}
317-
318-
Logger::println("Intrinsic ABI: Transforming arguments");
319-
LOG_SCOPE;
320-
321-
for (auto arg : fty.args) {
322-
IF_LOG Logger::cout() << "Arg: " << arg->type->toChars() << '\n';
323-
324-
// Arguments that are in memory are of no interest to us.
325-
if (arg->byref) {
326-
continue;
327-
}
328-
329-
rewriteArgument(fty, *arg);
330-
331-
IF_LOG Logger::cout() << "New arg type: " << *arg->ltype << '\n';
332-
}
333-
}
334314
};
335315

336316
TargetABI *TargetABI::getIntrinsic() {

gen/abi/abi.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ struct TargetABI {
154154
virtual bool passThisBeforeSret(TypeFunction *tf) { return false; }
155155

156156
/// Called to give ABI the chance to rewrite the types
157-
virtual void rewriteFunctionType(IrFuncTy &fty) = 0;
157+
virtual void rewriteFunctionType(IrFuncTy &fty);
158158
virtual void rewriteVarargs(IrFuncTy &fty, std::vector<IrFuncTyArg *> &args);
159159
virtual void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) {}
160160

gen/abi/arm.cpp

+4-18
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,6 @@ struct ArmTargetABI : TargetABI {
6969
// problem is better understood.
7070
}
7171

72-
void rewriteFunctionType(IrFuncTy &fty) override {
73-
Type *retTy = fty.ret->type->toBasetype();
74-
if (!fty.ret->byref && retTy->ty == TY::Tstruct) {
75-
// Rewrite HFAs only because union HFAs are turned into IR types that are
76-
// non-HFA and messes up register selection
77-
if (isHFVA(retTy, hfvaToArray.maxElements, &fty.ret->ltype)) {
78-
hfvaToArray.applyTo(*fty.ret, fty.ret->ltype);
79-
} else {
80-
integerRewrite.applyTo(*fty.ret);
81-
}
82-
}
83-
84-
for (auto arg : fty.args) {
85-
if (!arg->byref)
86-
rewriteArgument(fty, *arg);
87-
}
88-
}
89-
9072
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
9173
// structs and arrays need rewrite as i32 arrays. This keeps data layout
9274
// unchanged when passed in registers r0-r3 and is necessary to match C ABI
@@ -95,6 +77,8 @@ struct ArmTargetABI : TargetABI {
9577
// r0, where before it consumed r0-r3.
9678
Type *ty = arg.type->toBasetype();
9779

80+
const bool isReturnValue = &arg == fty.ret;
81+
9882
// TODO: want to also rewrite Tsarray as i32 arrays, but sometimes
9983
// llvm selects an aligned ldrd instruction even though the ptr is
10084
// unaligned (e.g. walking through members of array char[5][]).
@@ -104,6 +88,8 @@ struct ArmTargetABI : TargetABI {
10488
// non-HFA and messes up register selection
10589
if (isHFVA(ty, hfvaToArray.maxElements, &arg.ltype)) {
10690
hfvaToArray.applyTo(arg, arg.ltype);
91+
} else if (isReturnValue) {
92+
integerRewrite.applyTo(arg);
10793
} else if (DtoAlignment(ty) <= 4) {
10894
compositeToArray32.applyTo(arg);
10995
} else {

gen/abi/loongarch64.cpp

+14-19
Original file line numberDiff line numberDiff line change
@@ -136,35 +136,30 @@ struct LoongArch64TargetABI : TargetABI {
136136
return size(t) > 16;
137137
}
138138

139-
void rewriteFunctionType(IrFuncTy &fty) override {
140-
if (!skipReturnValueRewrite(fty)) {
141-
if (requireHardfloatRewrite(fty.ret->type)) {
142-
// rewrite here because we should not apply this to variadic arguments
143-
hardfloatRewrite.applyTo(*fty.ret);
144-
} else {
145-
rewriteArgument(fty, *fty.ret);
146-
}
147-
}
148-
149-
for (auto arg : fty.args) {
150-
if (!arg->byref) {
151-
if (requireHardfloatRewrite(arg->type)) {
152-
// rewrite here because we should not apply this to variadic arguments
153-
hardfloatRewrite.applyTo(*arg);
154-
} else {
155-
rewriteArgument(fty, *arg);
156-
}
157-
}
139+
void rewriteVarargs(IrFuncTy &fty,
140+
std::vector<IrFuncTyArg *> &args) override {
141+
for (auto arg : args) {
142+
if (!arg->byref)
143+
rewriteArgument(fty, *arg, /*isVararg=*/true);
158144
}
159145
}
160146

161147
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
148+
rewriteArgument(fty, arg, /*isVararg=*/false);
149+
}
150+
151+
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg, bool isVararg) {
162152
if (!isPOD(arg.type)) {
163153
// non-PODs should be passed in memory
164154
indirectByvalRewrite.applyTo(arg);
165155
return;
166156
}
167157

158+
if (!isVararg && requireHardfloatRewrite(arg.type)) {
159+
hardfloatRewrite.applyTo(arg);
160+
return;
161+
}
162+
168163
Type *ty = arg.type->toBasetype();
169164
if (ty->isintegral() && (ty->ty == TY::Tint32 || ty->ty == TY::Tuns32 ||
170165
ty->ty == TY::Tdchar)) {

gen/abi/mips64.cpp

-12
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,6 @@ struct MIPS64TargetABI : TargetABI {
4646
return ty == TY::Tstruct || ty == TY::Tsarray;
4747
}
4848

49-
void rewriteFunctionType(IrFuncTy &fty) override {
50-
if (!fty.ret->byref) {
51-
rewriteArgument(fty, *fty.ret);
52-
}
53-
54-
for (auto arg : fty.args) {
55-
if (!arg->byref) {
56-
rewriteArgument(fty, *arg);
57-
}
58-
}
59-
}
60-
6149
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
6250
// FIXME
6351
}

gen/abi/nvptx.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@ struct NVPTXTargetABI : TargetABI {
3030
t = t->toBasetype();
3131
return ((t->ty == TY::Tsarray || t->ty == TY::Tstruct) && size(t) > 64);
3232
}
33-
void rewriteFunctionType(IrFuncTy &fty) override {
34-
for (auto arg : fty.args) {
35-
if (!arg->byref)
36-
rewriteArgument(fty, *arg);
37-
}
38-
}
3933
bool returnInArg(TypeFunction *tf, bool) override {
4034
return !tf->isref() && DtoIsInMemoryOnly(tf->next);
4135
}

gen/abi/ppc.cpp

-14
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,6 @@ struct PPCTargetABI : TargetABI {
5959
(!Is64Bit || size(t) > 64);
6060
}
6161

62-
void rewriteFunctionType(IrFuncTy &fty) override {
63-
// return value
64-
if (!fty.ret->byref) {
65-
rewriteArgument(fty, *fty.ret);
66-
}
67-
68-
// explicit parameters
69-
for (auto arg : fty.args) {
70-
if (!arg->byref) {
71-
rewriteArgument(fty, *arg);
72-
}
73-
}
74-
}
75-
7662
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
7763
Type *ty = arg.type->toBasetype();
7864

gen/abi/ppc64le.cpp

-14
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,6 @@ struct PPC64LETargetABI : TargetABI {
4848
!isHFVA(t, hfvaToArray.maxElements));
4949
}
5050

51-
void rewriteFunctionType(IrFuncTy &fty) override {
52-
// return value
53-
if (!fty.ret->byref) {
54-
rewriteArgument(fty, *fty.ret);
55-
}
56-
57-
// explicit parameters
58-
for (auto arg : fty.args) {
59-
if (!arg->byref) {
60-
rewriteArgument(fty, *arg);
61-
}
62-
}
63-
}
64-
6551
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
6652
Type *ty = arg.type->toBasetype();
6753
if (ty->ty == TY::Tstruct || ty->ty == TY::Tsarray) {

gen/abi/riscv64.cpp

+11-21
Original file line numberDiff line numberDiff line change
@@ -182,32 +182,22 @@ struct RISCV64TargetABI : TargetABI {
182182
}
183183
return size(t) > 16;
184184
}
185-
void rewriteFunctionType(IrFuncTy &fty) override {
186-
if (!fty.ret->byref) {
187-
if (!skipReturnValueRewrite(fty)) {
188-
if (!fty.ret->byref && isPOD(fty.ret->type) &&
189-
requireHardfloatRewrite(fty.ret->type)) {
190-
// rewrite here because we should not apply this to variadic arguments
191-
hardfloatRewrite.applyTo(*fty.ret);
192-
} else {
193-
rewriteArgument(fty, *fty.ret);
194-
}
195-
}
196-
}
197185

198-
for (auto arg : fty.args) {
199-
if (!arg->byref && isPOD(arg->type) &&
200-
requireHardfloatRewrite(arg->type)) {
201-
// rewrite here because we should not apply this to variadic arguments
202-
hardfloatRewrite.applyTo(*arg);
203-
} else {
204-
rewriteArgument(fty, *arg);
205-
}
186+
void rewriteVarargs(IrFuncTy &fty,
187+
std::vector<IrFuncTyArg *> &args) override {
188+
for (auto arg : args) {
189+
if (!arg->byref)
190+
rewriteArgument(fty, *arg, /*isVararg=*/true);
206191
}
207192
}
208193

209194
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
210-
if (arg.byref) {
195+
rewriteArgument(fty, arg, /*isVararg=*/false);
196+
}
197+
198+
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg, bool isVararg) {
199+
if (!isVararg && isPOD(arg.type) && requireHardfloatRewrite(arg.type)) {
200+
hardfloatRewrite.applyTo(arg);
211201
return;
212202
}
213203

gen/abi/spirv.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,6 @@ struct SPIRVTargetABI : TargetABI {
3030
t = t->toBasetype();
3131
return ((t->ty == TY::Tsarray || t->ty == TY::Tstruct) && size(t) > 64);
3232
}
33-
void rewriteFunctionType(IrFuncTy &fty) override {
34-
for (auto arg : fty.args) {
35-
if (!arg->byref)
36-
rewriteArgument(fty, *arg);
37-
}
38-
if (!skipReturnValueRewrite(fty))
39-
rewriteArgument(fty, *fty.ret);
40-
}
4133
bool returnInArg(TypeFunction *tf, bool) override {
4234
if (tf->isref())
4335
return false;

gen/abi/wasm.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ struct WasmTargetABI : TargetABI {
6969
bool passByVal(TypeFunction *, Type *t) override {
7070
return DtoIsInMemoryOnly(t) && !isDirectlyPassedAggregate(t);
7171
}
72-
73-
void rewriteFunctionType(IrFuncTy &) override {}
7472
};
7573

7674
// The public getter for abi.cpp.

gen/abi/win64.cpp

+1-18
Original file line numberDiff line numberDiff line change
@@ -155,20 +155,6 @@ struct Win64TargetABI : TargetABI {
155155
return tf->linkage == LINK::cpp;
156156
}
157157

158-
void rewriteFunctionType(IrFuncTy &fty) override {
159-
// return value
160-
if (!skipReturnValueRewrite(fty)) {
161-
rewrite(fty, *fty.ret, /*isReturnValue=*/true);
162-
}
163-
164-
// explicit parameters
165-
for (auto arg : fty.args) {
166-
if (!arg->byref) {
167-
rewriteArgument(fty, *arg);
168-
}
169-
}
170-
}
171-
172158
void rewriteVarargs(IrFuncTy &fty,
173159
std::vector<IrFuncTyArg *> &args) override {
174160
for (auto arg : args) {
@@ -183,12 +169,9 @@ struct Win64TargetABI : TargetABI {
183169
}
184170

185171
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
186-
rewrite(fty, arg, /*isReturnValue=*/false);
187-
}
188-
189-
void rewrite(IrFuncTy &fty, IrFuncTyArg &arg, bool isReturnValue) {
190172
Type *t = arg.type->toBasetype();
191173
LLType *originalLType = arg.ltype;
174+
const bool isReturnValue = &arg == fty.ret;
192175

193176
if (passPointerToHiddenCopy(t, isReturnValue, fty.type)) {
194177
// the caller allocates a hidden copy and passes a pointer to that copy

0 commit comments

Comments
 (0)