diff --git a/gen/cl_options.cpp b/gen/cl_options.cpp index 06bfffe6..f24e9c3a 100644 --- a/gen/cl_options.cpp +++ b/gen/cl_options.cpp @@ -313,6 +313,9 @@ cl::opt singleObj("singleobj", cl::desc("Create only a single output object file"), cl::ZeroOrMore); +cl::opt linkonceTemplates("linkonce-templates", + cl::desc("Use linkonce_odr linkage for template symbols instead of weak_odr"), + cl::ZeroOrMore); static cl::extrahelp footer("\n" "-d-debug can also be specified without options, in which case it enables all\n" diff --git a/gen/cl_options.h b/gen/cl_options.h index 5db72e82..e2c32e91 100644 --- a/gen/cl_options.h +++ b/gen/cl_options.h @@ -42,6 +42,7 @@ namespace opts { extern cl::list mAttrs; extern cl::opt mTargetTriple; extern cl::opt singleObj; + extern cl::opt linkonceTemplates; // Arguments to -d-debug extern std::vector debugArgs; diff --git a/gen/linkage.cpp b/gen/linkage.cpp new file mode 100644 index 00000000..62853374 --- /dev/null +++ b/gen/linkage.cpp @@ -0,0 +1,4 @@ +#include "linkage.h" +#include "gen/cl_options.h" + +LLGlobalValue::LinkageTypes templateLinkage; diff --git a/gen/linkage.h b/gen/linkage.h index b4f12078..ccd0eac0 100644 --- a/gen/linkage.h +++ b/gen/linkage.h @@ -1,13 +1,14 @@ #ifndef LDC_GEN_LINKAGE_H #define LDC_GEN_LINKAGE_H +#include "gen/llvm.h" + // Make it easier to test new linkage types -# define TEMPLATE_LINKAGE_TYPE llvm::GlobalValue::WeakODRLinkage -# define TYPEINFO_LINKAGE_TYPE llvm::GlobalValue::LinkOnceODRLinkage +# define TYPEINFO_LINKAGE_TYPE LLGlobalValue::LinkOnceODRLinkage // The One-Definition-Rule shouldn't matter for debug info, right? -# define DEBUGINFO_LINKONCE_LINKAGE_TYPE \ - llvm::GlobalValue::LinkOnceAnyLinkage +# define DEBUGINFO_LINKONCE_LINKAGE_TYPE LLGlobalValue::LinkOnceAnyLinkage +extern LLGlobalValue::LinkageTypes templateLinkage; #endif diff --git a/gen/main.cpp b/gen/main.cpp index 7a0ad186..30d398c0 100644 --- a/gen/main.cpp +++ b/gen/main.cpp @@ -36,6 +36,7 @@ #include "cond.h" #include "gen/logger.h" +#include "gen/linkage.h" #include "gen/linker.h" #include "gen/irstate.h" #include "gen/optimizer.h" @@ -259,6 +260,10 @@ int main(int argc, char** argv) global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno; global.params.output_s = opts::output_s ? OUTPUTFLAGset : OUTPUTFLAGno; + templateLinkage = + opts::linkonceTemplates ? LLGlobalValue::LinkOnceODRLinkage + : LLGlobalValue::WeakODRLinkage; + if (global.params.run || !runargs.empty()) { // FIXME: how to properly detect the presence of a PositionalEatsArgs // option without parameters? We want to emit an error in that case... diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 0f0be292..7dc469ec 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -245,7 +245,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) return llvm::GlobalValue::AvailableExternallyLinkage; // template if (needsTemplateLinkage(sym)) - return TEMPLATE_LINKAGE_TYPE; + return templateLinkage; } // function else if (FuncDeclaration* fdecl = sym->isFuncDeclaration()) @@ -263,12 +263,12 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) return llvm::GlobalValue::AvailableExternallyLinkage; // array operations are always template linkage if (fdecl->isArrayOp) - return TEMPLATE_LINKAGE_TYPE; + 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 TEMPLATE_LINKAGE_TYPE; + return templateLinkage; // extern(C) functions are always external else if (ft->linkage == LINKc) return llvm::GlobalValue::ExternalLinkage; @@ -283,7 +283,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) return llvm::GlobalValue::AvailableExternallyLinkage; // template if (needsTemplateLinkage(cd)) - return TEMPLATE_LINKAGE_TYPE; + return templateLinkage; } else { @@ -334,7 +334,7 @@ llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym) if (needsTemplateLinkage(sym)) { if (isAvailableExternally(sym) && mustDefineSymbol(sym)) return llvm::GlobalValue::AvailableExternallyLinkage; - return TEMPLATE_LINKAGE_TYPE; + return templateLinkage; } else return llvm::GlobalValue::InternalLinkage; @@ -345,7 +345,7 @@ llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym) if (isAvailableExternally(sym) && mustDefineSymbol(sym)) return llvm::GlobalValue::AvailableExternallyLinkage; if (needsTemplateLinkage(sym)) - return TEMPLATE_LINKAGE_TYPE; + return templateLinkage; else return llvm::GlobalValue::ExternalLinkage; }