Skip to content

Commit

Permalink
TargetABI: Add base rewriteFunctionType() implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
kinke committed Dec 8, 2024
1 parent dd44cfa commit 24825ce
Show file tree
Hide file tree
Showing 13 changed files with 38 additions and 177 deletions.
15 changes: 3 additions & 12 deletions gen/abi/aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,7 @@ struct AArch64TargetABI : TargetABI {
bool passByVal(TypeFunction *, Type *) override { return false; }

void rewriteFunctionType(IrFuncTy &fty) override {
if (!skipReturnValueRewrite(fty)) {
rewriteArgument(fty, *fty.ret, /*isReturnVal=*/true);
}

for (auto arg : fty.args) {
if (!arg->byref)
rewriteArgument(fty, *arg, /*isReturnVal=*/false);
}
TargetABI::rewriteFunctionType(fty);

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

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
return rewriteArgument(fty, arg, /*isReturnVal=*/false);
}

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg, bool isReturnVal) {
Type *t = arg.type->toBasetype();

if (!isAggregate(t))
return;

const bool isReturnVal = &arg == fty.ret;

// compiler magic: pass va_list args implicitly by reference
if (!isReturnVal && isAAPCS64VaList(t)) {
arg.byref = true;
Expand Down
40 changes: 10 additions & 30 deletions gen/abi/abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,16 @@ bool TargetABI::preferPassByRef(Type *t) {

//////////////////////////////////////////////////////////////////////////////

void TargetABI::rewriteFunctionType(IrFuncTy &fty) {
if (!skipReturnValueRewrite(fty))
rewriteArgument(fty, *fty.ret);

for (auto arg : fty.args) {
if (!arg->byref)
rewriteArgument(fty, *arg);
}
}

void TargetABI::rewriteVarargs(IrFuncTy &fty,
std::vector<IrFuncTyArg *> &args) {
for (auto arg : args) {
Expand Down Expand Up @@ -231,10 +241,6 @@ struct UnknownTargetABI : TargetABI {
bool passByVal(TypeFunction *, Type *t) override {
return DtoIsInMemoryOnly(t);
}

void rewriteFunctionType(IrFuncTy &) override {
// why?
}
};

//////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -305,32 +311,6 @@ struct IntrinsicABI : TargetABI {
remove_padding.applyTo(arg, abiTy);
}
}

void rewriteFunctionType(IrFuncTy &fty) override {
if (!fty.arg_sret) {
Type *rt = fty.ret->type->toBasetype();
if (rt->ty == TY::Tstruct) {
Logger::println("Intrinsic ABI: Transforming return type");
rewriteArgument(fty, *fty.ret);
}
}

Logger::println("Intrinsic ABI: Transforming arguments");
LOG_SCOPE;

for (auto arg : fty.args) {
IF_LOG Logger::cout() << "Arg: " << arg->type->toChars() << '\n';

// Arguments that are in memory are of no interest to us.
if (arg->byref) {
continue;
}

rewriteArgument(fty, *arg);

IF_LOG Logger::cout() << "New arg type: " << *arg->ltype << '\n';
}
}
};

TargetABI *TargetABI::getIntrinsic() {
Expand Down
2 changes: 1 addition & 1 deletion gen/abi/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ struct TargetABI {
virtual bool passThisBeforeSret(TypeFunction *tf) { return false; }

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

Expand Down
22 changes: 4 additions & 18 deletions gen/abi/arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,6 @@ struct ArmTargetABI : TargetABI {
// problem is better understood.
}

void rewriteFunctionType(IrFuncTy &fty) override {
Type *retTy = fty.ret->type->toBasetype();
if (!fty.ret->byref && retTy->ty == TY::Tstruct) {
// Rewrite HFAs only because union HFAs are turned into IR types that are
// non-HFA and messes up register selection
if (isHFVA(retTy, hfvaToArray.maxElements, &fty.ret->ltype)) {
hfvaToArray.applyTo(*fty.ret, fty.ret->ltype);
} else {
integerRewrite.applyTo(*fty.ret);
}
}

for (auto arg : fty.args) {
if (!arg->byref)
rewriteArgument(fty, *arg);
}
}

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
// structs and arrays need rewrite as i32 arrays. This keeps data layout
// unchanged when passed in registers r0-r3 and is necessary to match C ABI
Expand All @@ -95,6 +77,8 @@ struct ArmTargetABI : TargetABI {
// r0, where before it consumed r0-r3.
Type *ty = arg.type->toBasetype();

const bool isReturnValue = &arg == fty.ret;

// TODO: want to also rewrite Tsarray as i32 arrays, but sometimes
// llvm selects an aligned ldrd instruction even though the ptr is
// unaligned (e.g. walking through members of array char[5][]).
Expand All @@ -104,6 +88,8 @@ struct ArmTargetABI : TargetABI {
// non-HFA and messes up register selection
if (isHFVA(ty, hfvaToArray.maxElements, &arg.ltype)) {
hfvaToArray.applyTo(arg, arg.ltype);
} else if (isReturnValue) {
integerRewrite.applyTo(arg);
} else if (DtoAlignment(ty) <= 4) {
compositeToArray32.applyTo(arg);
} else {
Expand Down
29 changes: 8 additions & 21 deletions gen/abi/loongarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,35 +136,22 @@ struct LoongArch64TargetABI : TargetABI {
return size(t) > 16;
}

void rewriteFunctionType(IrFuncTy &fty) override {
if (!skipReturnValueRewrite(fty)) {
if (requireHardfloatRewrite(fty.ret->type)) {
// rewrite here because we should not apply this to variadic arguments
hardfloatRewrite.applyTo(*fty.ret);
} else {
rewriteArgument(fty, *fty.ret);
}
}

for (auto arg : fty.args) {
if (!arg->byref) {
if (requireHardfloatRewrite(arg->type)) {
// rewrite here because we should not apply this to variadic arguments
hardfloatRewrite.applyTo(*arg);
} else {
rewriteArgument(fty, *arg);
}
}
}
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
rewriteArgument(fty, arg, /*isVararg=*/ false);
}

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg, bool isVararg) {
if (!isPOD(arg.type)) {
// non-PODs should be passed in memory
indirectByvalRewrite.applyTo(arg);
return;
}

if (!isVararg && requireHardfloatRewrite(arg.type)) {
hardfloatRewrite.applyTo(arg);
return;
}

Type *ty = arg.type->toBasetype();
if (ty->isintegral() && (ty->ty == TY::Tint32 || ty->ty == TY::Tuns32 ||
ty->ty == TY::Tdchar)) {
Expand Down
12 changes: 0 additions & 12 deletions gen/abi/mips64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,6 @@ struct MIPS64TargetABI : TargetABI {
return ty == TY::Tstruct || ty == TY::Tsarray;
}

void rewriteFunctionType(IrFuncTy &fty) override {
if (!fty.ret->byref) {
rewriteArgument(fty, *fty.ret);
}

for (auto arg : fty.args) {
if (!arg->byref) {
rewriteArgument(fty, *arg);
}
}
}

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
// FIXME
}
Expand Down
6 changes: 0 additions & 6 deletions gen/abi/nvptx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ struct NVPTXTargetABI : TargetABI {
t = t->toBasetype();
return ((t->ty == TY::Tsarray || t->ty == TY::Tstruct) && size(t) > 64);
}
void rewriteFunctionType(IrFuncTy &fty) override {
for (auto arg : fty.args) {
if (!arg->byref)
rewriteArgument(fty, *arg);
}
}
bool returnInArg(TypeFunction *tf, bool) override {
return !tf->isref() && DtoIsInMemoryOnly(tf->next);
}
Expand Down
14 changes: 0 additions & 14 deletions gen/abi/ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,6 @@ struct PPCTargetABI : TargetABI {
(!Is64Bit || size(t) > 64);
}

void rewriteFunctionType(IrFuncTy &fty) override {
// return value
if (!fty.ret->byref) {
rewriteArgument(fty, *fty.ret);
}

// explicit parameters
for (auto arg : fty.args) {
if (!arg->byref) {
rewriteArgument(fty, *arg);
}
}
}

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
Type *ty = arg.type->toBasetype();

Expand Down
14 changes: 0 additions & 14 deletions gen/abi/ppc64le.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,6 @@ struct PPC64LETargetABI : TargetABI {
!isHFVA(t, hfvaToArray.maxElements));
}

void rewriteFunctionType(IrFuncTy &fty) override {
// return value
if (!fty.ret->byref) {
rewriteArgument(fty, *fty.ret);
}

// explicit parameters
for (auto arg : fty.args) {
if (!arg->byref) {
rewriteArgument(fty, *arg);
}
}
}

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
Type *ty = arg.type->toBasetype();
if (ty->ty == TY::Tstruct || ty->ty == TY::Tsarray) {
Expand Down
32 changes: 11 additions & 21 deletions gen/abi/riscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,32 +182,22 @@ struct RISCV64TargetABI : TargetABI {
}
return size(t) > 16;
}
void rewriteFunctionType(IrFuncTy &fty) override {
if (!fty.ret->byref) {
if (!skipReturnValueRewrite(fty)) {
if (!fty.ret->byref && isPOD(fty.ret->type) &&
requireHardfloatRewrite(fty.ret->type)) {
// rewrite here because we should not apply this to variadic arguments
hardfloatRewrite.applyTo(*fty.ret);
} else {
rewriteArgument(fty, *fty.ret);
}
}
}

for (auto arg : fty.args) {
if (!arg->byref && isPOD(arg->type) &&
requireHardfloatRewrite(arg->type)) {
// rewrite here because we should not apply this to variadic arguments
hardfloatRewrite.applyTo(*arg);
} else {
rewriteArgument(fty, *arg);
}
void rewriteVarargs(IrFuncTy &fty,
std::vector<IrFuncTyArg *> &args) override {
for (auto arg : args) {
if (!arg->byref)
rewriteArgument(fty, *arg, /*isVararg=*/true);
}
}

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
if (arg.byref) {
rewriteArgument(fty, arg, /*isVararg=*/false);
}

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg, bool isVararg) {
if (!isVararg && isPOD(arg.type) && requireHardfloatRewrite(arg.type)) {
hardfloatRewrite.applyTo(arg);
return;
}

Expand Down
8 changes: 0 additions & 8 deletions gen/abi/spirv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,6 @@ struct SPIRVTargetABI : TargetABI {
t = t->toBasetype();
return ((t->ty == TY::Tsarray || t->ty == TY::Tstruct) && size(t) > 64);
}
void rewriteFunctionType(IrFuncTy &fty) override {
for (auto arg : fty.args) {
if (!arg->byref)
rewriteArgument(fty, *arg);
}
if (!skipReturnValueRewrite(fty))
rewriteArgument(fty, *fty.ret);
}
bool returnInArg(TypeFunction *tf, bool) override {
if (tf->isref())
return false;
Expand Down
2 changes: 0 additions & 2 deletions gen/abi/wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ struct WasmTargetABI : TargetABI {
bool passByVal(TypeFunction *, Type *t) override {
return DtoIsInMemoryOnly(t) && !isDirectlyPassedAggregate(t);
}

void rewriteFunctionType(IrFuncTy &) override {}
};

// The public getter for abi.cpp.
Expand Down
19 changes: 1 addition & 18 deletions gen/abi/win64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,6 @@ struct Win64TargetABI : TargetABI {
return tf->linkage == LINK::cpp;
}

void rewriteFunctionType(IrFuncTy &fty) override {
// return value
if (!skipReturnValueRewrite(fty)) {
rewrite(fty, *fty.ret, /*isReturnValue=*/true);
}

// explicit parameters
for (auto arg : fty.args) {
if (!arg->byref) {
rewriteArgument(fty, *arg);
}
}
}

void rewriteVarargs(IrFuncTy &fty,
std::vector<IrFuncTyArg *> &args) override {
for (auto arg : args) {
Expand All @@ -183,12 +169,9 @@ struct Win64TargetABI : TargetABI {
}

void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
rewrite(fty, arg, /*isReturnValue=*/false);
}

void rewrite(IrFuncTy &fty, IrFuncTyArg &arg, bool isReturnValue) {
Type *t = arg.type->toBasetype();
LLType *originalLType = arg.ltype;
const bool isReturnValue = &arg == fty.ret;

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

0 comments on commit 24825ce

Please sign in to comment.