Skip to content

Commit

Permalink
TargetABI: Handle ref-returning function types *outside* TargetABI::r…
Browse files Browse the repository at this point in the history
…eturnInArg()
  • Loading branch information
kinke committed Dec 16, 2024
1 parent 898f7bd commit ece9e9e
Show file tree
Hide file tree
Showing 15 changed files with 11 additions and 49 deletions.
4 changes: 0 additions & 4 deletions gen/abi/aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ struct AArch64TargetABI : TargetABI {
AArch64TargetABI() {}

bool returnInArg(TypeFunction *tf, bool) override {
if (tf->isref()) {
return false;
}

Type *rt = tf->next->toBasetype();
if (rt->ty == TY::Tstruct || rt->ty == TY::Tsarray) {
auto argTypes = getArgTypes(rt);
Expand Down
3 changes: 0 additions & 3 deletions gen/abi/abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,6 @@ llvm::CallingConv::ID TargetABI::callingConv(FuncDeclaration *fdecl) {
//////////////////////////////////////////////////////////////////////////////

bool TargetABI::returnInArg(TypeFunction *tf, bool needsThis) {
if (tf->isref())
return false;

// default: use sret for non-PODs or if a same-typed argument would be passed
// byval
Type *rt = tf->next->toBasetype();
Expand Down
2 changes: 0 additions & 2 deletions gen/abi/arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ struct ArmTargetABI : TargetABI {
// AAPCS 5.4 wants composites > 4-bytes returned by arg except for
// Homogeneous Aggregates of up-to 4 float types (6.1.2.1) - an HFA.
// TODO: see if Tsarray should be candidate for HFA.
if (tf->isref())
return false;
Type *rt = tf->next->toBasetype();

if (!isPOD(rt))
Expand Down
2 changes: 1 addition & 1 deletion gen/abi/nvptx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct NVPTXTargetABI : TargetABI {
return DtoIsInMemoryOnly(t) && isPOD(t) && size(t) > 64;
}
bool returnInArg(TypeFunction *tf, bool) override {
return !tf->isref() && DtoIsInMemoryOnly(tf->next);
return DtoIsInMemoryOnly(tf->next);
}
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
TargetABI::rewriteArgument(fty, arg);
Expand Down
4 changes: 0 additions & 4 deletions gen/abi/ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ struct PPCTargetABI : TargetABI {
explicit PPCTargetABI(const bool Is64Bit) : Is64Bit(Is64Bit) {}

bool returnInArg(TypeFunction *tf, bool) override {
if (tf->isref()) {
return false;
}

Type *rt = tf->next->toBasetype();

// The ABI specifies that aggregates of size 8 bytes or less are
Expand Down
3 changes: 0 additions & 3 deletions gen/abi/riscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,6 @@ struct RISCV64TargetABI : TargetABI {
return pointerTo(Type::tvoid);
}
bool returnInArg(TypeFunction *tf, bool) override {
if (tf->isref())
return false;

Type *rt = tf->next->toBasetype();
return !isPOD(rt) || size(rt) > 16;
}
Expand Down
2 changes: 0 additions & 2 deletions gen/abi/spirv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ struct SPIRVTargetABI : TargetABI {
return DtoIsInMemoryOnly(t) && isPOD(t) && size(t) > 64;
}
bool returnInArg(TypeFunction *tf, bool) override {
if (tf->isref())
return false;
Type *retty = tf->next->toBasetype();
if (retty->ty == TY::Tsarray)
return true;
Expand Down
3 changes: 0 additions & 3 deletions gen/abi/win64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,6 @@ struct Win64TargetABI : TargetABI {
}

bool returnInArg(TypeFunction *tf, bool needsThis) override {
if (tf->isref())
return false;

Type *rt = tf->next->toBasetype();

// for non-static member functions, MSVC++ enforces sret for all structs
Expand Down
4 changes: 0 additions & 4 deletions gen/abi/x86-64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,6 @@ struct X86_64TargetABI : TargetABI {
};

bool X86_64TargetABI::returnInArg(TypeFunction *tf, bool) {
if (tf->isref()) {
return false;
}

Type *rt = tf->next->toBasetype();

// x87 creal is returned on the x87 stack
Expand Down
3 changes: 0 additions & 3 deletions gen/abi/x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,6 @@ struct X86TargetABI : TargetABI {
}

bool returnInArg(TypeFunction *tf, bool needsThis) override {
if (tf->isref())
return false;

Type *rt = getExtraLoweredReturnType(tf);
const bool externD = isExternD(tf);

Expand Down
2 changes: 1 addition & 1 deletion gen/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
const bool byref = f->isref() && rt->toBasetype()->ty != TY::Tvoid;
llvm::AttrBuilder attrs(getGlobalContext());

if (abi->returnInArg(f, fd && fd->needThis())) {
if (!byref && abi->returnInArg(f, fd && fd->needThis())) {
// sret return
llvm::AttrBuilder sretAttrs(getGlobalContext());
sretAttrs.addStructRetAttr(DtoType(rt));
Expand Down
2 changes: 1 addition & 1 deletion gen/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ TypeTuple *Target::toArgTypes(Type *t) {
}

bool Target::isReturnOnStack(TypeFunction *tf, bool needsThis) {
return gABI->returnInArg(tf, needsThis);
return !tf->isref() && gABI->returnInArg(tf, needsThis);
}

bool Target::preferPassByRef(Type *t) { return gABI->preferPassByRef(t); }
Expand Down
12 changes: 8 additions & 4 deletions gen/toir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2930,10 +2930,14 @@ bool toInPlaceConstruction(DLValue *lhs, Expression *rhs) {
// E.g., `T v = foo();` if the callee `T foo()` uses sret.
// In this case, pass `&v` as hidden sret argument, i.e., let `foo()`
// construct the return value directly into the lhs lvalue.
if (DtoIsReturnInArg(ce)) {
Logger::println("success, in-place-constructing sret return value");
ToElemVisitor::call(gIR, ce, DtoLVal(lhs));
return true;
if (!ce->f || !DtoIsIntrinsic(ce->f)) { // intrinsics don't use sret
if (auto tf = ce->e1->type->toBasetype()->isTypeFunction()) {
if (target.isReturnOnStack(tf, ce->f && ce->f->needThis())) {
Logger::println("success, in-place-constructing sret return value");
ToElemVisitor::call(gIR, ce, DtoLVal(lhs));
return true;
}
}
}

// detect <structliteral | temporary>.ctor(args)
Expand Down
9 changes: 0 additions & 9 deletions gen/tollvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,6 @@ bool DtoIsInMemoryOnly(Type *type) {
return (t == TY::Tstruct || t == TY::Tsarray);
}

bool DtoIsReturnInArg(CallExp *ce) {
Type *t = ce->e1->type->toBasetype();
if (t->ty == TY::Tfunction && (!ce->f || !DtoIsIntrinsic(ce->f))) {
return gABI->returnInArg(static_cast<TypeFunction *>(t),
ce->f && ce->f->needThis());
}
return false;
}

void DtoAddExtendAttr(Type *type, llvm::AttrBuilder &attrs) {
type = type->toBasetype();
if (type->isintegral() && type->ty != TY::Tvector && size(type) <= 2) {
Expand Down
5 changes: 0 additions & 5 deletions gen/tollvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ LLType *stripAddrSpaces(LLType *v);
// memory, referencing all values via LL pointers (structs and static arrays).
bool DtoIsInMemoryOnly(Type *type);

// Returns true if the callee uses sret (struct return).
// In that case, the caller needs to allocate the return value and pass its
// address as additional parameter to the callee, which will set it up.
bool DtoIsReturnInArg(CallExp *ce);

// Adds an appropriate attribute if the type should be zero or sign extended.
void DtoAddExtendAttr(Type *type, llvm::AttrBuilder &attrs);

Expand Down

0 comments on commit ece9e9e

Please sign in to comment.