mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 08:30:47 +03:00
Store front-end D function type in IrFuncTy
As we do for IrFuncTyArg. We'll need access to the front-end linkage for the Posix ABIs too in order to implement indirect-by-value passing of non-PODs for `extern(C++)`.
This commit is contained in:
parent
c01dfc3db8
commit
92913d4c08
16 changed files with 51 additions and 38 deletions
|
@ -41,7 +41,7 @@ struct AArch64TargetABI : TargetABI {
|
||||||
(t->ty == Tstruct && t->size() > 16 && !isHFA((TypeStruct *)t));
|
(t->ty == Tstruct && t->size() > 16 && !isHFA((TypeStruct *)t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
Type *retTy = fty.ret->type->toBasetype();
|
Type *retTy = fty.ret->type->toBasetype();
|
||||||
if (!fty.ret->byref && retTy->ty == Tstruct) {
|
if (!fty.ret->byref && retTy->ty == Tstruct) {
|
||||||
// Rewrite HFAs only because union HFAs are turned into IR types that are
|
// Rewrite HFAs only because union HFAs are turned into IR types that are
|
||||||
|
@ -59,7 +59,8 @@ struct AArch64TargetABI : TargetABI {
|
||||||
}
|
}
|
||||||
|
|
||||||
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
||||||
if (tf->linkage == LINKd && tf->varargs != 1 && fty.args.size() > 1) {
|
if (fty.type->linkage == LINKd && fty.type->varargs != 1 &&
|
||||||
|
fty.args.size() > 1) {
|
||||||
fty.reverseParams = true;
|
fty.reverseParams = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ struct ArmTargetABI : TargetABI {
|
||||||
// problem is better understood.
|
// problem is better understood.
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
Type *retTy = fty.ret->type->toBasetype();
|
Type *retTy = fty.ret->type->toBasetype();
|
||||||
if (!fty.ret->byref && retTy->ty == Tstruct) {
|
if (!fty.ret->byref && retTy->ty == Tstruct) {
|
||||||
// Rewrite HFAs only because union HFAs are turned into IR types that are
|
// Rewrite HFAs only because union HFAs are turned into IR types that are
|
||||||
|
@ -86,7 +86,8 @@ struct ArmTargetABI : TargetABI {
|
||||||
}
|
}
|
||||||
|
|
||||||
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
||||||
if (tf->linkage == LINKd && tf->varargs != 1 && fty.args.size() > 1) {
|
if (fty.type->linkage == LINKd && fty.type->varargs != 1 &&
|
||||||
|
fty.args.size() > 1) {
|
||||||
fty.reverseParams = true;
|
fty.reverseParams = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct MIPS64TargetABI : TargetABI {
|
||||||
return ty == Tstruct || ty == Tsarray;
|
return ty == Tstruct || ty == Tsarray;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
if (!fty.ret->byref) {
|
if (!fty.ret->byref) {
|
||||||
rewriteArgument(fty, *fty.ret);
|
rewriteArgument(fty, *fty.ret);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,8 @@ struct MIPS64TargetABI : TargetABI {
|
||||||
}
|
}
|
||||||
|
|
||||||
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
||||||
if (tf->linkage == LINKd && tf->varargs != 1 && fty.args.size() > 1) {
|
if (fty.type->linkage == LINKd && fty.type->varargs != 1 &&
|
||||||
|
fty.args.size() > 1) {
|
||||||
fty.reverseParams = true;
|
fty.reverseParams = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct NVPTXTargetABI : TargetABI {
|
||||||
t = t->toBasetype();
|
t = t->toBasetype();
|
||||||
return ((t->ty == Tsarray || t->ty == Tstruct) && t->size() > 64);
|
return ((t->ty == Tsarray || t->ty == Tstruct) && t->size() > 64);
|
||||||
}
|
}
|
||||||
void rewriteFunctionType(TypeFunction *t, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
for (auto arg : fty.args) {
|
for (auto arg : fty.args) {
|
||||||
if (!arg->byref)
|
if (!arg->byref)
|
||||||
rewriteArgument(fty, *arg);
|
rewriteArgument(fty, *arg);
|
||||||
|
|
|
@ -58,7 +58,7 @@ struct PPCTargetABI : TargetABI {
|
||||||
(!Is64Bit || t->size() > 64);
|
(!Is64Bit || t->size() > 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
// return value
|
// return value
|
||||||
if (!fty.ret->byref) {
|
if (!fty.ret->byref) {
|
||||||
rewriteArgument(fty, *fty.ret);
|
rewriteArgument(fty, *fty.ret);
|
||||||
|
@ -72,7 +72,8 @@ struct PPCTargetABI : TargetABI {
|
||||||
}
|
}
|
||||||
|
|
||||||
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
||||||
if (tf->linkage == LINKd && tf->varargs != 1 && fty.args.size() > 1) {
|
if (fty.type->linkage == LINKd && fty.type->varargs != 1 &&
|
||||||
|
fty.args.size() > 1) {
|
||||||
fty.reverseParams = true;
|
fty.reverseParams = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct PPC64LETargetABI : TargetABI {
|
||||||
!isHFA((TypeStruct *)t, nullptr, 8));
|
!isHFA((TypeStruct *)t, nullptr, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
// return value
|
// return value
|
||||||
if (!fty.ret->byref) {
|
if (!fty.ret->byref) {
|
||||||
rewriteArgument(fty, *fty.ret);
|
rewriteArgument(fty, *fty.ret);
|
||||||
|
@ -61,7 +61,8 @@ struct PPC64LETargetABI : TargetABI {
|
||||||
}
|
}
|
||||||
|
|
||||||
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
||||||
if (tf->linkage == LINKd && tf->varargs != 1 && fty.args.size() > 1) {
|
if (fty.type->linkage == LINKd && fty.type->varargs != 1 &&
|
||||||
|
fty.args.size() > 1) {
|
||||||
fty.reverseParams = true;
|
fty.reverseParams = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct SPIRVTargetABI : TargetABI {
|
||||||
t = t->toBasetype();
|
t = t->toBasetype();
|
||||||
return ((t->ty == Tsarray || t->ty == Tstruct) && t->size() > 64);
|
return ((t->ty == Tsarray || t->ty == Tstruct) && t->size() > 64);
|
||||||
}
|
}
|
||||||
void rewriteFunctionType(TypeFunction *t, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
for (auto arg : fty.args) {
|
for (auto arg : fty.args) {
|
||||||
if (!arg->byref)
|
if (!arg->byref)
|
||||||
rewriteArgument(fty, *arg);
|
rewriteArgument(fty, *arg);
|
||||||
|
|
|
@ -80,10 +80,6 @@ private:
|
||||||
return isAggregate(t) && !canRewriteAsInt(t);
|
return isAggregate(t) && !canRewriteAsInt(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
LINK &getLinkage(IrFuncTy &fty) {
|
|
||||||
return reinterpret_cast<LINK &>(fty.tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Win64TargetABI()
|
Win64TargetABI()
|
||||||
: isMSVC(global.params.targetTriple->isWindowsMSVCEnvironment()) {}
|
: isMSVC(global.params.targetTriple->isWindowsMSVCEnvironment()) {}
|
||||||
|
@ -111,10 +107,7 @@ public:
|
||||||
return tf->linkage == LINKcpp;
|
return tf->linkage == LINKcpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
// store linkage in fty.tag as required by rewriteArgument() later
|
|
||||||
getLinkage(fty) = tf->linkage;
|
|
||||||
|
|
||||||
// return value
|
// return value
|
||||||
const auto rt = fty.ret->type->toBasetype();
|
const auto rt = fty.ret->type->toBasetype();
|
||||||
if (!fty.ret->byref && rt->ty != Tvoid) {
|
if (!fty.ret->byref && rt->ty != Tvoid) {
|
||||||
|
@ -129,7 +122,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
||||||
if (tf->linkage == LINKd && tf->varargs != 1 && fty.args.size() > 1) {
|
if (fty.type->linkage == LINKd && fty.type->varargs != 1 &&
|
||||||
|
fty.args.size() > 1) {
|
||||||
fty.reverseParams = true;
|
fty.reverseParams = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +149,7 @@ public:
|
||||||
Type *t = arg.type->toBasetype();
|
Type *t = arg.type->toBasetype();
|
||||||
LLType *originalLType = arg.ltype;
|
LLType *originalLType = arg.ltype;
|
||||||
|
|
||||||
if (passPointerToHiddenCopy(t, isReturnValue, getLinkage(fty))) {
|
if (passPointerToHiddenCopy(t, isReturnValue, fty.type->linkage)) {
|
||||||
// the caller allocates a hidden copy and passes a pointer to that copy
|
// the caller allocates a hidden copy and passes a pointer to that copy
|
||||||
byvalRewrite.applyTo(arg);
|
byvalRewrite.applyTo(arg);
|
||||||
} else if (isAggregate(t) && canRewriteAsInt(t) && !isMagicCppStruct(t)) {
|
} else if (isAggregate(t) && canRewriteAsInt(t) && !isMagicCppStruct(t)) {
|
||||||
|
|
|
@ -222,7 +222,7 @@ struct X86_64TargetABI : TargetABI {
|
||||||
|
|
||||||
bool passByVal(Type *t) override;
|
bool passByVal(Type *t) override;
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override;
|
void rewriteFunctionType(IrFuncTy &fty) override;
|
||||||
void rewriteVarargs(IrFuncTy &fty, std::vector<IrFuncTyArg *> &args) override;
|
void rewriteVarargs(IrFuncTy &fty, std::vector<IrFuncTyArg *> &args) override;
|
||||||
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override;
|
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override;
|
||||||
void rewriteArgument(IrFuncTyArg &arg, RegCount ®Count);
|
void rewriteArgument(IrFuncTyArg &arg, RegCount ®Count);
|
||||||
|
@ -289,7 +289,7 @@ void X86_64TargetABI::rewriteArgument(IrFuncTyArg &arg, RegCount ®Count) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86_64TargetABI::rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) {
|
void X86_64TargetABI::rewriteFunctionType(IrFuncTy &fty) {
|
||||||
RegCount ®Count = getRegCount(fty);
|
RegCount ®Count = getRegCount(fty);
|
||||||
regCount = RegCount(); // initialize
|
regCount = RegCount(); // initialize
|
||||||
|
|
||||||
|
@ -320,7 +320,8 @@ void X86_64TargetABI::rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) {
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
// extern(D): reverse parameter order for non variadics, for DMD-compliance
|
||||||
if (tf->linkage == LINKd && tf->varargs != 1 && fty.args.size() > 1) {
|
if (fty.type->linkage == LINKd && fty.type->varargs != 1 &&
|
||||||
|
fty.args.size() > 1) {
|
||||||
fty.reverseParams = true;
|
fty.reverseParams = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,12 +123,12 @@ struct X86TargetABI : TargetABI {
|
||||||
return DtoIsInMemoryOnly(t);
|
return DtoIsInMemoryOnly(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
const bool externD = (tf->linkage == LINKd && tf->varargs != 1);
|
const bool externD = (fty.type->linkage == LINKd && fty.type->varargs != 1);
|
||||||
|
|
||||||
// return value:
|
// return value:
|
||||||
if (!fty.ret->byref) {
|
if (!fty.ret->byref) {
|
||||||
Type *rt = tf->next->toBasetype(); // for sret, rt == void
|
Type *rt = fty.type->next->toBasetype(); // for sret, rt == void
|
||||||
if (isAggregate(rt) && !isMagicCppStruct(rt) && canRewriteAsInt(rt) &&
|
if (isAggregate(rt) && !isMagicCppStruct(rt) && canRewriteAsInt(rt) &&
|
||||||
// don't rewrite cfloat for extern(D)
|
// don't rewrite cfloat for extern(D)
|
||||||
!(externD && rt->ty == Tcomplex32)) {
|
!(externD && rt->ty == Tcomplex32)) {
|
||||||
|
|
|
@ -304,7 +304,7 @@ struct UnknownTargetABI : TargetABI {
|
||||||
|
|
||||||
bool passByVal(Type *t) override { return t->toBasetype()->ty == Tstruct; }
|
bool passByVal(Type *t) override { return t->toBasetype()->ty == Tstruct; }
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *t, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &) override {
|
||||||
// why?
|
// why?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -369,7 +369,7 @@ struct IntrinsicABI : TargetABI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override {
|
void rewriteFunctionType(IrFuncTy &fty) override {
|
||||||
if (!fty.arg_sret) {
|
if (!fty.arg_sret) {
|
||||||
Type *rt = fty.ret->type->toBasetype();
|
Type *rt = fty.ret->type->toBasetype();
|
||||||
if (rt->ty == Tstruct) {
|
if (rt->ty == Tstruct) {
|
||||||
|
|
|
@ -144,7 +144,7 @@ struct TargetABI {
|
||||||
virtual bool passThisBeforeSret(TypeFunction *tf) { return false; }
|
virtual bool passThisBeforeSret(TypeFunction *tf) { return false; }
|
||||||
|
|
||||||
/// Called to give ABI the chance to rewrite the types
|
/// Called to give ABI the chance to rewrite the types
|
||||||
virtual void rewriteFunctionType(TypeFunction *t, IrFuncTy &fty) = 0;
|
virtual void rewriteFunctionType(IrFuncTy &fty) = 0;
|
||||||
virtual void rewriteVarargs(IrFuncTy &fty, std::vector<IrFuncTyArg *> &args);
|
virtual void rewriteVarargs(IrFuncTy &fty, std::vector<IrFuncTyArg *> &args);
|
||||||
virtual void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) {}
|
virtual void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) {}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
|
|
||||||
// Do not modify irFty yet; this function may be called recursively if any
|
// Do not modify irFty yet; this function may be called recursively if any
|
||||||
// of the argument types refer to this type.
|
// of the argument types refer to this type.
|
||||||
IrFuncTy newIrFty;
|
IrFuncTy newIrFty(f);
|
||||||
|
|
||||||
// The index of the next argument on the LLVM level.
|
// The index of the next argument on the LLVM level.
|
||||||
unsigned nextLLArgIdx = 0;
|
unsigned nextLLArgIdx = 0;
|
||||||
|
@ -188,7 +188,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
}
|
}
|
||||||
|
|
||||||
// let the ABI rewrite the types as necessary
|
// let the ABI rewrite the types as necessary
|
||||||
abi->rewriteFunctionType(f, newIrFty);
|
abi->rewriteFunctionType(newIrFty);
|
||||||
|
|
||||||
// Now we can modify irFty safely.
|
// Now we can modify irFty safely.
|
||||||
irFty = std::move(newIrFty);
|
irFty = std::move(newIrFty);
|
||||||
|
|
|
@ -16,12 +16,15 @@
|
||||||
#include "gen/tollvm.h"
|
#include "gen/tollvm.h"
|
||||||
#include "ir/irdsymbol.h"
|
#include "ir/irdsymbol.h"
|
||||||
|
|
||||||
IrFunction::IrFunction(FuncDeclaration *fd) : FMF(opts::defaultFMF) {
|
IrFunction::IrFunction(FuncDeclaration *fd)
|
||||||
|
: FMF(opts::defaultFMF), irFty(nullptr /*set immediately below*/) {
|
||||||
decl = fd;
|
decl = fd;
|
||||||
|
|
||||||
Type *t = fd->type->toBasetype();
|
Type *t = fd->type->toBasetype();
|
||||||
assert(t->ty == Tfunction);
|
assert(t->ty == Tfunction);
|
||||||
type = static_cast<TypeFunction *>(t);
|
type = static_cast<TypeFunction *>(t);
|
||||||
|
|
||||||
|
irFty.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrFunction::setNeverInline() {
|
void IrFunction::setNeverInline() {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
class DValue;
|
class DValue;
|
||||||
class Type;
|
class Type;
|
||||||
|
class TypeFunction;
|
||||||
struct ABIRewrite;
|
struct ABIRewrite;
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class Type;
|
class Type;
|
||||||
|
@ -83,6 +84,9 @@ struct IrFuncTyArg {
|
||||||
|
|
||||||
// represents a function type
|
// represents a function type
|
||||||
struct IrFuncTy {
|
struct IrFuncTy {
|
||||||
|
// D type
|
||||||
|
TypeFunction *type;
|
||||||
|
|
||||||
// The final LLVM type
|
// The final LLVM type
|
||||||
llvm::FunctionType *funcType = nullptr;
|
llvm::FunctionType *funcType = nullptr;
|
||||||
|
|
||||||
|
@ -116,6 +120,8 @@ struct IrFuncTy {
|
||||||
llvm::Value *getParamLVal(Type *dty, size_t idx, llvm::Value *val);
|
llvm::Value *getParamLVal(Type *dty, size_t idx, llvm::Value *val);
|
||||||
|
|
||||||
AttrSet getParamAttrs(bool passThisBeforeSret);
|
AttrSet getParamAttrs(bool passThisBeforeSret);
|
||||||
|
|
||||||
|
IrFuncTy(TypeFunction *tf) : type(tf) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,8 +23,10 @@ IrTypeFunction *IrTypeFunction::get(Type *dt) {
|
||||||
assert(!dt->ctype);
|
assert(!dt->ctype);
|
||||||
assert(dt->ty == Tfunction);
|
assert(dt->ty == Tfunction);
|
||||||
|
|
||||||
IrFuncTy irFty;
|
TypeFunction *tf = static_cast<TypeFunction *>(dt);
|
||||||
llvm::Type *lt = DtoFunctionType(dt, irFty, nullptr, nullptr);
|
|
||||||
|
IrFuncTy irFty(tf);
|
||||||
|
llvm::Type *lt = DtoFunctionType(tf, irFty, nullptr, nullptr);
|
||||||
|
|
||||||
// Could have already built the type as part of a struct forward reference,
|
// Could have already built the type as part of a struct forward reference,
|
||||||
// just as for pointers and arrays.
|
// just as for pointers and arrays.
|
||||||
|
@ -44,9 +46,11 @@ IrTypeDelegate *IrTypeDelegate::get(Type *t) {
|
||||||
assert(t->ty == Tdelegate);
|
assert(t->ty == Tdelegate);
|
||||||
assert(t->nextOf()->ty == Tfunction);
|
assert(t->nextOf()->ty == Tfunction);
|
||||||
|
|
||||||
IrFuncTy irFty;
|
TypeFunction *tf = static_cast<TypeFunction *>(t->nextOf());
|
||||||
|
|
||||||
|
IrFuncTy irFty(tf);
|
||||||
llvm::Type *ltf =
|
llvm::Type *ltf =
|
||||||
DtoFunctionType(t->nextOf(), irFty, nullptr, Type::tvoid->pointerTo());
|
DtoFunctionType(tf, irFty, nullptr, Type::tvoid->pointerTo());
|
||||||
llvm::Type *types[] = {getVoidPtrType(), getPtrToType(ltf)};
|
llvm::Type *types[] = {getVoidPtrType(), getPtrToType(ltf)};
|
||||||
LLStructType *lt = LLStructType::get(gIR->context(), types, false);
|
LLStructType *lt = LLStructType::get(gIR->context(), types, false);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue