Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: enable sret for dynamic arrays #901

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions gen/aa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue)
};

// call
llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_arraybounds");
gIR->CreateCallOrInvoke(errorfn, args);
LLVM_D_CallRuntimeFunction(loc, "_d_arraybounds", args);

// the function does not return
gIR->ir->CreateUnreachable();
Expand Down
6 changes: 1 addition & 5 deletions gen/abi-ppc64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,12 @@ struct PPC64TargetABI : TargetABI {
}
}

bool returnInArg(TypeFunction* tf)
bool returnInArg(Type* rt, LINK /*linkage*/)
{
if (tf->isref)
return false;

// Return structs and static arrays on the stack. The latter is needed
// because otherwise LLVM tries to actually return the array in a number
// of physical registers, which leads, depending on the target, to
// either horrendous codegen or backend crashes.
Type* rt = tf->next->toBasetype();
return (rt->ty == Tstruct || rt->ty == Tsarray);
}

Expand Down
11 changes: 3 additions & 8 deletions gen/abi-win64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct Win64TargetABI : TargetABI

llvm::CallingConv::ID callingConv(LINK l);

bool returnInArg(TypeFunction* tf);
bool returnInArg(Type* rt, LINK linkage);

bool passByVal(Type* t);

Expand Down Expand Up @@ -112,13 +112,8 @@ llvm::CallingConv::ID Win64TargetABI::callingConv(LINK l)
}
}

bool Win64TargetABI::returnInArg(TypeFunction* tf)
bool Win64TargetABI::returnInArg(Type* rt, LINK /*linkage*/)
{
if (tf->isref)
return false;

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

// * let LLVM return 80-bit real/ireal on the x87 stack, for DMD compliance
if (realIs80bits() && (rt->ty == Tfloat80 || rt->ty == Timaginary80))
return false;
Expand All @@ -128,7 +123,7 @@ bool Win64TargetABI::returnInArg(TypeFunction* tf)
// XMM0 for single float/ifloat/double/idouble)
// * all other types are returned via struct-return (sret)
return (rt->ty == Tstruct && !((TypeStruct*)rt)->sym->isPOD())
|| isPassedWithByvalSemantics(rt);
|| isPassedWithByvalSemantics(rt) || (rt->ty == Tarray);
}

bool Win64TargetABI::passByVal(Type* t)
Expand Down
8 changes: 2 additions & 6 deletions gen/abi-x86-64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ struct X86_64TargetABI : TargetABI {

llvm::CallingConv::ID callingConv(LINK l);

bool returnInArg(TypeFunction* tf);
bool returnInArg(Type* rt, LINK linkage);

bool passByVal(Type* t);

Expand Down Expand Up @@ -262,11 +262,7 @@ llvm::CallingConv::ID X86_64TargetABI::callingConv(LINK l) {
}
}

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

Type* rt = tf->next;
bool X86_64TargetABI::returnInArg(Type* rt, LINK /*linkage*/) {
return passByVal(rt);
}

Expand Down
15 changes: 15 additions & 0 deletions gen/abi-x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,21 @@ struct X86TargetABI : TargetABI
return (rt->ty == Tstruct || rt->ty == Tcomplex64 || rt->ty == Tcomplex80);
}

bool returnInArg(Type* rt, LINK linkage)
{
// D only returns structs on the stack
if (linkage == LINKd)
{
return rt->ty == Tstruct
|| rt->ty == Tsarray
;
}
// other ABI's follow C, which is cdouble and creal returned on the stack
// as well as structs
else
return (rt->ty == Tstruct || rt->ty == Tcomplex64 || rt->ty == Tcomplex80);
}

bool passByVal(Type* t)
{
return t->toBasetype()->ty == Tstruct || t->toBasetype()->ty == Tsarray;
Expand Down
21 changes: 16 additions & 5 deletions gen/abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ LLValue* ABIRewrite::loadFromMemory(LLValue* address, LLType* asType, const char

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

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

return returnInArg(tf->next->toBasetype(), tf->linkage);
}

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

void TargetABI::rewriteVarargs(IrFuncTy& fty, std::vector<IrFuncTyArg*>& args)
{
for (unsigned i = 0; i < args.size(); ++i)
Expand Down Expand Up @@ -159,16 +169,12 @@ struct UnknownTargetABI : TargetABI
}
}

bool returnInArg(TypeFunction* tf)
bool returnInArg(Type* rt, LINK /*linkage*/)
{
if (tf->isref)
return false;

// Return structs and static arrays on the stack. The latter is needed
// because otherwise LLVM tries to actually return the array in a number
// of physical registers, which leads, depending on the target, to
// either horrendous codegen or backend crashes.
Type* rt = tf->next->toBasetype();
return (rt->ty == Tstruct || rt->ty == Tsarray);
}

Expand Down Expand Up @@ -224,6 +230,11 @@ struct IntrinsicABI : TargetABI
return false;
}

bool returnInArg(Type* /*t*/, LINK /*linkage*/)
{
return false;
}

bool passByVal(Type* t)
{
return false;
Expand Down
3 changes: 2 additions & 1 deletion gen/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ struct TargetABI
/// Returns true if the function uses sret (struct return),
/// meaning that it gets a hidden pointer to a struct which has been pre-
/// allocated by the caller.
virtual bool returnInArg(TypeFunction* tf) = 0;
virtual bool returnInArg(TypeFunction* tf);
virtual bool returnInArg(Type* returntype, LINK linkage) = 0;

/// Returns true if the type is passed by value
virtual bool passByVal(Type* t) = 0;
Expand Down
Loading