diff --git a/gen/abi/aarch64.cpp b/gen/abi/aarch64.cpp index 2a9f58639e..144312ff07 100644 --- a/gen/abi/aarch64.cpp +++ b/gen/abi/aarch64.cpp @@ -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 @@ -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; diff --git a/gen/abi/abi.cpp b/gen/abi/abi.cpp index b034f65072..4050964041 100644 --- a/gen/abi/abi.cpp +++ b/gen/abi/abi.cpp @@ -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 &args) { for (auto arg : args) { @@ -231,10 +241,6 @@ struct UnknownTargetABI : TargetABI { bool passByVal(TypeFunction *, Type *t) override { return DtoIsInMemoryOnly(t); } - - void rewriteFunctionType(IrFuncTy &) override { - // why? - } }; ////////////////////////////////////////////////////////////////////////////// @@ -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() { diff --git a/gen/abi/abi.h b/gen/abi/abi.h index 3545fb531a..48a42e51bb 100644 --- a/gen/abi/abi.h +++ b/gen/abi/abi.h @@ -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 &args); virtual void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) {} diff --git a/gen/abi/arm.cpp b/gen/abi/arm.cpp index ed4c311a22..3b5ee7b58e 100644 --- a/gen/abi/arm.cpp +++ b/gen/abi/arm.cpp @@ -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 @@ -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][]). @@ -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 { diff --git a/gen/abi/loongarch64.cpp b/gen/abi/loongarch64.cpp index b27a7b89be..639a5d1f13 100644 --- a/gen/abi/loongarch64.cpp +++ b/gen/abi/loongarch64.cpp @@ -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)) { diff --git a/gen/abi/mips64.cpp b/gen/abi/mips64.cpp index 478f12ad58..84d42624d4 100644 --- a/gen/abi/mips64.cpp +++ b/gen/abi/mips64.cpp @@ -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 } diff --git a/gen/abi/nvptx.cpp b/gen/abi/nvptx.cpp index 7c4878aaea..e85b86db1f 100644 --- a/gen/abi/nvptx.cpp +++ b/gen/abi/nvptx.cpp @@ -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); } diff --git a/gen/abi/ppc.cpp b/gen/abi/ppc.cpp index 81b1c9ce1b..d2401b4425 100644 --- a/gen/abi/ppc.cpp +++ b/gen/abi/ppc.cpp @@ -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(); diff --git a/gen/abi/ppc64le.cpp b/gen/abi/ppc64le.cpp index 129e1719bc..f540f727d5 100644 --- a/gen/abi/ppc64le.cpp +++ b/gen/abi/ppc64le.cpp @@ -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) { diff --git a/gen/abi/riscv64.cpp b/gen/abi/riscv64.cpp index 158bfaeba2..cac1c2958a 100644 --- a/gen/abi/riscv64.cpp +++ b/gen/abi/riscv64.cpp @@ -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 &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; } diff --git a/gen/abi/spirv.cpp b/gen/abi/spirv.cpp index 1dd09f3cd8..22d5128a9b 100644 --- a/gen/abi/spirv.cpp +++ b/gen/abi/spirv.cpp @@ -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; diff --git a/gen/abi/wasm.cpp b/gen/abi/wasm.cpp index 52669a538d..5d5c44daa8 100644 --- a/gen/abi/wasm.cpp +++ b/gen/abi/wasm.cpp @@ -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. diff --git a/gen/abi/win64.cpp b/gen/abi/win64.cpp index 631aeb1088..3a1fdc8df2 100644 --- a/gen/abi/win64.cpp +++ b/gen/abi/win64.cpp @@ -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 &args) override { for (auto arg : args) { @@ -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