llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym, bool checkInline) { if (DtoIsTemplateInstance(sym)) return templateLinkage; else if (checkInline && isAvailableExternally(sym)) return llvm::GlobalValue::AvailableExternallyLinkage; else return llvm::GlobalValue::ExternalLinkage; }
llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym) { if (DtoIsTemplateInstance(sym)) { if (isAvailableExternally(sym)) return llvm::GlobalValue::AvailableExternallyLinkage; return templateLinkage; } else return llvm::GlobalValue::InternalLinkage; }
LinkageWithCOMDAT DtoLinkage(Dsymbol *sym) { auto linkage = (DtoIsTemplateInstance(sym) ? templateLinkage : LLGlobalValue::ExternalLinkage); // If @(ldc.attributes.weak) is applied, override the linkage to WeakAny if (hasWeakUDA(sym)) { linkage = LLGlobalValue::WeakAnyLinkage; } return {linkage, supportsCOMDAT()}; }
LinkageWithCOMDAT DtoLinkage(Dsymbol* sym) { if (DtoIsTemplateInstance(sym)) return LinkageWithCOMDAT(templateLinkage, supportsCOMDAT()); return LinkageWithCOMDAT(llvm::GlobalValue::ExternalLinkage, false); }
LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) { // global/static variable if (VarDeclaration* vd = sym->isVarDeclaration()) { IF_LOG Logger::println("Variable %savailable externally: %s", (vd->availableExternally ? "" : "not "), vd->toChars()); // generated by inlining semantics run if (vd->availableExternally) return llvm::GlobalValue::AvailableExternallyLinkage; // template if (DtoIsTemplateInstance(sym)) return templateLinkage; // Currently, we have to consider all variables, even function-local // statics, to be external, as CTFE might cause template functions // instances to be semantic3'd that occur within the body of a function // from an imported module. Consequently, a copy of them is codegen'd // in the importing module, even if they might reference a static in a // function in the imported module (e.g. via an alias parameter). // // A fix for this would be to track instantiations/semantic3 runs made // solely for CTFE purposes in a way similar to how the extra inlining // semantic runs are handled. // // LDC_FIXME: Can this also occur for functions? Find a better solution. if (true || vd->storage_class & STCextern) return llvm::GlobalValue::ExternalLinkage; } else if (FuncDeclaration* fdecl = sym->isFuncDeclaration()) { IF_LOG Logger::println("Function %savailable externally: %s", (fdecl->availableExternally ? "" : "not "), fdecl->toChars()); assert(fdecl->type->ty == Tfunction); TypeFunction* ft = static_cast<TypeFunction*>(fdecl->type); // intrinsics are always external if (fdecl->llvmInternal == LLVMintrinsic) return llvm::GlobalValue::ExternalLinkage; // Mark functions generated by an inlining semantic run as // available_externally. Naked functions are turned into module-level // inline asm and are thus declaration-only as far as the LLVM IR level // is concerned. if (fdecl->availableExternally && !fdecl->naked) return llvm::GlobalValue::AvailableExternallyLinkage; // array operations are always template linkage if (fdecl->isArrayOp == 1) return templateLinkage; // template instances should have weak linkage // but only if there's a body, and it's not naked // otherwise we make it external if (DtoIsTemplateInstance(fdecl) && fdecl->fbody && !fdecl->naked) return templateLinkage; // extern(C) functions are always external if (ft->linkage == LINKc) return llvm::GlobalValue::ExternalLinkage; // If a function without a body is nested in another // function, we cannot use internal linkage for that // function (see below about nested functions) // FIXME: maybe there is a better way without emission // of needless symbols? if (!fdecl->fbody) return llvm::GlobalValue::ExternalLinkage; } // class else if (ClassDeclaration* cd = sym->isClassDeclaration()) { IF_LOG Logger::println("Class %savailable externally: %s", (cd->availableExternally ? "" : "not "), vd->toChars()); // generated by inlining semantics run if (cd->availableExternally) return llvm::GlobalValue::AvailableExternallyLinkage; // template if (DtoIsTemplateInstance(cd)) return templateLinkage; } else { llvm_unreachable("not global/function"); } // The logic here should be sound in theory, but as long as the frontend // keeps inserting templates into wrong modules, this yields to linking // errors (see e.g. GitHub issue #558). #if 0 // Check if sym is a nested function and we can declare it as internal. // // Nested naked functions and the implicitly generated __require/__ensure // functions for in/out contracts cannot be internalized. The reason // for the latter is that contract functions, despite being nested, can be // referenced from other D modules e.g. in the case of contracts on // interface methods (where __require/__ensure are emitted to the module // where the interface is declared, but an actual interface implementation // can be in a completely different place). FuncDeclaration* fd = sym->isFuncDeclaration(); if (!fd || (!fd->naked && fd->ident != Id::require && fd->ident != Id::ensure)) { // Any symbol nested in a function that cannot be inlined can't be // referenced directly from outside that function, so we can give // such symbols internal linkage. This holds even if nested indirectly, // such as member functions of aggregates nested in functions. // // Note: This must be checked after things like template member-ness or // symbols nested in templates would get duplicated for each module, // breaking things like // --- // int counter(T)() { static int i; return i++; }" // --- // if instances get emitted in multiple object files because they'd use // different instances of 'i'. // TODO: Check if we are giving away too much inlining potential due to // canInline being overly conservative here. for (Dsymbol* parent = sym->parent; parent ; parent = parent->parent) { FuncDeclaration *parentFd = parent->isFuncDeclaration(); if (parentFd && !parentFd->canInline(parentFd->needThis(), false, false)) { // We also cannot internalize nested functions which are // leaked to the outside via a templated return type, because // that type will also be codegen'd in any caller modules (see // GitHub issue #131). // Since we can't easily determine if this is really the case // here, just don't internalize it if the parent returns a // template at all, to be safe. TypeFunction* tf = static_cast<TypeFunction*>(parentFd->type); if (!DtoIsTemplateInstance(tf->next->toDsymbol(parentFd->scope))) return llvm::GlobalValue::InternalLinkage; } } } #endif // default to external linkage return llvm::GlobalValue::ExternalLinkage; }
void DtoDefineNakedFunction(FuncDeclaration* fd) { Logger::println("DtoDefineNakedFunction(%s)", fd->mangle()); LOG_SCOPE; assert(fd->ir.irFunc); gIR->functions.push_back(fd->ir.irFunc); // we need to do special processing on the body, since we only want // to allow actual inline asm blocks to reach the final asm output std::ostringstream& asmstr = gIR->nakedAsm; // build function header // FIXME: could we perhaps use llvm asmwriter to give us these details ? const char* mangle = fd->mangle(); std::ostringstream tmpstr; bool const isWin = global.params.targetTriple.isOSWindows(); bool const isOSX = (global.params.targetTriple.getOS() == llvm::Triple::Darwin || global.params.targetTriple.getOS() == llvm::Triple::MacOSX); // osx is different // also mangling has an extra underscore prefixed if (isOSX) { std::string section = "text"; bool weak = false; if (DtoIsTemplateInstance(fd)) { tmpstr << "section\t__TEXT,__textcoal_nt,coalesced,pure_instructions"; section = tmpstr.str(); weak = true; } asmstr << "\t." << section << std::endl; asmstr << "\t.align\t4,0x90" << std::endl; asmstr << "\t.globl\t_" << mangle << std::endl; if (weak) { asmstr << "\t.weak_definition\t_" << mangle << std::endl; } asmstr << "_" << mangle << ":" << std::endl; } else { std::string fullMangle; if (global.params.targetTriple.getOS() == llvm::Triple::MinGW32 || global.params.targetTriple.getOS() == llvm::Triple::Win32) { fullMangle = "_"; } fullMangle += mangle; const char* linkage = "globl"; std::string section = "text"; if (DtoIsTemplateInstance(fd)) { linkage = "weak"; tmpstr << "section\t.gnu.linkonce.t." << fullMangle << ",\"ax\""; if (!isWin) tmpstr << ",@progbits"; section = tmpstr.str(); } asmstr << "\t." << section << std::endl; asmstr << "\t.align\t16" << std::endl; if (isWin) { asmstr << "\t.def\t" << fullMangle << ";"; // hard code these two numbers for now since gas ignores .scl and llvm // is defaulting to .type 32 for everything I have seen asmstr << "\t.scl 2; .type 32;\t.endef" << std::endl; } else { asmstr << "\t.type\t" << fullMangle << ",@function" << std::endl; } asmstr << "\t." << linkage << "\t" << fullMangle << std::endl; asmstr << fullMangle << ":" << std::endl; } // emit body fd->fbody->toNakedIR(gIR); // We could have generated new errors in toNakedIR(), but we are in codegen // already so we have to abort here. if (global.errors) fatal(); // emit size after body // llvm does this on linux, but not on osx or Win if (!(isWin || isOSX)) { asmstr << "\t.size\t" << mangle << ", .-" << mangle << std::endl << std::endl; } gIR->module->appendModuleInlineAsm(asmstr.str()); asmstr.str(""); gIR->functions.pop_back(); }
LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) { const bool mustDefine = mustDefineSymbol(sym); // global variable if (VarDeclaration* vd = sym->isVarDeclaration()) { if (mustDefine) { IF_LOG Logger::println("Variable %savailable externally: %s", (vd->availableExternally ? "" : "not "), vd->toChars()); } // generated by inlining semantics run if (vd->availableExternally && mustDefine) return llvm::GlobalValue::AvailableExternallyLinkage; // template if (needsTemplateLinkage(sym)) return templateLinkage; // never use InternalLinkage for variables marked as "extern" if (vd->storage_class & STCextern) return llvm::GlobalValue::ExternalLinkage; } // function else if (FuncDeclaration* fdecl = sym->isFuncDeclaration()) { if (mustDefine) { IF_LOG Logger::println("Function %savailable externally: %s", (fdecl->availableExternally ? "" : "not "), fdecl->toChars()); } assert(fdecl->type->ty == Tfunction); TypeFunction* ft = static_cast<TypeFunction*>(fdecl->type); // intrinsics are always external if (fdecl->llvmInternal == LLVMintrinsic) return llvm::GlobalValue::ExternalLinkage; // generated by inlining semantics run if (fdecl->availableExternally && mustDefine) return llvm::GlobalValue::AvailableExternallyLinkage; // array operations are always template linkage if (fdecl->isArrayOp == 1) return templateLinkage; // template instances should have weak linkage // but only if there's a body, and it's not naked // otherwise we make it external else if (needsTemplateLinkage(fdecl) && fdecl->fbody && !fdecl->naked) return templateLinkage; // extern(C) functions are always external else if (ft->linkage == LINKc) return llvm::GlobalValue::ExternalLinkage; // If a function without a body is nested in another // function, we cannot use internal linkage for that // function (see below about nested functions) // FIXME: maybe there is a better way without emission // of needless symbols? if (!fdecl->fbody) return llvm::GlobalValue::ExternalLinkage; } // class else if (ClassDeclaration* cd = sym->isClassDeclaration()) { if (mustDefine) { IF_LOG Logger::println("Class %savailable externally: %s", (cd->availableExternally ? "" : "not "), vd->toChars()); } // generated by inlining semantics run if (cd->availableExternally && mustDefine) return llvm::GlobalValue::AvailableExternallyLinkage; // template if (needsTemplateLinkage(cd)) return templateLinkage; } else { assert(0 && "not global/function"); } // If the function needs to be defined in the current module, check if it // is a nested function and we can declare it as internal. bool canInternalize = mustDefine; // Nested naked functions and the implicitly generated __require/__ensure // functions for in/out contracts cannot be internalized. The reason // for the latter is that contract functions, despite being nested, can be // referenced from other D modules e.g. in the case of contracts on // interface methods (where __require/__ensure are emitted to the module // where the interface is declared, but an actual interface implementation // can be in a completely different place). if (canInternalize) { if (FuncDeclaration* fd = sym->isFuncDeclaration()) { if ((fd->naked != 0) || (fd->ident == Id::require) || (fd->ident == Id::ensure)) { canInternalize = false; } } } // Any symbol nested in a function that cannot be inlined can't be // referenced directly from outside that function, so we can give // such symbols internal linkage. This holds even if nested indirectly, // such as member functions of aggregates nested in functions. // // Note: This must be checked after things like template member-ness or // symbols nested in templates would get duplicated for each module, // breaking things like // --- // int counter(T)() { static int i; return i++; }" // --- // if instances get emitted in multiple object files because they'd use // different instances of 'i'. // TODO: Check if we are giving away too much inlining potential due to // canInline being overly conservative here. if (canInternalize) { for (Dsymbol* parent = sym->parent; parent ; parent = parent->parent) { FuncDeclaration *fd = parent->isFuncDeclaration(); if (fd && !fd->canInline(fd->needThis())) { // We also cannot internalize nested functions which are // leaked to the outside via a templated return type, because // that type will also be codegen'd in any caller modules (see // GitHub issue #131). // Since we can't easily determine if this is really the case // here, just don't internalize it if the parent returns a // template at all, to be safe. TypeFunction* tf = static_cast<TypeFunction*>(fd->type); if (!DtoIsTemplateInstance(tf->next->toDsymbol(fd->scope))) return llvm::GlobalValue::InternalLinkage; } } } // default to external linkage return llvm::GlobalValue::ExternalLinkage; }
llvm::GlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) { if (DtoIsTemplateInstance(sym)) return templateLinkage; return llvm::GlobalValue::ExternalLinkage; }