From 4f7bc678fbc35773770b3c6cab5b76a34892d298 Mon Sep 17 00:00:00 2001 From: kai Date: Mon, 15 Jul 2013 07:47:54 +0200 Subject: [PATCH] Implement pragma(lib) using module metadata. Since LLVM 3.3 pragma(lib) can be implemented like DMD does. --- gen/declarations.cpp | 40 +++++++++++++++++++++++++++++++++------- gen/irstate.h | 5 +++++ gen/module.cpp | 6 ++++++ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 5357baac..d5616031 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -22,6 +22,7 @@ #include "ir/ir.h" #include "ir/irtype.h" #include "ir/irvar.h" +#include "llvm/ADT/SmallString.h" /* ================================================================== */ @@ -333,13 +334,38 @@ void PragmaDeclaration::codegen(Ir* p) } } - size_t const n = nameLen + 3; - char *arg = static_cast(mem.malloc(n)); - arg[0] = '-'; - arg[1] = 'l'; - memcpy(arg + 2, se->string, nameLen); - arg[n-1] = 0; - global.params.linkswitches->push(arg); +#if LDC_LLVM_VER >= 303 + // With LLVM 3.3 or later we can place the library name in the object + // file. This seems to be supported only on Windows. + if (global.params.targetTriple.getOS() == llvm::Triple::Win32) + { + llvm::SmallString<24> LibName(llvm::StringRef(static_cast(se->string), nameLen)); + + // Win32: /DEFAULTLIB:"curl" + if (LibName.endswith(".a")) + LibName = LibName.substr(0, LibName.size()-2); + if (LibName.endswith(".lib")) + LibName = LibName.substr(0, LibName.size()-4); + llvm::SmallString<24> tmp("/DEFAULTLIB:\""); + tmp.append(LibName); + tmp.append("\""); + LibName = tmp; + + // Embedd library name as linker option in object file + llvm::Value *Value = llvm::MDString::get(gIR->context(), LibName); + gIR->LinkerMetadataArgs.push_back(llvm::MDNode::get(gIR->context(), Value)); + } + else +#endif + { + size_t const n = nameLen + 3; + char *arg = static_cast(mem.malloc(n)); + arg[0] = '-'; + arg[1] = 'l'; + memcpy(arg + 2, se->string, nameLen); + arg[n-1] = 0; + global.params.linkswitches->push(arg); + } } AttribDeclaration::codegen(p); } diff --git a/gen/irstate.h b/gen/irstate.h index 0a4df787..8083cad3 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -203,6 +203,11 @@ struct IRState /// Whether to emit array bounds checking in the current function. bool emitArrayBoundsChecks(); + +#if LDC_LLVM_VER >= 303 + /// Vector of options passed to the linker as metadata in object file. + llvm::SmallVector LinkerMetadataArgs; +#endif }; template diff --git a/gen/module.cpp b/gen/module.cpp index ebd447d0..61b97b45 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -422,6 +422,12 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) // generate ModuleInfo genmoduleinfo(); +#if LDC_LLVM_VER >= 303 + // Add the linker options metadata flag. + ir.module->addModuleFlag(llvm::Module::AppendUnique, "Linker Options", + llvm::MDNode::get(ir.context(), ir.LinkerMetadataArgs)); +#endif + // verify the llvm verifyModule(*ir.module);