diff --git a/gen/llvmcompat.cpp b/gen/llvmcompat.cpp index 11bf153f49..71198d6f72 100644 --- a/gen/llvmcompat.cpp +++ b/gen/llvmcompat.cpp @@ -1,83 +1,129 @@ #include "gen/llvmcompat.h" #include "llvm/Config/llvm-config.h" #include "llvm/ADT/Triple.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/Support/IRBuilder.h" #include #if LDC_LLVM_VER == 300 -namespace llvm { - namespace sys { - std::string getDefaultTargetTriple() { - return LLVM_HOSTTRIPLE; - } - } - - Triple Triple__get32BitArchVariant(const std::string& triple) { - Triple T(triple); - switch (T.getArch()) { - case Triple::UnknownArch: - case Triple::msp430: - T.setArch(Triple::UnknownArch); - break; - - case Triple::amdil: - case Triple::arm: - case Triple::cellspu: - case Triple::le32: - case Triple::mblaze: - case Triple::mips: - case Triple::mipsel: - case Triple::ppc: - case Triple::sparc: - case Triple::tce: - case Triple::thumb: - case Triple::x86: - case Triple::xcore: - // Already 32-bit. - break; - - case Triple::mips64: T.setArch(Triple::mips); break; - case Triple::mips64el: T.setArch(Triple::mipsel); break; - case Triple::ppc64: T.setArch(Triple::ppc); break; - case Triple::sparcv9: T.setArch(Triple::sparc); break; - case Triple::x86_64: T.setArch(Triple::x86); break; - } - return T; - } - - Triple Triple__get64BitArchVariant(const std::string& triple) { - Triple T(triple); - switch (T.getArch()) { - case Triple::UnknownArch: - case Triple::amdil: - case Triple::arm: - case Triple::cellspu: - case Triple::le32: - case Triple::mblaze: - case Triple::msp430: - case Triple::tce: - case Triple::thumb: - case Triple::xcore: - T.setArch(Triple::UnknownArch); - break; - - case Triple::mips64: - case Triple::mips64el: - case Triple::ppc64: - case Triple::sparcv9: - case Triple::x86_64: - // Already 64-bit. - break; - - case Triple::mips: T.setArch(Triple::mips64); break; - case Triple::mipsel: T.setArch(Triple::mips64el); break; - case Triple::ppc: T.setArch(Triple::ppc64); break; - case Triple::sparc: T.setArch(Triple::sparcv9); break; - case Triple::x86: T.setArch(Triple::x86_64); break; - } - return T; - } +using namespace llvm; +std::string llvm::sys::getDefaultTargetTriple() { + return LLVM_HOSTTRIPLE; } + +Triple llvm::Triple__get32BitArchVariant(const std::string& triple) { + Triple T(triple); + switch (T.getArch()) { + case Triple::UnknownArch: + case Triple::msp430: + T.setArch(Triple::UnknownArch); + break; + + case Triple::amdil: + case Triple::arm: + case Triple::cellspu: + case Triple::le32: + case Triple::mblaze: + case Triple::mips: + case Triple::mipsel: + case Triple::ppc: + case Triple::sparc: + case Triple::tce: + case Triple::thumb: + case Triple::x86: + case Triple::xcore: + // Already 32-bit. + break; + + case Triple::mips64: T.setArch(Triple::mips); break; + case Triple::mips64el: T.setArch(Triple::mipsel); break; + case Triple::ppc64: T.setArch(Triple::ppc); break; + case Triple::sparcv9: T.setArch(Triple::sparc); break; + case Triple::x86_64: T.setArch(Triple::x86); break; + } + return T; +} + +Triple llvm::Triple__get64BitArchVariant(const std::string& triple) { + Triple T(triple); + switch (T.getArch()) { + case Triple::UnknownArch: + case Triple::amdil: + case Triple::arm: + case Triple::cellspu: + case Triple::le32: + case Triple::mblaze: + case Triple::msp430: + case Triple::tce: + case Triple::thumb: + case Triple::xcore: + T.setArch(Triple::UnknownArch); + break; + + case Triple::mips64: + case Triple::mips64el: + case Triple::ppc64: + case Triple::sparcv9: + case Triple::x86_64: + // Already 64-bit. + break; + + case Triple::mips: T.setArch(Triple::mips64); break; + case Triple::mipsel: T.setArch(Triple::mips64el); break; + case Triple::ppc: T.setArch(Triple::ppc64); break; + case Triple::sparc: T.setArch(Triple::sparcv9); break; + case Triple::x86: T.setArch(Triple::x86_64); break; + } + return T; +} + +static void appendToGlobalArray(const char *Array, + Module &M, Function *F, int Priority) { + IRBuilder<> IRB(M.getContext()); + FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); + StructType *Ty = StructType::get( + IRB.getInt32Ty(), PointerType::getUnqual(FnTy), NULL); + + Constant *RuntimeCtorInit = ConstantStruct::get( + Ty, IRB.getInt32(Priority), F, NULL); + + // Get the current set of static global constructors and add the new ctor + // to the list. + SmallVector CurrentCtors; + if (GlobalVariable * GVCtor = M.getNamedGlobal(Array)) { + if (Constant *Init = GVCtor->getInitializer()) { + unsigned n = Init->getNumOperands(); + CurrentCtors.reserve(n + 1); + for (unsigned i = 0; i != n; ++i) + CurrentCtors.push_back(cast(Init->getOperand(i))); + } + GVCtor->eraseFromParent(); + } + + CurrentCtors.push_back(RuntimeCtorInit); + + // Create a new initializer. + ArrayType *AT = ArrayType::get(RuntimeCtorInit->getType(), + CurrentCtors.size()); + Constant *NewInit = ConstantArray::get(AT, CurrentCtors); + + // Create the new global variable and replace all uses of + // the old global variable with the new one. + (void)new GlobalVariable(M, NewInit->getType(), false, + GlobalValue::AppendingLinkage, NewInit, Array); +} + +void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority) { + appendToGlobalArray("llvm.global_ctors", M, F, Priority); +} + +void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority) { + appendToGlobalArray("llvm.global_dtors", M, F, Priority); +} + #endif diff --git a/gen/llvmcompat.h b/gen/llvmcompat.h index 693e828c82..2137bd3ce5 100644 --- a/gen/llvmcompat.h +++ b/gen/llvmcompat.h @@ -14,12 +14,19 @@ #if LDC_LLVM_VER == 300 namespace llvm { + class Module; + class Function; + namespace sys { std::string getDefaultTargetTriple(); } Triple Triple__get32BitArchVariant(const std::string&_this); Triple Triple__get64BitArchVariant(const std::string& _this); + + // From Transforms/Utils/ModuleUtils + void appendToGlobalCtors(Module &M, Function *F, int Priority); + void appendToGlobalDtors(Module &M, Function *F, int Priority); } #endif diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index e53038c9fb..26536bab40 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -10,6 +10,9 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetMachine.h" +#if LDC_LLVM_VER >= 301 +#include "llvm/Transforms/Utils/ModuleUtils.h" +#endif #include "gen/tollvm.h" #include "gen/irstate.h" @@ -24,6 +27,7 @@ #include "gen/todebug.h" #include "gen/nested.h" #include "ir/irmodule.h" +#include "gen/llvmcompat.h" #include @@ -1837,3 +1841,15 @@ void printLabelName(std::ostream& target, const char* func_mangle, const char* l target << gTargetMachine->getMCAsmInfo()->getPrivateGlobalPrefix() << func_mangle << "_" << label_name; } + +////////////////////////////////////////////////////////////////////////////////////////// +// CTOR and DTOR +////////////////////////////////////////////////////////////////////////////////////////// + +void AppendFunctionToLLVMGlobalCtorsDtors(llvm::Function* func, const uint32_t priority, const bool isCtor) +{ + if (isCtor) + llvm::appendToGlobalCtors(*gIR->module, func, priority); + else + llvm::appendToGlobalDtors(*gIR->module, func, priority); +} diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 1fd85a0735..4a11dcd7ff 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -196,4 +196,6 @@ Type* stripModifiers(Type* type); void printLabelName(std::ostream& target, const char* func_mangle, const char* label_name); +void AppendFunctionToLLVMGlobalCtorsDtors(llvm::Function* func, const uint32_t priority, const bool isCtor); + #endif diff --git a/gen/module.cpp b/gen/module.cpp index 284a0961cd..31c62bbd5f 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -645,23 +645,5 @@ void Module::genmoduleinfo() // build the modulereference and ctor for registering it LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSymbol()); - // register this ctor in the magic llvm.global_ctors appending array - LLFunctionType* magicfty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); - std::vector magictypes; - magictypes.push_back(LLType::getInt32Ty(gIR->context())); - magictypes.push_back(getPtrToType(magicfty)); - LLStructType* magicsty = LLStructType::get(gIR->context(), magictypes); - - // make the constant element - std::vector magicconstants; - magicconstants.push_back(DtoConstUint(65535)); - magicconstants.push_back(mictor); - LLConstant* magicinit = LLConstantStruct::get(magicsty, magicconstants); - - // declare the appending array - llvm::ArrayType* appendArrTy = llvm::ArrayType::get(magicsty, 1); - std::vector appendInits(1, magicinit); - LLConstant* appendInit = LLConstantArray::get(appendArrTy, appendInits); - std::string appendName("llvm.global_ctors"); - new llvm::GlobalVariable(*gIR->module, appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName); + AppendFunctionToLLVMGlobalCtorsDtors(mictor, 65535, true); }