diff --git a/gen/abi-x86.cpp b/gen/abi-x86.cpp index a2a241e215..f7734604b9 100644 --- a/gen/abi-x86.cpp +++ b/gen/abi-x86.cpp @@ -36,8 +36,6 @@ struct X86TargetABI : TargetABI return llvm::CallingConv::C; case LINKd: case LINKdefault: - return global.params.targetTriple.isOSWindows() ? - llvm::CallingConv::C : llvm::CallingConv::X86_StdCall; case LINKpascal: case LINKwindows: return llvm::CallingConv::X86_StdCall; @@ -46,6 +44,30 @@ struct X86TargetABI : TargetABI } } + std::string mangleForLLVM(llvm::StringRef name, LINK l) + { + switch (l) + { + case LINKc: + case LINKcpp: + case LINKintrinsic: + case LINKpascal: + case LINKwindows: + return name; + case LINKd: + case LINKdefault: + if (global.params.targetTriple.isOSWindows()) + { + // Prepend a 0x1 byte to keep LLVM from adding the usual + // "@" stdcall suffix. + return ("\1_" + name).str(); + } + return name; + default: + llvm_unreachable("Unhandled D linkage type."); + } + } + bool returnInArg(TypeFunction* tf) { #if DMDV2 diff --git a/gen/abi.h b/gen/abi.h index e79f20112a..21b2ae2302 100644 --- a/gen/abi.h +++ b/gen/abi.h @@ -60,7 +60,15 @@ struct TargetABI /// Returns the LLVM calling convention to be used for the given D linkage /// type on the target. - virtual llvm::CallingConv::ID callingConv(enum LINK l) = 0; + virtual llvm::CallingConv::ID callingConv(LINK l) = 0; + + /// Applies any rewrites that might be required to accurately reproduce the + /// passed function name on LLVM given a specific calling convention. + /// + /// Using this function at a stage where the name could be user-visible is + /// almost certainly a mistake; it is intended to e.g. prepend '\1' where + /// disabling the LLVM-internal name mangling/postprocessing is required. + virtual std::string mangleForLLVM(llvm::StringRef name, LINK l) { return name; } /// Called if a new function type is resolved virtual void newFunctionType(TypeFunction* tf) {} diff --git a/gen/functions.cpp b/gen/functions.cpp index fe353897db..d74d463647 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -741,48 +741,52 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) fdecl->ir.irFunc = new IrFunction(fdecl); } - // mangled name - const char* mangled_name; - if (fdecl->llvmInternal == LLVMintrinsic) - mangled_name = fdecl->intrinsicName.c_str(); - else - mangled_name = fdecl->mangle(); - LLFunction* vafunc = 0; if (fdecl->isVaIntrinsic()) vafunc = DtoDeclareVaFunction(fdecl); + // calling convention + LINK link = f->linkage; + if (vafunc || fdecl->llvmInternal == LLVMintrinsic +#if DMDV2 + // DMD treats _Dmain as having C calling convention and this has been + // hardcoded into druntime, even if the frontend type has D linkage. + // See Bugzilla issue 9028. + || fdecl->isMain() +#endif + ) + { + link = LINKc; + } + + // mangled name + std::string mangledName; + if (fdecl->llvmInternal == LLVMintrinsic) + mangledName = fdecl->intrinsicName; + else + mangledName = fdecl->mangle(); + mangledName = gABI->mangleForLLVM(mangledName, link); + // construct function LLFunctionType* functype = DtoFunctionType(fdecl); - LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name); + LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName); if (!func) { if(fdecl->llvmInternal == LLVMinline_ir) func = DtoInlineIRFunction(fdecl); else - func = LLFunction::Create(functype, DtoLinkage(fdecl), mangled_name, gIR->module); + func = LLFunction::Create(functype, DtoLinkage(fdecl), mangledName, gIR->module); } else if (func->getFunctionType() != functype) { error(fdecl->loc, "Function type does not match previously declared function with the same mangled name: %s", fdecl->mangle()); } + func->setCallingConv(gABI->callingConv(link)); + if (Logger::enabled()) Logger::cout() << "func = " << *func << std::endl; // add func to IRFunc fdecl->ir.irFunc->func = func; - // calling convention - if (!vafunc && fdecl->llvmInternal != LLVMintrinsic -#if DMDV2 - // DMD treats _Dmain as having C calling convention and this has been - // hardcoded into druntime, even if the frontend type has D linkage. - // See Bugzilla issue 9028. - && !fdecl->isMain() -#endif - ) - func->setCallingConv(gABI->callingConv(f->linkage)); - else // fall back to C, it should be the right thing to do - func->setCallingConv(llvm::CallingConv::C); - // parameter attributes if (!fdecl->isIntrinsic()) { set_param_attrs(f, func, fdecl); diff --git a/gen/module.cpp b/gen/module.cpp index 5ffd7e25ed..9d153db895 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -74,15 +74,18 @@ static llvm::Function* build_module_function(const std::string &name, const std: std::vector argsTy; LLFunctionType* fnTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false); - assert(gIR->module->getFunction(name) == NULL); - llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module); + + std::string const symbolName = gABI->mangleForLLVM(name, LINKd); + assert(gIR->module->getFunction(symbolName) == NULL); + llvm::Function* fn = llvm::Function::Create(fnTy, + llvm::GlobalValue::InternalLinkage, symbolName, gIR->module); fn->setCallingConv(gABI->callingConv(LINKd)); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); IRBuilder<> builder(bb); // debug info - DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); + DtoDwarfSubProgramInternal(name.c_str(), symbolName.c_str()); // Call ctor's typedef std::list::const_iterator FuncIterator;