mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 16:11:08 +03:00
MSVC: Port Rainer's upstream extern(C++) method ABI fixes
From https://github.com/dlang/dmd/pull/8330.
This commit is contained in:
parent
3ca43c51b8
commit
a133ffad56
21 changed files with 70 additions and 50 deletions
|
@ -602,7 +602,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!funcdecl.inferRetType && !Target.isReturnOnStack(f))
|
if (!funcdecl.inferRetType && !Target.isReturnOnStack(f, funcdecl.needThis()))
|
||||||
funcdecl.nrvo_can = 0;
|
funcdecl.nrvo_can = 0;
|
||||||
|
|
||||||
bool inferRef = (f.isref && (funcdecl.storage_class & STC.auto_));
|
bool inferRef = (f.isref && (funcdecl.storage_class & STC.auto_));
|
||||||
|
@ -656,7 +656,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
||||||
if (funcdecl.storage_class & STC.auto_)
|
if (funcdecl.storage_class & STC.auto_)
|
||||||
funcdecl.storage_class &= ~STC.auto_;
|
funcdecl.storage_class &= ~STC.auto_;
|
||||||
}
|
}
|
||||||
if (!Target.isReturnOnStack(f))
|
if (!Target.isReturnOnStack(f, funcdecl.needThis()))
|
||||||
funcdecl.nrvo_can = 0;
|
funcdecl.nrvo_can = 0;
|
||||||
|
|
||||||
if (funcdecl.fbody.isErrorStatement())
|
if (funcdecl.fbody.isErrorStatement())
|
||||||
|
|
12
dmd/target.d
12
dmd/target.d
|
@ -21,6 +21,7 @@ import dmd.dmodule;
|
||||||
import dmd.dstruct;
|
import dmd.dstruct;
|
||||||
import dmd.dsymbol;
|
import dmd.dsymbol;
|
||||||
import dmd.expression;
|
import dmd.expression;
|
||||||
|
import dmd.func;
|
||||||
import dmd.globals;
|
import dmd.globals;
|
||||||
import dmd.id;
|
import dmd.id;
|
||||||
import dmd.identifier;
|
import dmd.identifier;
|
||||||
|
@ -653,18 +654,21 @@ struct Target
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Determine return style of function - whether in registers or
|
||||||
|
* through a hidden pointer to the caller's stack.
|
||||||
* Params:
|
* Params:
|
||||||
* tf = function type to check
|
* tf = function type to check
|
||||||
|
* needsThis = true if the function type is for a non-static member function
|
||||||
* Returns:
|
* Returns:
|
||||||
* true if return value from function is on the stack
|
* true if return value from function is on the stack
|
||||||
*/
|
*/
|
||||||
version(IN_LLVM)
|
version(IN_LLVM)
|
||||||
{
|
{
|
||||||
extern (C++) static bool isReturnOnStack(TypeFunction tf);
|
extern (C++) static bool isReturnOnStack(TypeFunction tf, bool needsThis);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
extern (C++) static bool isReturnOnStack(TypeFunction tf)
|
extern (C++) static bool isReturnOnStack(TypeFunction tf, bool needsThis)
|
||||||
{
|
{
|
||||||
if (tf.isref)
|
if (tf.isref)
|
||||||
{
|
{
|
||||||
|
@ -691,6 +695,8 @@ struct Target
|
||||||
StructDeclaration sd = (cast(TypeStruct)tns).sym;
|
StructDeclaration sd = (cast(TypeStruct)tns).sym;
|
||||||
if (sd.ident == Id.__c_long_double)
|
if (sd.ident == Id.__c_long_double)
|
||||||
return false;
|
return false;
|
||||||
|
if (tf.linkage == LINK.cpp && needsThis)
|
||||||
|
return true;
|
||||||
if (!sd.isPOD() || sz > 8)
|
if (!sd.isPOD() || sz > 8)
|
||||||
return true;
|
return true;
|
||||||
if (sd.fields.dim == 0)
|
if (sd.fields.dim == 0)
|
||||||
|
@ -708,6 +714,8 @@ struct Target
|
||||||
StructDeclaration sd = (cast(TypeStruct)tb).sym;
|
StructDeclaration sd = (cast(TypeStruct)tb).sym;
|
||||||
if (sd.ident == Id.__c_long_double)
|
if (sd.ident == Id.__c_long_double)
|
||||||
return false;
|
return false;
|
||||||
|
if (tf.linkage == LINK.cpp && needsThis)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ struct Target
|
||||||
static Type *cppParameterType(Parameter *p);
|
static Type *cppParameterType(Parameter *p);
|
||||||
static LINK systemLinkage();
|
static LINK systemLinkage();
|
||||||
static TypeTuple *toArgTypes(Type *t);
|
static TypeTuple *toArgTypes(Type *t);
|
||||||
static bool isReturnOnStack(TypeFunction *tf);
|
static bool isReturnOnStack(TypeFunction *tf, bool needsThis);
|
||||||
static d_uns64 parameterSize(const Loc& loc, Type *t);
|
static d_uns64 parameterSize(const Loc& loc, Type *t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1074,7 +1074,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
|
||||||
return new ErrorExp();
|
return new ErrorExp();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool value = Target.isReturnOnStack(tf);
|
bool value = Target.isReturnOnStack(tf, fd && fd.needThis());
|
||||||
return new IntegerExp(e.loc, value, Type.tbool);
|
return new IntegerExp(e.loc, value, Type.tbool);
|
||||||
}
|
}
|
||||||
if (e.ident == Id.getFunctionVariadicStyle)
|
if (e.ident == Id.getFunctionVariadicStyle)
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct AArch64TargetABI : TargetABI {
|
||||||
CompositeToArray64 compositeToArray64;
|
CompositeToArray64 compositeToArray64;
|
||||||
IntegerRewrite integerRewrite;
|
IntegerRewrite integerRewrite;
|
||||||
|
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool) override {
|
||||||
if (tf->isref) {
|
if (tf->isref) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ struct ArmTargetABI : TargetABI {
|
||||||
CompositeToArray64 compositeToArray64;
|
CompositeToArray64 compositeToArray64;
|
||||||
IntegerRewrite integerRewrite;
|
IntegerRewrite integerRewrite;
|
||||||
|
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool) override {
|
||||||
// AAPCS 5.4 wants composites > 4-bytes returned by arg except for
|
// 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.
|
// Homogeneous Aggregates of up-to 4 float types (6.1.2.1) - an HFA.
|
||||||
// TODO: see if Tsarray should be candidate for HFA.
|
// TODO: see if Tsarray should be candidate for HFA.
|
||||||
|
|
|
@ -25,7 +25,7 @@ struct MIPS64TargetABI : TargetABI {
|
||||||
|
|
||||||
explicit MIPS64TargetABI(const bool Is64Bit) : Is64Bit(Is64Bit) {}
|
explicit MIPS64TargetABI(const bool Is64Bit) : Is64Bit(Is64Bit) {}
|
||||||
|
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool) override {
|
||||||
if (tf->isref) {
|
if (tf->isref) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ struct NVPTXTargetABI : TargetABI {
|
||||||
rewriteArgument(fty, *arg);
|
rewriteArgument(fty, *arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool) override {
|
||||||
return !tf->isref && DtoIsInMemoryOnly(tf->next);
|
return !tf->isref && DtoIsInMemoryOnly(tf->next);
|
||||||
}
|
}
|
||||||
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
|
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
|
||||||
|
|
|
@ -35,7 +35,7 @@ struct PPCTargetABI : TargetABI {
|
||||||
|
|
||||||
explicit PPCTargetABI(const bool Is64Bit) : Is64Bit(Is64Bit) {}
|
explicit PPCTargetABI(const bool Is64Bit) : Is64Bit(Is64Bit) {}
|
||||||
|
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool) override {
|
||||||
if (tf->isref) {
|
if (tf->isref) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct PPC64LETargetABI : TargetABI {
|
||||||
|
|
||||||
explicit PPC64LETargetABI() : hfaToArray(8) {}
|
explicit PPC64LETargetABI() : hfaToArray(8) {}
|
||||||
|
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool) override {
|
||||||
if (tf->isref) {
|
if (tf->isref) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ struct SPIRVTargetABI : TargetABI {
|
||||||
rewriteArgument(fty, *arg);
|
rewriteArgument(fty, *arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool) override {
|
||||||
return !tf->isref && DtoIsInMemoryOnly(tf->next);
|
return !tf->isref && DtoIsInMemoryOnly(tf->next);
|
||||||
}
|
}
|
||||||
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
|
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
|
||||||
|
|
|
@ -104,16 +104,23 @@ public:
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool needsThis) override {
|
||||||
if (tf->isref)
|
if (tf->isref)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Type *rt = tf->next->toBasetype();
|
||||||
|
|
||||||
|
// for non-static member functions, MSVC++ enforces sret for all structs
|
||||||
|
if (isMSVC && tf->linkage == LINKcpp && needsThis && rt->ty == Tstruct &&
|
||||||
|
!isMagicCppStruct(rt)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// * all POD types of a power-of-2 size <= 8 bytes (incl. 2x32-bit cfloat)
|
// * all POD types of a power-of-2 size <= 8 bytes (incl. 2x32-bit cfloat)
|
||||||
// are returned in a register (RAX, or XMM0 for single float/ifloat/
|
// are returned in a register (RAX, or XMM0 for single float/ifloat/
|
||||||
// double/idouble)
|
// double/idouble)
|
||||||
// * 80-bit real/ireal are returned on the x87 stack
|
// * 80-bit real/ireal are returned on the x87 stack
|
||||||
// * all other types are returned via sret
|
// * all other types are returned via sret
|
||||||
Type *rt = tf->next->toBasetype();
|
|
||||||
return passPointerToHiddenCopy(rt, /*isReturnValue=*/true, tf->linkage);
|
return passPointerToHiddenCopy(rt, /*isReturnValue=*/true, tf->linkage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,7 @@ struct X86_64TargetABI : TargetABI {
|
||||||
ImplicitByvalRewrite byvalRewrite;
|
ImplicitByvalRewrite byvalRewrite;
|
||||||
IndirectByvalRewrite indirectByvalRewrite;
|
IndirectByvalRewrite indirectByvalRewrite;
|
||||||
|
|
||||||
bool returnInArg(TypeFunction *tf) override;
|
bool returnInArg(TypeFunction *tf, bool needsThis) override;
|
||||||
|
|
||||||
bool passByVal(TypeFunction *tf, Type *t) override;
|
bool passByVal(TypeFunction *tf, Type *t) override;
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ private:
|
||||||
// The public getter for abi.cpp
|
// The public getter for abi.cpp
|
||||||
TargetABI *getX86_64TargetABI() { return new X86_64TargetABI; }
|
TargetABI *getX86_64TargetABI() { return new X86_64TargetABI; }
|
||||||
|
|
||||||
bool X86_64TargetABI::returnInArg(TypeFunction *tf) {
|
bool X86_64TargetABI::returnInArg(TypeFunction *tf, bool) {
|
||||||
if (tf->isref) {
|
if (tf->isref) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct X86TargetABI : TargetABI {
|
||||||
case LINKobjc:
|
case LINKobjc:
|
||||||
return llvm::CallingConv::C;
|
return llvm::CallingConv::C;
|
||||||
case LINKcpp:
|
case LINKcpp:
|
||||||
return isMSVC && fdecl && fdecl->isThis()
|
return isMSVC && fdecl && fdecl->needThis()
|
||||||
? llvm::CallingConv::X86_ThisCall
|
? llvm::CallingConv::X86_ThisCall
|
||||||
: llvm::CallingConv::C;
|
: llvm::CallingConv::C;
|
||||||
case LINKd:
|
case LINKd:
|
||||||
|
@ -83,7 +83,7 @@ struct X86TargetABI : TargetABI {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool needsThis) override {
|
||||||
if (tf->isref)
|
if (tf->isref)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -109,8 +109,15 @@ struct X86TargetABI : TargetABI {
|
||||||
if (!externD && !returnStructsInRegs)
|
if (!externD && !returnStructsInRegs)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
const bool isMSVCpp = isMSVC && tf->linkage == LINKcpp;
|
||||||
|
|
||||||
|
// for non-static member functions, MSVC++ enforces sret for all structs
|
||||||
|
if (isMSVCpp && needsThis && rt->ty == Tstruct) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// force sret for non-POD structs
|
// force sret for non-POD structs
|
||||||
const bool excludeStructsWithCtor = (isMSVC && tf->linkage == LINKcpp);
|
const bool excludeStructsWithCtor = isMSVCpp;
|
||||||
if (!isPOD(rt, excludeStructsWithCtor))
|
if (!isPOD(rt, excludeStructsWithCtor))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -297,7 +297,7 @@ const char *TargetABI::objcMsgSendFunc(Type *ret, IrFuncTy &fty) {
|
||||||
|
|
||||||
// Some reasonable defaults for when we don't know what ABI to use.
|
// Some reasonable defaults for when we don't know what ABI to use.
|
||||||
struct UnknownTargetABI : TargetABI {
|
struct UnknownTargetABI : TargetABI {
|
||||||
bool returnInArg(TypeFunction *tf) override {
|
bool returnInArg(TypeFunction *tf, bool) override {
|
||||||
if (tf->isref) {
|
if (tf->isref) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -361,7 +361,7 @@ TargetABI *TargetABI::getTarget() {
|
||||||
struct IntrinsicABI : TargetABI {
|
struct IntrinsicABI : TargetABI {
|
||||||
RemoveStructPadding remove_padding;
|
RemoveStructPadding remove_padding;
|
||||||
|
|
||||||
bool returnInArg(TypeFunction *tf) override { return false; }
|
bool returnInArg(TypeFunction *, bool) override { return false; }
|
||||||
|
|
||||||
bool passByVal(TypeFunction *, Type *t) override { return false; }
|
bool passByVal(TypeFunction *, Type *t) override { return false; }
|
||||||
|
|
||||||
|
|
|
@ -120,13 +120,15 @@ struct TargetABI {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the D function uses sret (struct return).
|
/// Returns true if the D function uses sret (struct return).
|
||||||
|
/// `needsThis` is true if the function type is for a non-static member
|
||||||
|
/// function.
|
||||||
///
|
///
|
||||||
/// A LL sret function doesn't really return a struct (in fact, it returns
|
/// A LL sret function doesn't really return a struct (in fact, it returns
|
||||||
/// void); it merely just sets a struct which has been pre-allocated by the
|
/// void); it merely just sets a struct which has been pre-allocated by the
|
||||||
/// caller.
|
/// caller.
|
||||||
/// The address is passed as additional function parameter using the StructRet
|
/// The address is passed as additional function parameter using the StructRet
|
||||||
/// attribute.
|
/// attribute.
|
||||||
virtual bool returnInArg(TypeFunction *tf) = 0;
|
virtual bool returnInArg(TypeFunction *tf, bool needsThis) = 0;
|
||||||
|
|
||||||
/// Returns true if the D type is passed using the LLVM ByVal attribute.
|
/// Returns true if the D type is passed using the LLVM ByVal attribute.
|
||||||
///
|
///
|
||||||
|
|
|
@ -57,8 +57,7 @@ static bool isMainFunction(FuncDeclaration *fd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
Type *nesttype, bool isMain, bool isCtor,
|
Type *nesttype, FuncDeclaration *fd) {
|
||||||
bool isIntrinsic, bool hasSel) {
|
|
||||||
IF_LOG Logger::println("DtoFunctionType(%s)", type->toChars());
|
IF_LOG Logger::println("DtoFunctionType(%s)", type->toChars());
|
||||||
LOG_SCOPE
|
LOG_SCOPE
|
||||||
|
|
||||||
|
@ -73,7 +72,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
return irFty.funcType;
|
return irFty.funcType;
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetABI *abi = (isIntrinsic ? TargetABI::getIntrinsic() : gABI);
|
TargetABI *abi = fd && DtoIsIntrinsic(fd) ? TargetABI::getIntrinsic() : gABI;
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -82,6 +81,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
// 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;
|
||||||
|
|
||||||
|
const bool isMain = fd && isMainFunction(fd);
|
||||||
if (isMain) {
|
if (isMain) {
|
||||||
// D and C main functions always return i32, even if declared as returning
|
// D and C main functions always return i32, even if declared as returning
|
||||||
// void.
|
// void.
|
||||||
|
@ -91,7 +91,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
const bool byref = f->isref && rt->toBasetype()->ty != Tvoid;
|
const bool byref = f->isref && rt->toBasetype()->ty != Tvoid;
|
||||||
AttrBuilder attrs;
|
AttrBuilder attrs;
|
||||||
|
|
||||||
if (abi->returnInArg(f)) {
|
if (abi->returnInArg(f, fd && fd->needThis())) {
|
||||||
// sret return
|
// sret return
|
||||||
newIrFty.arg_sret = new IrFuncTyArg(
|
newIrFty.arg_sret = new IrFuncTyArg(
|
||||||
rt, true,
|
rt, true,
|
||||||
|
@ -112,7 +112,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
// Add the this pointer for member functions
|
// Add the this pointer for member functions
|
||||||
AttrBuilder attrs;
|
AttrBuilder attrs;
|
||||||
attrs.add(LLAttribute::NonNull);
|
attrs.add(LLAttribute::NonNull);
|
||||||
if (isCtor) {
|
if (fd && fd->isCtorDeclaration()) {
|
||||||
attrs.add(LLAttribute::Returned);
|
attrs.add(LLAttribute::Returned);
|
||||||
}
|
}
|
||||||
newIrFty.arg_this =
|
newIrFty.arg_this =
|
||||||
|
@ -126,7 +126,15 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
++nextLLArgIdx;
|
++nextLLArgIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasSel) {
|
bool hasObjCSelector = false;
|
||||||
|
if (fd && fd->linkage == LINKobjc && thistype) {
|
||||||
|
if (fd->selector) {
|
||||||
|
hasObjCSelector = true;
|
||||||
|
} else if (fd->parent->isClassDeclaration()) {
|
||||||
|
fd->error("Objective-C `@selector` is missing");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasObjCSelector) {
|
||||||
// TODO: make arg_objcselector to match dmd type
|
// TODO: make arg_objcselector to match dmd type
|
||||||
newIrFty.arg_objcSelector = new IrFuncTyArg(Type::tvoidptr, false);
|
newIrFty.arg_objcSelector = new IrFuncTyArg(Type::tvoidptr, false);
|
||||||
++nextLLArgIdx;
|
++nextLLArgIdx;
|
||||||
|
@ -272,7 +280,6 @@ llvm::FunctionType *DtoFunctionType(FuncDeclaration *fdecl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *dthis = nullptr, *dnest = nullptr;
|
Type *dthis = nullptr, *dnest = nullptr;
|
||||||
bool hasSel = false;
|
|
||||||
|
|
||||||
if (fdecl->ident == Id::ensure || fdecl->ident == Id::require) {
|
if (fdecl->ident == Id::ensure || fdecl->ident == Id::require) {
|
||||||
FuncDeclaration *p = fdecl->parent->isFuncDeclaration();
|
FuncDeclaration *p = fdecl->parent->isFuncDeclaration();
|
||||||
|
@ -299,18 +306,8 @@ llvm::FunctionType *DtoFunctionType(FuncDeclaration *fdecl) {
|
||||||
dnest = Type::tvoid->pointerTo();
|
dnest = Type::tvoid->pointerTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fdecl->linkage == LINKobjc && dthis) {
|
LLFunctionType *functype = DtoFunctionType(
|
||||||
if (fdecl->selector) {
|
fdecl->type, getIrFunc(fdecl, true)->irFty, dthis, dnest, fdecl);
|
||||||
hasSel = true;
|
|
||||||
} else if (fdecl->parent->isClassDeclaration()) {
|
|
||||||
fdecl->error("Objective-C `@selector` is missing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LLFunctionType *functype =
|
|
||||||
DtoFunctionType(fdecl->type, getIrFunc(fdecl, true)->irFty, dthis, dnest,
|
|
||||||
isMainFunction(fdecl), fdecl->isCtorDeclaration(),
|
|
||||||
DtoIsIntrinsic(fdecl), hasSel);
|
|
||||||
|
|
||||||
return functype;
|
return functype;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,8 @@ class FunctionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::FunctionType *DtoFunctionType(Type *t, IrFuncTy &irFty, Type *thistype,
|
llvm::FunctionType *DtoFunctionType(Type *t, IrFuncTy &irFty, Type *thistype,
|
||||||
Type *nesttype, bool isMain = false,
|
Type *nesttype,
|
||||||
bool isCtor = false,
|
FuncDeclaration *fd = nullptr);
|
||||||
bool isIntrinsic = false,
|
|
||||||
bool hasSel = false);
|
|
||||||
llvm::FunctionType *DtoFunctionType(FuncDeclaration *fdecl);
|
llvm::FunctionType *DtoFunctionType(FuncDeclaration *fdecl);
|
||||||
|
|
||||||
void DtoResolveFunction(FuncDeclaration *fdecl);
|
void DtoResolveFunction(FuncDeclaration *fdecl);
|
||||||
|
|
|
@ -268,6 +268,6 @@ Expression *Target::paintAsType(Expression *e, Type *type) {
|
||||||
*/
|
*/
|
||||||
void Target::loadModule(Module *m) {}
|
void Target::loadModule(Module *m) {}
|
||||||
|
|
||||||
bool Target::isReturnOnStack(TypeFunction *tf) {
|
bool Target::isReturnOnStack(TypeFunction *tf, bool needsThis) {
|
||||||
return gABI->returnInArg(tf);
|
return gABI->returnInArg(tf, needsThis);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,8 @@ bool DtoIsInMemoryOnly(Type *type) {
|
||||||
bool DtoIsReturnInArg(CallExp *ce) {
|
bool DtoIsReturnInArg(CallExp *ce) {
|
||||||
Type *t = ce->e1->type->toBasetype();
|
Type *t = ce->e1->type->toBasetype();
|
||||||
if (t->ty == Tfunction && (!ce->f || !DtoIsIntrinsic(ce->f))) {
|
if (t->ty == Tfunction && (!ce->f || !DtoIsIntrinsic(ce->f))) {
|
||||||
return gABI->returnInArg(static_cast<TypeFunction *>(t));
|
return gABI->returnInArg(static_cast<TypeFunction *>(t),
|
||||||
|
ce->f && ce->f->needThis());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b0b28297a8befba66640c7b4462ecdc12c40c318
|
Subproject commit e1e05efb40fa122cae53faa6d8dff25b098c9203
|
Loading…
Add table
Add a link
Reference in a new issue