From 0b411b873ca2691738d8ee3bd3c224ecc382ad64 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Sun, 1 Apr 2012 22:06:08 +0100 Subject: [PATCH 1/6] Separated compiler from the driver into the shared library --- CMakeLists.txt | 40 +++++++++++++++++++++++++++------------- {gen => driver}/main.cpp | 0 2 files changed, 27 insertions(+), 13 deletions(-) rename {gen => driver}/main.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ffd4ec7..4a5f6b82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,7 +191,7 @@ foreach(TARGET ${HOST_ARCH} ${EXTRA_LLVM_MODULES}) endforeach(TARGET) set_source_files_properties( - ${PROJECT_SOURCE_DIR}/gen/main.cpp PROPERTIES + ${PROJECT_SOURCE_DIR}/driver/main.cpp PROPERTIES COMPILE_DEFINITIONS LDC_TARGETS=${LLVM_MODULES_DEFINE} ) @@ -204,6 +204,7 @@ set_source_files_properties( file(GLOB_RECURSE FE_SRC ${DMDFE_PATH}/*.c ${DMDFE_PATH}/*.h) file(GLOB_RECURSE GEN_SRC gen/*.cpp gen/*.h) file(GLOB IR_SRC ir/*.cpp ir/*.h) +file(GLOB_RECURSE DRV_SRC driver/*.cpp driver/*.h) # exclude idgen and impcnvgen and generated sources, just in case list(REMOVE_ITEM FE_SRC ${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/idgen.c @@ -266,9 +267,31 @@ endif(USE_METADATA) # # Set up the main ldc/ldc2 target. # +set(LDC_LIB LDCShared) # Path where ldc executable will be put -add_executable(${LDC_EXE} ${LDC_SOURCE_FILES}) +add_library(${LDC_LIB} SHARED ${LDC_SOURCE_FILES}) +# Build ldc +set_target_properties( + ${LDC_LIB} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin + LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib + COMPILE_FLAGS "${LLVM_CXXFLAGS} ${LIBCONFIG_CXXFLAGS} -Wno-deprecated -Wno-write-strings -fexceptions" +) + +# LDFLAGS should actually be in target property LINK_FLAGS, but this works, and gets around linking problems +target_link_libraries(${LDC_LIB} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES}" ${LIBCONFIG_LDFLAGS} config++) +if(WIN32) + target_link_libraries(${LDC_LIB} imagehlp psapi) +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + target_link_libraries(${LDC_LIB} dl) +endif(WIN32) + +if(USE_BOEHM_GC) + target_link_libraries(${LDC_LIB} ${PROJECT_SOURCE_DIR}/libgc.a) +endif(USE_BOEHM_GC) + +add_executable(${LDC_EXE} ${DRV_SRC}) # Name of ldc executable set(LDC_EXE_NAME ${PROGRAM_PREFIX}${LDC_EXE}${PROGRAM_SUFFIX}) # Build ldc @@ -278,18 +301,8 @@ set_target_properties( RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin COMPILE_FLAGS "${LLVM_CXXFLAGS} ${LIBCONFIG_CXXFLAGS} -Wno-deprecated -Wno-write-strings -fexceptions" ) +target_link_libraries(${LDC_EXE} ${LDC_LIB}) -# LDFLAGS should actually be in target property LINK_FLAGS, but this works, and gets around linking problems -target_link_libraries(${LDC_EXE} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES}" ${LIBCONFIG_LDFLAGS} config++) -if(WIN32) - target_link_libraries(${LDC_EXE} imagehlp psapi) -elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - target_link_libraries(${LDC_EXE} dl) -endif(WIN32) - -if(USE_BOEHM_GC) - target_link_libraries(${LDC_EXE} ${PROJECT_SOURCE_DIR}/libgc.a) -endif(USE_BOEHM_GC) get_target_property(LDC_LOC ${LDC_EXE} LOCATION) @@ -300,6 +313,7 @@ get_target_property(LDC_LOC ${LDC_EXE} LOCATION) add_subdirectory(runtime) install(TARGETS ${LDC_EXE} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${LDC_LIB} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) install(PROGRAMS ${PROJECT_SOURCE_DIR}/bin/${LDMD_EXE} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(FILES ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}_install.conf DESTINATION ${CONF_INST_DIR} RENAME ${LDC_EXE}.conf) install(FILES ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}_install.rebuild.conf DESTINATION ${CONF_INST_DIR} RENAME ${LDC_EXE}.rebuild.conf) diff --git a/gen/main.cpp b/driver/main.cpp similarity index 100% rename from gen/main.cpp rename to driver/main.cpp From 71044056e4465039eeb45940f7bf95d603ae447b Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Mon, 2 Apr 2012 00:11:30 +0100 Subject: [PATCH 2/6] split toobj.cpp and moved writeModule outside of LDCShared --- driver/main.cpp | 3 +- driver/toobj.cpp | 175 ++++ {gen => driver}/toobj.h | 0 gen/{toobj.cpp => module.cpp} | 1524 +++++++++++++++------------------ 4 files changed, 854 insertions(+), 848 deletions(-) create mode 100644 driver/toobj.cpp rename {gen => driver}/toobj.h (100%) rename gen/{toobj.cpp => module.cpp} (76%) diff --git a/driver/main.cpp b/driver/main.cpp index 3ff361e0..50f8ba03 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -33,7 +33,6 @@ #include "gen/linker.h" #include "gen/irstate.h" #include "gen/optimizer.h" -#include "gen/toobj.h" #include "gen/metadata.h" #include "gen/passes/Passes.h" @@ -43,6 +42,8 @@ using namespace opts; #include "gen/configfile.h" +#include "driver/toobj.h" + #if POSIX #include #elif _WIN32 diff --git a/driver/toobj.cpp b/driver/toobj.cpp new file mode 100644 index 00000000..98ce6abc --- /dev/null +++ b/driver/toobj.cpp @@ -0,0 +1,175 @@ + +// Copyright (c) 1999-2004 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include +#include + +#include "llvm/Analysis/Verifier.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetMachine.h" + +#include "gen/irstate.h" +#include "gen/logger.h" +#include "gen/optimizer.h" + + +////////////////////////////////////////////////////////////////////////////////////////// + +extern llvm::cl::opt noVerify; + +////////////////////////////////////////////////////////////////////////////////////////// + +// fwd decl +void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out, + llvm::TargetMachine::CodeGenFileType fileType); + +////////////////////////////////////////////////////////////////////////////////////////// + +void writeModule(llvm::Module* m, std::string filename) +{ + // run optimizer + bool reverify = ldc_optimize_module(m); + + // verify the llvm + if (!noVerify && reverify) { + std::string verifyErr; + Logger::println("Verifying module... again..."); + LOG_SCOPE; + if (llvm::verifyModule(*m,llvm::ReturnStatusAction,&verifyErr)) + { + error("%s", verifyErr.c_str()); + fatal(); + } + else { + Logger::println("Verification passed!"); + } + } + + // eventually do our own path stuff, dmd's is a bit strange. + typedef llvm::sys::Path LLPath; + + // write LLVM bitcode + if (global.params.output_bc) { + LLPath bcpath = LLPath(filename); + bcpath.eraseSuffix(); + bcpath.appendSuffix(std::string(global.bc_ext)); + Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str()); + std::string errinfo; + llvm::raw_fd_ostream bos(bcpath.c_str(), errinfo, llvm::raw_fd_ostream::F_Binary); + if (bos.has_error()) + { + error("cannot write LLVM bitcode file '%s': %s", bcpath.c_str(), errinfo.c_str()); + fatal(); + } + llvm::WriteBitcodeToFile(m, bos); + } + + // write LLVM IR + if (global.params.output_ll) { + LLPath llpath = LLPath(filename); + llpath.eraseSuffix(); + llpath.appendSuffix(std::string(global.ll_ext)); + Logger::println("Writing LLVM asm to: %s\n", llpath.c_str()); + std::string errinfo; + llvm::raw_fd_ostream aos(llpath.c_str(), errinfo); + if (aos.has_error()) + { + error("cannot write LLVM asm file '%s': %s", llpath.c_str(), errinfo.c_str()); + fatal(); + } + m->print(aos, NULL); + } + + // write native assembly + if (global.params.output_s) { + LLPath spath = LLPath(filename); + spath.eraseSuffix(); + spath.appendSuffix(std::string(global.s_ext)); + Logger::println("Writing native asm to: %s\n", spath.c_str()); + std::string err; + { + llvm::raw_fd_ostream out(spath.c_str(), err); + if (err.empty()) + { + emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_AssemblyFile); + } + else + { + error("cannot write native asm: %s", err.c_str()); + fatal(); + } + } + } + + if (global.params.output_o) { + LLPath objpath = LLPath(filename); + Logger::println("Writing object file to: %s\n", objpath.c_str()); + std::string err; + { + llvm::raw_fd_ostream out(objpath.c_str(), err, llvm::raw_fd_ostream::F_Binary); + if (err.empty()) + { + emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_ObjectFile); + } + else + { + error("cannot write object file: %s", err.c_str()); + fatal(); + } + } + } +} + +/* ================================================================== */ + +// based on llc code, University of Illinois Open Source License +void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out, + llvm::TargetMachine::CodeGenFileType fileType) +{ + using namespace llvm; + + // Build up all of the passes that we want to do to the module. + FunctionPassManager Passes(&m); + + if (const TargetData *TD = Target.getTargetData()) + Passes.add(new TargetData(*TD)); + else + Passes.add(new TargetData(&m)); + + // Last argument is enum CodeGenOpt::Level OptLevel + // debug info doesn't work properly with OptLevel != None! + CodeGenOpt::Level LastArg = CodeGenOpt::Default; + if (global.params.symdebug || !optimize()) + LastArg = CodeGenOpt::None; + else if (optLevel() >= 3) + LastArg = CodeGenOpt::Aggressive; + + llvm::formatted_raw_ostream fout(out); + if (Target.addPassesToEmitFile(Passes, fout, fileType, LastArg)) + assert(0 && "no support for asm output"); + + Passes.doInitialization(); + + // Run our queue of passes all at once now, efficiently. + for (llvm::Module::iterator I = m.begin(), E = m.end(); I != E; ++I) + if (!I->isDeclaration()) + Passes.run(*I); + + Passes.doFinalization(); + + // release module from module provider so we can delete it ourselves + //std::string Err; + //llvm::Module* rmod = Provider.releaseModule(&Err); + //assert(rmod); +} diff --git a/gen/toobj.h b/driver/toobj.h similarity index 100% rename from gen/toobj.h rename to driver/toobj.h diff --git a/gen/toobj.cpp b/gen/module.cpp similarity index 76% rename from gen/toobj.cpp rename to gen/module.cpp index 1bc4929f..e17d35ee 100644 --- a/gen/toobj.cpp +++ b/gen/module.cpp @@ -1,847 +1,677 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "gen/llvm.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/LinkAllPasses.h" -#include "llvm/Support/Program.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/LLVMContext.h" - -#include "mars.h" -#include "module.h" -#include "mtype.h" -#include "declaration.h" -#include "statement.h" -#include "enum.h" -#include "aggregate.h" -#include "init.h" -#include "attrib.h" -#include "id.h" -#include "import.h" -#include "template.h" -#include "scope.h" - -#include "gen/abi.h" -#include "gen/arrays.h" -#include "gen/classes.h" -#include "gen/cl_options.h" -#include "gen/functions.h" -#include "gen/irstate.h" -#include "gen/llvmhelpers.h" -#include "gen/logger.h" -#include "gen/optimizer.h" -#include "gen/programs.h" -#include "gen/rttibuilder.h" -#include "gen/runtime.h" -#include "gen/structs.h" -#include "gen/todebug.h" -#include "gen/tollvm.h" - -#include "ir/irvar.h" -#include "ir/irmodule.h" -#include "ir/irtype.h" - -#if DMDV2 -#define NEW_MODULEINFO_LAYOUT 1 -#endif - -////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::cl::opt noVerify("noverify", - llvm::cl::desc("Do not run the validation pass before writing bitcode"), - llvm::cl::ZeroOrMore); - -////////////////////////////////////////////////////////////////////////////////////////// - -// fwd decl -void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out, - llvm::TargetMachine::CodeGenFileType fileType); - -////////////////////////////////////////////////////////////////////////////////////////// - -llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) -{ - bool logenabled = Logger::enabled(); - if (llvmForceLogging && !logenabled) - { - Logger::enable(); - } - - Logger::println("Generating module: %s\n", (md ? md->toChars() : toChars())); - LOG_SCOPE; - - if (global.params.verbose_cg) - printf("codegen: %s (%s)\n", toPrettyChars(), srcfile->toChars()); - - assert(!global.errors); - - // name the module - llvm::StringRef mname(toChars()); - if (md != 0) - mname = md->toChars(); - - // create a new ir state - // TODO look at making the instance static and moving most functionality into IrModule where it belongs - IRState ir(new llvm::Module(mname, context)); - gIR = &ir; - ir.dmodule = this; - - // reset all IR data stored in Dsymbols - IrDsymbol::resetAll(); - - sir->setState(&ir); - - // set target triple - ir.module->setTargetTriple(global.params.targetTriple); - - // set final data layout - ir.module->setDataLayout(global.params.dataLayout); - if (Logger::enabled()) - Logger::cout() << "Final data layout: " << global.params.dataLayout << '\n'; - - // allocate the target abi - gABI = TargetABI::getTarget(); - - // debug info - DtoDwarfCompileUnit(this); - - // handle invalid 'objectø module - if (!ClassDeclaration::object) { - error("is missing 'class Object'"); - fatal(); - } - if (!ClassDeclaration::classinfo) { - error("is missing 'class ClassInfo'"); - fatal(); - } - - LLVM_D_InitRuntime(); - - // process module members - for (unsigned k=0; k < members->dim; k++) { - Dsymbol* dsym = (Dsymbol*)(members->data[k]); - assert(dsym); - dsym->codegen(sir); - } - - // emit function bodies - sir->emitFunctionBodies(); - - // for singleobj-compilation, fully emit all seen template instances - if (opts::singleObj) - { - while (!ir.seenTemplateInstances.empty()) - { - IRState::TemplateInstanceSet::iterator it, end = ir.seenTemplateInstances.end(); - for (it = ir.seenTemplateInstances.begin(); it != end; ++it) - (*it)->codegen(sir); - ir.seenTemplateInstances.clear(); - - // emit any newly added function bodies - sir->emitFunctionBodies(); - } - } - - // finilize debug info - DtoDwarfModuleEnd(); - - // generate ModuleInfo - genmoduleinfo(); - - // verify the llvm - if (!noVerify) { - std::string verifyErr; - Logger::println("Verifying module..."); - LOG_SCOPE; - if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) - { - error("%s", verifyErr.c_str()); - fatal(); - } - else { - Logger::println("Verification passed!"); - } - } - - gIR = NULL; - - if (llvmForceLogging && !logenabled) - { - Logger::disable(); - } - - sir->setState(NULL); - - return ir.module; -} - -void writeModule(llvm::Module* m, std::string filename) -{ - // run optimizer - bool reverify = ldc_optimize_module(m); - - // verify the llvm - if (!noVerify && reverify) { - std::string verifyErr; - Logger::println("Verifying module... again..."); - LOG_SCOPE; - if (llvm::verifyModule(*m,llvm::ReturnStatusAction,&verifyErr)) - { - error("%s", verifyErr.c_str()); - fatal(); - } - else { - Logger::println("Verification passed!"); - } - } - - // eventually do our own path stuff, dmd's is a bit strange. - typedef llvm::sys::Path LLPath; - - // write LLVM bitcode - if (global.params.output_bc) { - LLPath bcpath = LLPath(filename); - bcpath.eraseSuffix(); - bcpath.appendSuffix(std::string(global.bc_ext)); - Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str()); - std::string errinfo; - llvm::raw_fd_ostream bos(bcpath.c_str(), errinfo, llvm::raw_fd_ostream::F_Binary); - if (bos.has_error()) - { - error("cannot write LLVM bitcode file '%s': %s", bcpath.c_str(), errinfo.c_str()); - fatal(); - } - llvm::WriteBitcodeToFile(m, bos); - } - - // write LLVM IR - if (global.params.output_ll) { - LLPath llpath = LLPath(filename); - llpath.eraseSuffix(); - llpath.appendSuffix(std::string(global.ll_ext)); - Logger::println("Writing LLVM asm to: %s\n", llpath.c_str()); - std::string errinfo; - llvm::raw_fd_ostream aos(llpath.c_str(), errinfo); - if (aos.has_error()) - { - error("cannot write LLVM asm file '%s': %s", llpath.c_str(), errinfo.c_str()); - fatal(); - } - m->print(aos, NULL); - } - - // write native assembly - if (global.params.output_s) { - LLPath spath = LLPath(filename); - spath.eraseSuffix(); - spath.appendSuffix(std::string(global.s_ext)); - Logger::println("Writing native asm to: %s\n", spath.c_str()); - std::string err; - { - llvm::raw_fd_ostream out(spath.c_str(), err); - if (err.empty()) - { - emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_AssemblyFile); - } - else - { - error("cannot write native asm: %s", err.c_str()); - fatal(); - } - } - } - - if (global.params.output_o) { - LLPath objpath = LLPath(filename); - Logger::println("Writing object file to: %s\n", objpath.c_str()); - std::string err; - { - llvm::raw_fd_ostream out(objpath.c_str(), err, llvm::raw_fd_ostream::F_Binary); - if (err.empty()) - { - emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_ObjectFile); - } - else - { - error("cannot write object file: %s", err.c_str()); - fatal(); - } - } - } -} - -/* ================================================================== */ - -// based on llc code, University of Illinois Open Source License -void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out, - llvm::TargetMachine::CodeGenFileType fileType) -{ - using namespace llvm; - - // Build up all of the passes that we want to do to the module. - FunctionPassManager Passes(&m); - - if (const TargetData *TD = Target.getTargetData()) - Passes.add(new TargetData(*TD)); - else - Passes.add(new TargetData(&m)); - - // Last argument is enum CodeGenOpt::Level OptLevel - // debug info doesn't work properly with OptLevel != None! - CodeGenOpt::Level LastArg = CodeGenOpt::Default; - if (global.params.symdebug || !optimize()) - LastArg = CodeGenOpt::None; - else if (optLevel() >= 3) - LastArg = CodeGenOpt::Aggressive; - - llvm::formatted_raw_ostream fout(out); - if (Target.addPassesToEmitFile(Passes, fout, fileType, LastArg)) - assert(0 && "no support for asm output"); - - Passes.doInitialization(); - - // Run our queue of passes all at once now, efficiently. - for (llvm::Module::iterator I = m.begin(), E = m.end(); I != E; ++I) - if (!I->isDeclaration()) - Passes.run(*I); - - Passes.doFinalization(); - - // release module from module provider so we can delete it ourselves - //std::string Err; - //llvm::Module* rmod = Provider.releaseModule(&Err); - //assert(rmod); -} - -/* ================================================================== */ - -static llvm::Function* build_module_function(const std::string &name, const std::list &funcs, - const std::list &gates = std::list()) -{ - if (gates.empty()) { - if (funcs.empty()) - return NULL; - - if (funcs.size() == 1) - return funcs.front()->ir.irFunc->func; - } - - 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); - fn->setCallingConv(DtoCallingConv(0, LINKd)); - - llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); - IRBuilder<> builder(bb); - - // debug info - DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); - - // Call ctor's - typedef std::list::const_iterator FuncIterator; - for (FuncIterator itr = funcs.begin(), end = funcs.end(); itr != end; ++itr) { - llvm::Function* f = (*itr)->ir.irFunc->func; - llvm::CallInst* call = builder.CreateCall(f,""); - call->setCallingConv(DtoCallingConv(0, LINKd)); - } - - // Increment vgate's - typedef std::list::const_iterator GatesIterator; - for (GatesIterator itr = gates.begin(), end = gates.end(); itr != end; ++itr) { - assert((*itr)->ir.irGlobal); - llvm::Value* val = (*itr)->ir.irGlobal->value; - llvm::Value* rval = builder.CreateLoad(val, "vgate"); - llvm::Value* res = builder.CreateAdd(rval, DtoConstUint(1), "vgate"); - builder.CreateStore(res, val); - } - - builder.CreateRetVoid(); - return fn; -} - -// build module ctor - -llvm::Function* build_module_ctor() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("6__ctorZ"); -#if DMDV2 - return build_module_function(name, gIR->ctors, gIR->gates); -#else - return build_module_function(name, gIR->ctors); -#endif -} - -// build module dtor - -static llvm::Function* build_module_dtor() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("6__dtorZ"); - return build_module_function(name, gIR->dtors); -} - -// build module unittest - -static llvm::Function* build_module_unittest() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("10__unittestZ"); - return build_module_function(name, gIR->unitTests); -} - -#if DMDV2 - -// build module shared ctor - -llvm::Function* build_module_shared_ctor() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("13__shared_ctorZ"); - return build_module_function(name, gIR->sharedCtors, gIR->sharedGates); -} - -// build module shared dtor - -static llvm::Function* build_module_shared_dtor() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("13__shared_dtorZ"); - return build_module_function(name, gIR->sharedDtors); -} - -#endif - -// build ModuleReference and register function, to register the module info in the global linked list -static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) -{ - // build ctor type - LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); - - // build ctor name - std::string fname = "_D"; - fname += gIR->dmodule->mangle(); - fname += "16__moduleinfoCtorZ"; - - // build a function that registers the moduleinfo in the global moduleinfo linked list - LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, gIR->module); - - // provide the default initializer - LLStructType* modulerefTy = DtoModuleReferenceType(); - std::vector mrefvalues; - mrefvalues.push_back(LLConstant::getNullValue(modulerefTy->getContainedType(0))); - mrefvalues.push_back(llvm::ConstantExpr::getBitCast(moduleinfo, modulerefTy->getContainedType(1))); - LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, mrefvalues); - - // create the ModuleReference node for this module - std::string thismrefname = "_D"; - thismrefname += gIR->dmodule->mangle(); - thismrefname += "11__moduleRefZ"; - LLGlobalVariable* thismref = new LLGlobalVariable(*gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, thismrefname); - - // make sure _Dmodule_ref is declared - LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref"); - LLType *modulerefPtrTy = getPtrToType(modulerefTy); - if (!mref) - mref = new LLGlobalVariable(*gIR->module, modulerefPtrTy, false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref"); - mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy)); - - // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list - llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "moduleinfoCtorEntry", ctor); - IRBuilder<> builder(bb); - - // debug info - llvm::DISubprogram subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()); - - // get current beginning - LLValue* curbeg = builder.CreateLoad(mref, "current"); - - // put current beginning as the next of this one - LLValue* gep = builder.CreateStructGEP(thismref, 0, "next"); - builder.CreateStore(curbeg, gep); - - // replace beginning - builder.CreateStore(thismref, mref); - - // return - builder.CreateRetVoid(); - - return ctor; -} - -llvm::GlobalVariable* Module::moduleInfoSymbol() -{ - // create name - std::string MIname("_D"); - MIname.append(mangle()); - MIname.append("8__ModuleZ"); - - if (gIR->dmodule != this) { - LLType* moduleinfoTy = DtoType(moduleinfo->type); - LLGlobalVariable *var = gIR->module->getGlobalVariable(MIname); - if (!var) - var = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); - return var; - } - - if (moduleInfoVar) - return moduleInfoVar; - - // declare global - // flags will be modified at runtime so can't make it constant - moduleInfoVar = new llvm::GlobalVariable(*gIR->module, moduleInfoType, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); - - return moduleInfoVar; -} - -// Put out instance of ModuleInfo for this Module - -void Module::genmoduleinfo() -{ - // resolve ModuleInfo - if (!moduleinfo) - { - error("object.d is missing the ModuleInfo class"); - fatal(); - } - // check for patch - else - { -#if DMDV2 - unsigned sizeof_ModuleInfo = 16 * PTRSIZE; -#else - unsigned sizeof_ModuleInfo = 14 * PTRSIZE; -#endif - if (sizeof_ModuleInfo != moduleinfo->structsize) - { - error("object.d ModuleInfo class is incorrect"); - fatal(); - } - } - - // use the RTTIBuilder - RTTIBuilder b(moduleinfo); - - // some types - LLType* moduleinfoTy = moduleinfo->type->irtype->getType(); - LLType* classinfoTy = ClassDeclaration::classinfo->type->irtype->getType(); - - // importedModules[] - std::vector importInits; - LLConstant* importedModules = 0; - llvm::ArrayType* importedModulesTy = 0; - for (size_t i = 0; i < aimports.dim; i++) - { - Module *m = (Module *)aimports.data[i]; - if (!m->needModuleInfo() || m == this) - continue; - - // declare the imported module info - std::string m_name("_D"); - m_name.append(m->mangle()); - m_name.append("8__ModuleZ"); - llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name); - if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name); - importInits.push_back(m_gvar); - } - // has import array? - if (!importInits.empty()) - { - importedModulesTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size()); - importedModules = LLConstantArray::get(importedModulesTy, importInits); - } - - // localClasses[] - LLConstant* localClasses = 0; - llvm::ArrayType* localClassesTy = 0; - ClassDeclarations aclasses; - //printf("members->dim = %d\n", members->dim); - for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *member; - - member = (Dsymbol *)members->data[i]; - //printf("\tmember '%s'\n", member->toChars()); - member->addLocalClass(&aclasses); - } - // fill inits - std::vector classInits; - for (size_t i = 0; i < aclasses.dim; i++) - { - ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i]; - cd->codegen(Type::sir); - - if (cd->isInterfaceDeclaration()) - { - Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars()); - continue; - } - else if (cd->sizeok != 1) - { - Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars()); - continue; - } - Logger::println("class: %s", cd->toPrettyChars()); - LLConstant *c = DtoBitCast(cd->ir.irStruct->getClassInfoSymbol(), getPtrToType(classinfoTy)); - classInits.push_back(c); - } - // has class array? - if (!classInits.empty()) - { - localClassesTy = llvm::ArrayType::get(getPtrToType(classinfoTy), classInits.size()); - localClasses = LLConstantArray::get(localClassesTy, classInits); - } - -#if NEW_MODULEINFO_LAYOUT - - // These must match the values in druntime/src/object_.d - #define MIstandalone 4 - #define MItlsctor 8 - #define MItlsdtor 0x10 - #define MIctor 0x20 - #define MIdtor 0x40 - #define MIxgetMembers 0x80 - #define MIictor 0x100 - #define MIunitTest 0x200 - #define MIimportedModules 0x400 - #define MIlocalClasses 0x800 - #define MInew 0x80000000 // it's the "new" layout - - llvm::Function* fsharedctor = build_module_shared_ctor(); - llvm::Function* fshareddtor = build_module_shared_dtor(); - llvm::Function* funittest = build_module_unittest(); - llvm::Function* fctor = build_module_ctor(); - llvm::Function* fdtor = build_module_dtor(); - - unsigned flags = MInew; - if (fctor) - flags |= MItlsctor; - if (fdtor) - flags |= MItlsdtor; - if (fsharedctor) - flags |= MIctor; - if (fshareddtor) - flags |= MIdtor; -#if 0 - if (fgetmembers) - flags |= MIxgetMembers; - if (fictor) - flags |= MIictor; -#endif - if (funittest) - flags |= MIunitTest; - if (importedModules) - flags |= MIimportedModules; - if (localClasses) - flags |= MIlocalClasses; - - if (!needmoduleinfo) - flags |= MIstandalone; - - b.push_uint(flags); // flags - b.push_uint(0); // index - - if (fctor) - b.push(fctor); - if (fdtor) - b.push(fdtor); - if (fsharedctor) - b.push(fsharedctor); - if (fshareddtor) - b.push(fshareddtor); -#if 0 - if (fgetmembers) - b.push(fgetmembers); - if (fictor) - b.push(fictor); -#endif - if (funittest) - b.push(funittest); - if (importedModules) { - b.push_size(importInits.size()); - b.push(importedModules); - } - if (localClasses) { - b.push_size(classInits.size()); - b.push(localClasses); - } - - // Put out module name as a 0-terminated string, to save bytes - b.push(DtoConstStringPtr(toPrettyChars())); - -#else - // The layout is: - // char[] name; - // ModuleInfo[] importedModules; - // ClassInfo[] localClasses; - // uint flags; - // - // void function() ctor; - // void function() dtor; - // void function() unitTest; - // - // void* xgetMembers; - // void function() ictor; - // - // version(D_Version2) { - // void *sharedctor; - // void *shareddtor; - // uint index; - // void*[1] reserved; - // } - - LLConstant *c = 0; - - // name - b.push_string(toPrettyChars()); - - // importedModules - if (importedModules) - { - std::string m_name("_D"); - m_name.append(mangle()); - m_name.append("9__importsZ"); - llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name); - if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, importedModulesTy, true, llvm::GlobalValue::InternalLinkage, importedModules, m_name); - c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(importedModulesTy->getElementType())); - c = DtoConstSlice(DtoConstSize_t(importInits.size()), c); - } - else - { - c = DtoConstSlice(DtoConstSize_t(0), getNullValue(getPtrToType(moduleinfoTy))); - } - b.push(c); - - // localClasses - if (localClasses) - { - std::string m_name("_D"); - m_name.append(mangle()); - m_name.append("9__classesZ"); - assert(gIR->module->getGlobalVariable(m_name) == NULL); - llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(*gIR->module, localClassesTy, true, llvm::GlobalValue::InternalLinkage, localClasses, m_name); - c = DtoGEPi(m_gvar, 0, 0); - c = DtoConstSlice(DtoConstSize_t(classInits.size()), c); - } - else - { - c = DtoConstSlice( DtoConstSize_t(0), getNullValue(getPtrToType(getPtrToType(classinfoTy))) ); - } - b.push(c); - - // flags (4 means MIstandalone) - unsigned mi_flags = needmoduleinfo ? 0 : 4; - b.push_uint(mi_flags); - - // function pointer type for next three fields - LLType* fnptrTy = getPtrToType(LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false)); - - // ctor -#if DMDV2 - llvm::Function* fctor = build_module_shared_ctor(); -#else - llvm::Function* fctor = build_module_ctor(); -#endif - c = fctor ? fctor : getNullValue(fnptrTy); - b.push(c); - - // dtor -#if DMDV2 - llvm::Function* fdtor = build_module_shared_dtor(); -#else - llvm::Function* fdtor = build_module_dtor(); -#endif - c = fdtor ? fdtor : getNullValue(fnptrTy); - b.push(c); - - // unitTest - llvm::Function* unittest = build_module_unittest(); - c = unittest ? unittest : getNullValue(fnptrTy); - b.push(c); - - // xgetMembers - c = getNullValue(getVoidPtrType()); - b.push(c); - - // ictor - c = getNullValue(fnptrTy); - b.push(c); - -#if DMDV2 - - // tls ctor - fctor = build_module_ctor(); - c = fctor ? fctor : getNullValue(fnptrTy); - b.push(c); - - // tls dtor - fdtor = build_module_dtor(); - c = fdtor ? fdtor : getNullValue(fnptrTy); - b.push(c); - - // index + reserved void*[1] - LLType* AT = llvm::ArrayType::get(getVoidPtrType(), 2); - c = getNullValue(AT); - b.push(c); - -#endif - -#endif - - /*Logger::println("MODULE INFO INITIALIZERS"); - for (size_t i=0; igetType() != moduleinfoTy->getElementType(i)) - assert(0); - }*/ - - // create and set initializer - b.finalize(moduleInfoType, moduleInfoSymbol()); - - // 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); -} +#include "gen/llvm.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Module.h" +#include "llvm/LinkAllPasses.h" + +#include "mars.h" +#include "module.h" +#include "mtype.h" +#include "declaration.h" +#include "statement.h" +#include "enum.h" +#include "aggregate.h" +#include "init.h" +#include "attrib.h" +#include "id.h" +#include "import.h" +#include "template.h" +#include "scope.h" + +#include "gen/abi.h" +#include "gen/arrays.h" +#include "gen/classes.h" +#include "gen/cl_options.h" +#include "gen/functions.h" +#include "gen/llvmhelpers.h" +#include "gen/logger.h" +#include "gen/programs.h" +#include "gen/rttibuilder.h" +#include "gen/runtime.h" +#include "gen/structs.h" +#include "gen/todebug.h" +#include "gen/tollvm.h" + +#include "ir/irvar.h" +#include "ir/irmodule.h" +#include "ir/irtype.h" + +#if DMDV2 +#define NEW_MODULEINFO_LAYOUT 1 +#endif + +////////////////////////////////////////////////////////////////////////////////////////// + +llvm::cl::opt noVerify("noverify", + llvm::cl::desc("Do not run the validation pass before writing bitcode"), + llvm::cl::ZeroOrMore); + +////////////////////////////////////////////////////////////////////////////////////////// + +static llvm::Function* build_module_function(const std::string &name, const std::list &funcs, + const std::list &gates = std::list()) +{ + if (gates.empty()) { + if (funcs.empty()) + return NULL; + + if (funcs.size() == 1) + return funcs.front()->ir.irFunc->func; + } + + 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); + fn->setCallingConv(DtoCallingConv(0, LINKd)); + + llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); + IRBuilder<> builder(bb); + + // debug info + DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); + + // Call ctor's + typedef std::list::const_iterator FuncIterator; + for (FuncIterator itr = funcs.begin(), end = funcs.end(); itr != end; ++itr) { + llvm::Function* f = (*itr)->ir.irFunc->func; + llvm::CallInst* call = builder.CreateCall(f,""); + call->setCallingConv(DtoCallingConv(0, LINKd)); + } + + // Increment vgate's + typedef std::list::const_iterator GatesIterator; + for (GatesIterator itr = gates.begin(), end = gates.end(); itr != end; ++itr) { + assert((*itr)->ir.irGlobal); + llvm::Value* val = (*itr)->ir.irGlobal->value; + llvm::Value* rval = builder.CreateLoad(val, "vgate"); + llvm::Value* res = builder.CreateAdd(rval, DtoConstUint(1), "vgate"); + builder.CreateStore(res, val); + } + + builder.CreateRetVoid(); + return fn; +} + +// build module ctor + +llvm::Function* build_module_ctor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("6__ctorZ"); +#if DMDV2 + return build_module_function(name, gIR->ctors, gIR->gates); +#else + return build_module_function(name, gIR->ctors); +#endif +} + +// build module dtor + +static llvm::Function* build_module_dtor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("6__dtorZ"); + return build_module_function(name, gIR->dtors); +} + +// build module unittest + +static llvm::Function* build_module_unittest() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("10__unittestZ"); + return build_module_function(name, gIR->unitTests); +} + +#if DMDV2 + +// build module shared ctor + +llvm::Function* build_module_shared_ctor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("13__shared_ctorZ"); + return build_module_function(name, gIR->sharedCtors, gIR->sharedGates); +} + +// build module shared dtor + +static llvm::Function* build_module_shared_dtor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("13__shared_dtorZ"); + return build_module_function(name, gIR->sharedDtors); +} + +#endif + +// build ModuleReference and register function, to register the module info in the global linked list +static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) +{ + // build ctor type + LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); + + // build ctor name + std::string fname = "_D"; + fname += gIR->dmodule->mangle(); + fname += "16__moduleinfoCtorZ"; + + // build a function that registers the moduleinfo in the global moduleinfo linked list + LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, gIR->module); + + // provide the default initializer + LLStructType* modulerefTy = DtoModuleReferenceType(); + std::vector mrefvalues; + mrefvalues.push_back(LLConstant::getNullValue(modulerefTy->getContainedType(0))); + mrefvalues.push_back(llvm::ConstantExpr::getBitCast(moduleinfo, modulerefTy->getContainedType(1))); + LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, mrefvalues); + + // create the ModuleReference node for this module + std::string thismrefname = "_D"; + thismrefname += gIR->dmodule->mangle(); + thismrefname += "11__moduleRefZ"; + LLGlobalVariable* thismref = new LLGlobalVariable(*gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, thismrefname); + + // make sure _Dmodule_ref is declared + LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref"); + LLType *modulerefPtrTy = getPtrToType(modulerefTy); + if (!mref) + mref = new LLGlobalVariable(*gIR->module, modulerefPtrTy, false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref"); + mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy)); + + // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list + llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "moduleinfoCtorEntry", ctor); + IRBuilder<> builder(bb); + + // debug info + llvm::DISubprogram subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()); + + // get current beginning + LLValue* curbeg = builder.CreateLoad(mref, "current"); + + // put current beginning as the next of this one + LLValue* gep = builder.CreateStructGEP(thismref, 0, "next"); + builder.CreateStore(curbeg, gep); + + // replace beginning + builder.CreateStore(thismref, mref); + + // return + builder.CreateRetVoid(); + + return ctor; +} + +llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) +{ + bool logenabled = Logger::enabled(); + if (llvmForceLogging && !logenabled) + { + Logger::enable(); + } + + Logger::println("Generating module: %s\n", (md ? md->toChars() : toChars())); + LOG_SCOPE; + + if (global.params.verbose_cg) + printf("codegen: %s (%s)\n", toPrettyChars(), srcfile->toChars()); + + assert(!global.errors); + + // name the module + llvm::StringRef mname(toChars()); + if (md != 0) + mname = md->toChars(); + + // create a new ir state + // TODO look at making the instance static and moving most functionality into IrModule where it belongs + IRState ir(new llvm::Module(mname, context)); + gIR = &ir; + ir.dmodule = this; + + // reset all IR data stored in Dsymbols + IrDsymbol::resetAll(); + + sir->setState(&ir); + + // set target triple + ir.module->setTargetTriple(global.params.targetTriple); + + // set final data layout + ir.module->setDataLayout(global.params.dataLayout); + if (Logger::enabled()) + Logger::cout() << "Final data layout: " << global.params.dataLayout << '\n'; + + // allocate the target abi + gABI = TargetABI::getTarget(); + + // debug info + DtoDwarfCompileUnit(this); + + // handle invalid 'objectø module + if (!ClassDeclaration::object) { + error("is missing 'class Object'"); + fatal(); + } + if (!ClassDeclaration::classinfo) { + error("is missing 'class ClassInfo'"); + fatal(); + } + + LLVM_D_InitRuntime(); + + // process module members + for (unsigned k=0; k < members->dim; k++) { + Dsymbol* dsym = (Dsymbol*)(members->data[k]); + assert(dsym); + dsym->codegen(sir); + } + + // emit function bodies + sir->emitFunctionBodies(); + + // for singleobj-compilation, fully emit all seen template instances + if (opts::singleObj) + { + while (!ir.seenTemplateInstances.empty()) + { + IRState::TemplateInstanceSet::iterator it, end = ir.seenTemplateInstances.end(); + for (it = ir.seenTemplateInstances.begin(); it != end; ++it) + (*it)->codegen(sir); + ir.seenTemplateInstances.clear(); + + // emit any newly added function bodies + sir->emitFunctionBodies(); + } + } + + // finilize debug info + DtoDwarfModuleEnd(); + + // generate ModuleInfo + genmoduleinfo(); + + // verify the llvm + if (!noVerify) { + std::string verifyErr; + Logger::println("Verifying module..."); + LOG_SCOPE; + if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) + { + error("%s", verifyErr.c_str()); + fatal(); + } + else { + Logger::println("Verification passed!"); + } + } + + gIR = NULL; + + if (llvmForceLogging && !logenabled) + { + Logger::disable(); + } + + sir->setState(NULL); + + return ir.module; +} + +llvm::GlobalVariable* Module::moduleInfoSymbol() +{ + // create name + std::string MIname("_D"); + MIname.append(mangle()); + MIname.append("8__ModuleZ"); + + if (gIR->dmodule != this) { + LLType* moduleinfoTy = DtoType(moduleinfo->type); + LLGlobalVariable *var = gIR->module->getGlobalVariable(MIname); + if (!var) + var = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); + return var; + } + + if (moduleInfoVar) + return moduleInfoVar; + + // declare global + // flags will be modified at runtime so can't make it constant + moduleInfoVar = new llvm::GlobalVariable(*gIR->module, moduleInfoType, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); + + return moduleInfoVar; +} + +// Put out instance of ModuleInfo for this Module +void Module::genmoduleinfo() +{ + // resolve ModuleInfo + if (!moduleinfo) + { + error("object.d is missing the ModuleInfo class"); + fatal(); + } + // check for patch + else + { +#if DMDV2 + unsigned sizeof_ModuleInfo = 16 * PTRSIZE; +#else + unsigned sizeof_ModuleInfo = 14 * PTRSIZE; +#endif + if (sizeof_ModuleInfo != moduleinfo->structsize) + { + error("object.d ModuleInfo class is incorrect"); + fatal(); + } + } + + // use the RTTIBuilder + RTTIBuilder b(moduleinfo); + + // some types + LLType* moduleinfoTy = moduleinfo->type->irtype->getType(); + LLType* classinfoTy = ClassDeclaration::classinfo->type->irtype->getType(); + + // importedModules[] + std::vector importInits; + LLConstant* importedModules = 0; + llvm::ArrayType* importedModulesTy = 0; + for (size_t i = 0; i < aimports.dim; i++) + { + Module *m = (Module *)aimports.data[i]; + if (!m->needModuleInfo() || m == this) + continue; + + // declare the imported module info + std::string m_name("_D"); + m_name.append(m->mangle()); + m_name.append("8__ModuleZ"); + llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name); + if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name); + importInits.push_back(m_gvar); + } + // has import array? + if (!importInits.empty()) + { + importedModulesTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size()); + importedModules = LLConstantArray::get(importedModulesTy, importInits); + } + + // localClasses[] + LLConstant* localClasses = 0; + llvm::ArrayType* localClassesTy = 0; + ClassDeclarations aclasses; + //printf("members->dim = %d\n", members->dim); + for (size_t i = 0; i < members->dim; i++) + { + Dsymbol *member; + + member = (Dsymbol *)members->data[i]; + //printf("\tmember '%s'\n", member->toChars()); + member->addLocalClass(&aclasses); + } + // fill inits + std::vector classInits; + for (size_t i = 0; i < aclasses.dim; i++) + { + ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i]; + cd->codegen(Type::sir); + + if (cd->isInterfaceDeclaration()) + { + Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars()); + continue; + } + else if (cd->sizeok != 1) + { + Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars()); + continue; + } + Logger::println("class: %s", cd->toPrettyChars()); + LLConstant *c = DtoBitCast(cd->ir.irStruct->getClassInfoSymbol(), getPtrToType(classinfoTy)); + classInits.push_back(c); + } + // has class array? + if (!classInits.empty()) + { + localClassesTy = llvm::ArrayType::get(getPtrToType(classinfoTy), classInits.size()); + localClasses = LLConstantArray::get(localClassesTy, classInits); + } + +#if NEW_MODULEINFO_LAYOUT + + // These must match the values in druntime/src/object_.d + #define MIstandalone 4 + #define MItlsctor 8 + #define MItlsdtor 0x10 + #define MIctor 0x20 + #define MIdtor 0x40 + #define MIxgetMembers 0x80 + #define MIictor 0x100 + #define MIunitTest 0x200 + #define MIimportedModules 0x400 + #define MIlocalClasses 0x800 + #define MInew 0x80000000 // it's the "new" layout + + llvm::Function* fsharedctor = build_module_shared_ctor(); + llvm::Function* fshareddtor = build_module_shared_dtor(); + llvm::Function* funittest = build_module_unittest(); + llvm::Function* fctor = build_module_ctor(); + llvm::Function* fdtor = build_module_dtor(); + + unsigned flags = MInew; + if (fctor) + flags |= MItlsctor; + if (fdtor) + flags |= MItlsdtor; + if (fsharedctor) + flags |= MIctor; + if (fshareddtor) + flags |= MIdtor; +#if 0 + if (fgetmembers) + flags |= MIxgetMembers; + if (fictor) + flags |= MIictor; +#endif + if (funittest) + flags |= MIunitTest; + if (importedModules) + flags |= MIimportedModules; + if (localClasses) + flags |= MIlocalClasses; + + if (!needmoduleinfo) + flags |= MIstandalone; + + b.push_uint(flags); // flags + b.push_uint(0); // index + + if (fctor) + b.push(fctor); + if (fdtor) + b.push(fdtor); + if (fsharedctor) + b.push(fsharedctor); + if (fshareddtor) + b.push(fshareddtor); +#if 0 + if (fgetmembers) + b.push(fgetmembers); + if (fictor) + b.push(fictor); +#endif + if (funittest) + b.push(funittest); + if (importedModules) { + b.push_size(importInits.size()); + b.push(importedModules); + } + if (localClasses) { + b.push_size(classInits.size()); + b.push(localClasses); + } + + // Put out module name as a 0-terminated string, to save bytes + b.push(DtoConstStringPtr(toPrettyChars())); + +#else + // The layout is: + // char[] name; + // ModuleInfo[] importedModules; + // ClassInfo[] localClasses; + // uint flags; + // + // void function() ctor; + // void function() dtor; + // void function() unitTest; + // + // void* xgetMembers; + // void function() ictor; + // + // version(D_Version2) { + // void *sharedctor; + // void *shareddtor; + // uint index; + // void*[1] reserved; + // } + + LLConstant *c = 0; + + // name + b.push_string(toPrettyChars()); + + // importedModules + if (importedModules) + { + std::string m_name("_D"); + m_name.append(mangle()); + m_name.append("9__importsZ"); + llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name); + if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, importedModulesTy, true, llvm::GlobalValue::InternalLinkage, importedModules, m_name); + c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(importedModulesTy->getElementType())); + c = DtoConstSlice(DtoConstSize_t(importInits.size()), c); + } + else + { + c = DtoConstSlice(DtoConstSize_t(0), getNullValue(getPtrToType(moduleinfoTy))); + } + b.push(c); + + // localClasses + if (localClasses) + { + std::string m_name("_D"); + m_name.append(mangle()); + m_name.append("9__classesZ"); + assert(gIR->module->getGlobalVariable(m_name) == NULL); + llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(*gIR->module, localClassesTy, true, llvm::GlobalValue::InternalLinkage, localClasses, m_name); + c = DtoGEPi(m_gvar, 0, 0); + c = DtoConstSlice(DtoConstSize_t(classInits.size()), c); + } + else + { + c = DtoConstSlice( DtoConstSize_t(0), getNullValue(getPtrToType(getPtrToType(classinfoTy))) ); + } + b.push(c); + + // flags (4 means MIstandalone) + unsigned mi_flags = needmoduleinfo ? 0 : 4; + b.push_uint(mi_flags); + + // function pointer type for next three fields + LLType* fnptrTy = getPtrToType(LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false)); + + // ctor +#if DMDV2 + llvm::Function* fctor = build_module_shared_ctor(); +#else + llvm::Function* fctor = build_module_ctor(); +#endif + c = fctor ? fctor : getNullValue(fnptrTy); + b.push(c); + + // dtor +#if DMDV2 + llvm::Function* fdtor = build_module_shared_dtor(); +#else + llvm::Function* fdtor = build_module_dtor(); +#endif + c = fdtor ? fdtor : getNullValue(fnptrTy); + b.push(c); + + // unitTest + llvm::Function* unittest = build_module_unittest(); + c = unittest ? unittest : getNullValue(fnptrTy); + b.push(c); + + // xgetMembers + c = getNullValue(getVoidPtrType()); + b.push(c); + + // ictor + c = getNullValue(fnptrTy); + b.push(c); + +#if DMDV2 + + // tls ctor + fctor = build_module_ctor(); + c = fctor ? fctor : getNullValue(fnptrTy); + b.push(c); + + // tls dtor + fdtor = build_module_dtor(); + c = fdtor ? fdtor : getNullValue(fnptrTy); + b.push(c); + + // index + reserved void*[1] + LLType* AT = llvm::ArrayType::get(getVoidPtrType(), 2); + c = getNullValue(AT); + b.push(c); + +#endif + +#endif + + /*Logger::println("MODULE INFO INITIALIZERS"); + for (size_t i=0; igetType() != moduleinfoTy->getElementType(i)) + assert(0); + }*/ + + // create and set initializer + b.finalize(moduleInfoType, moduleInfoSymbol()); + + // 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); +} From feefad412c8ce7c73d753516483e74f4150fa881 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Mon, 2 Apr 2012 14:53:52 +0100 Subject: [PATCH 3/6] Move cl_options out of LDCShared --- dmd2/mars.h | 5 +++++ {gen => driver}/cl_options.cpp | 14 +++++++++----- {gen => driver}/cl_options.h | 4 ++-- {gen => driver}/linker.cpp | 5 +++-- {gen => driver}/linker.h | 0 driver/main.cpp | 4 ++-- driver/toobj.cpp | 8 +------- gen/arrays.cpp | 2 -- gen/functions.cpp | 3 +-- gen/linkage.cpp | 1 - gen/llvmhelpers.cpp | 3 +-- gen/module.cpp | 12 ++---------- 12 files changed, 26 insertions(+), 35 deletions(-) rename {gen => driver}/cl_options.cpp (96%) rename {gen => driver}/cl_options.h (95%) rename {gen => driver}/linker.cpp (99%) rename {gen => driver}/linker.h (100%) diff --git a/dmd2/mars.h b/dmd2/mars.h index dc640308..81d42059 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -272,6 +272,11 @@ struct Param const char* llvmArch; const char *targetTriple; const char *dataLayout; + + // Codegen cl options + bool singleObj; + bool disableRedZone; + bool noVerify; #endif }; diff --git a/gen/cl_options.cpp b/driver/cl_options.cpp similarity index 96% rename from gen/cl_options.cpp rename to driver/cl_options.cpp index a869620f..4374aa33 100644 --- a/gen/cl_options.cpp +++ b/driver/cl_options.cpp @@ -1,4 +1,4 @@ -#include "gen/cl_options.h" +#include "driver/cl_options.h" #include "gen/cl_helpers.h" #include "llvm/Target/TargetMachine.h" @@ -132,8 +132,9 @@ cl::opt output_o("output-o", cl::desc("Write native object")); // Disabling Red Zone -cl::opt disableRedZone("disable-red-zone", +cl::opt disableRedZone("disable-red-zone", cl::desc("Do not emit code that uses the red zone."), + cl::location(global.params.disableRedZone), cl::init(false)); // DDoc options @@ -360,7 +361,7 @@ static cl::opt postconditions("postconditions", cl::init(true)); -static MultiSetter ContractsSetter(false, +static MultiSetter ContractsSetter(false, &global.params.useIn, &global.params.useOut, NULL); static cl::opt contracts("contracts", cl::desc("(*) Enable function pre- and post-conditions"), @@ -374,10 +375,13 @@ static cl::opt > release("release", cl::location(ReleaseSetter), cl::ValueDisallowed); +cl::opt noVerify("noverify", + llvm::cl::desc("Do not run the validation pass before writing bitcode"), + cl::location(global.params.noVerify)); -cl::opt singleObj("singleobj", +cl::opt singleObj("singleobj", cl::desc("Create only a single output object file"), - cl::ZeroOrMore); + cl::location(global.params.singleObj)); cl::opt linkonceTemplates("linkonce-templates", cl::desc("Use linkonce_odr linkage for template symbols instead of weak_odr"), diff --git a/gen/cl_options.h b/driver/cl_options.h similarity index 95% rename from gen/cl_options.h rename to driver/cl_options.h index 53392e36..2fed81b0 100644 --- a/gen/cl_options.h +++ b/driver/cl_options.h @@ -33,7 +33,7 @@ namespace opts { extern cl::opt output_ll; extern cl::opt output_s; extern cl::opt output_o; - extern cl::opt disableRedZone; + extern cl::opt disableRedZone; extern cl::opt ddocDir; extern cl::opt ddocFile; extern cl::opt jsonFile; @@ -50,7 +50,7 @@ namespace opts { extern cl::opt mTargetTriple; extern cl::opt mRelocModel; extern cl::opt mCodeModel; - extern cl::opt singleObj; + extern cl::opt singleObj; extern cl::opt linkonceTemplates; // Arguments to -d-debug diff --git a/gen/linker.cpp b/driver/linker.cpp similarity index 99% rename from gen/linker.cpp rename to driver/linker.cpp index 33bf2c5c..8d189763 100644 --- a/gen/linker.cpp +++ b/driver/linker.cpp @@ -1,4 +1,3 @@ -#include "gen/linker.h" #include "gen/llvm.h" #include "llvm/Linker.h" #include "llvm/Support/FileSystem.h" @@ -13,10 +12,12 @@ #define NO_COUT_LOGGER #include "gen/logger.h" -#include "gen/cl_options.h" #include "gen/optimizer.h" #include "gen/programs.h" +#include "driver/linker.h" +#include "driver/cl_options.h" + ////////////////////////////////////////////////////////////////////////////// // Is this useful? diff --git a/gen/linker.h b/driver/linker.h similarity index 100% rename from gen/linker.h rename to driver/linker.h diff --git a/driver/main.cpp b/driver/main.cpp index 50f8ba03..633f7dc5 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -30,13 +30,13 @@ #include "gen/logger.h" #include "gen/linkage.h" -#include "gen/linker.h" #include "gen/irstate.h" #include "gen/optimizer.h" #include "gen/metadata.h" #include "gen/passes/Passes.h" -#include "gen/cl_options.h" +#include "driver/linker.h" +#include "driver/cl_options.h" #include "gen/cl_helpers.h" using namespace opts; diff --git a/driver/toobj.cpp b/driver/toobj.cpp index 98ce6abc..bdcb8982 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -24,12 +24,6 @@ #include "gen/optimizer.h" -////////////////////////////////////////////////////////////////////////////////////////// - -extern llvm::cl::opt noVerify; - -////////////////////////////////////////////////////////////////////////////////////////// - // fwd decl void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out, llvm::TargetMachine::CodeGenFileType fileType); @@ -42,7 +36,7 @@ void writeModule(llvm::Module* m, std::string filename) bool reverify = ldc_optimize_module(m); // verify the llvm - if (!noVerify && reverify) { + if (!global.params.noVerify && reverify) { std::string verifyErr; Logger::println("Verifying module... again..."); LOG_SCOPE; diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 62b97266..b5adde87 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -17,8 +17,6 @@ #include "ir/irmodule.h" #include "ir/irtypestruct.h" -#include "gen/cl_options.h" - ////////////////////////////////////////////////////////////////////////////////////////// static LLValue *DtoSlice(DValue *dval) diff --git a/gen/functions.cpp b/gen/functions.cpp index 72c4c342..d7946fa8 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -23,7 +23,6 @@ #include "gen/dvalue.h" #include "gen/abi.h" #include "gen/nested.h" -#include "gen/cl_options.h" #include "gen/pragma.h" using namespace llvm::Attribute; @@ -510,7 +509,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) // parameter attributes if (!fdecl->isIntrinsic()) { set_param_attrs(f, func, fdecl); - if (opts::disableRedZone) { + if (global.params.disableRedZone) { func->addFnAttr(NoRedZone); } } diff --git a/gen/linkage.cpp b/gen/linkage.cpp index 62853374..ba77f90f 100644 --- a/gen/linkage.cpp +++ b/gen/linkage.cpp @@ -1,4 +1,3 @@ #include "linkage.h" -#include "gen/cl_options.h" LLGlobalValue::LinkageTypes templateLinkage; diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 17b7119a..6584e7cd 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -22,7 +22,6 @@ #include "gen/functions.h" #include "gen/typeinf.h" #include "gen/todebug.h" -#include "gen/cl_options.h" #include "gen/nested.h" #include "ir/irmodule.h" @@ -1649,7 +1648,7 @@ bool mustDefineSymbol(Dsymbol* s) TemplateInstance* tinst = DtoIsTemplateInstance(s); if (tinst) { - if (!opts::singleObj) + if (!global.params.singleObj) return true; if (!tinst->emittedInModule) diff --git a/gen/module.cpp b/gen/module.cpp index e17d35ee..fc3ca84b 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -20,7 +20,6 @@ #include "gen/abi.h" #include "gen/arrays.h" #include "gen/classes.h" -#include "gen/cl_options.h" #include "gen/functions.h" #include "gen/llvmhelpers.h" #include "gen/logger.h" @@ -39,13 +38,6 @@ #define NEW_MODULEINFO_LAYOUT 1 #endif -////////////////////////////////////////////////////////////////////////////////////////// - -llvm::cl::opt noVerify("noverify", - llvm::cl::desc("Do not run the validation pass before writing bitcode"), - llvm::cl::ZeroOrMore); - -////////////////////////////////////////////////////////////////////////////////////////// static llvm::Function* build_module_function(const std::string &name, const std::list &funcs, const std::list &gates = std::list()) @@ -276,7 +268,7 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) sir->emitFunctionBodies(); // for singleobj-compilation, fully emit all seen template instances - if (opts::singleObj) + if (global.params.singleObj) { while (!ir.seenTemplateInstances.empty()) { @@ -297,7 +289,7 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) genmoduleinfo(); // verify the llvm - if (!noVerify) { + if (!global.params.noVerify) { std::string verifyErr; Logger::println("Verifying module..."); LOG_SCOPE; From 30b20794c7fd414b19cad6b913112924d5a0ee48 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Mon, 2 Apr 2012 16:43:46 +0100 Subject: [PATCH 4/6] Fix D1 frontend --- dmd/mars.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dmd/mars.h b/dmd/mars.h index bc9263fa..53b61d83 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -306,6 +306,11 @@ struct Param const char* llvmArch; const char *targetTriple; const char *dataLayout; + + // Codegen cl options + bool singleObj; + bool disableRedZone; + bool noVerify; #endif }; From a8398d64e829b31ad0be7d53706fcfb7ceb16a0d Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Tue, 3 Apr 2012 21:18:16 +0100 Subject: [PATCH 5/6] Moved configfile to the driver --- CMakeLists.txt | 7 +++---- {gen => driver}/configfile.cpp | 2 +- {gen => driver}/configfile.h | 0 driver/main.cpp | 3 +-- 4 files changed, 5 insertions(+), 7 deletions(-) rename {gen => driver}/configfile.cpp (99%) rename {gen => driver}/configfile.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a5f6b82..6936adac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -268,8 +268,6 @@ endif(USE_METADATA) # Set up the main ldc/ldc2 target. # set(LDC_LIB LDCShared) - -# Path where ldc executable will be put add_library(${LDC_LIB} SHARED ${LDC_SOURCE_FILES}) # Build ldc set_target_properties( @@ -280,7 +278,7 @@ set_target_properties( ) # LDFLAGS should actually be in target property LINK_FLAGS, but this works, and gets around linking problems -target_link_libraries(${LDC_LIB} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES}" ${LIBCONFIG_LDFLAGS} config++) +target_link_libraries(${LDC_LIB} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES}") if(WIN32) target_link_libraries(${LDC_LIB} imagehlp psapi) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") @@ -291,6 +289,7 @@ if(USE_BOEHM_GC) target_link_libraries(${LDC_LIB} ${PROJECT_SOURCE_DIR}/libgc.a) endif(USE_BOEHM_GC) +# Path where ldc executable will be put add_executable(${LDC_EXE} ${DRV_SRC}) # Name of ldc executable set(LDC_EXE_NAME ${PROGRAM_PREFIX}${LDC_EXE}${PROGRAM_SUFFIX}) @@ -301,7 +300,7 @@ set_target_properties( RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin COMPILE_FLAGS "${LLVM_CXXFLAGS} ${LIBCONFIG_CXXFLAGS} -Wno-deprecated -Wno-write-strings -fexceptions" ) -target_link_libraries(${LDC_EXE} ${LDC_LIB}) +target_link_libraries(${LDC_EXE} ${LDC_LIB} ${LIBCONFIG_LDFLAGS} config++) get_target_property(LDC_LOC ${LDC_EXE} LOCATION) diff --git a/gen/configfile.cpp b/driver/configfile.cpp similarity index 99% rename from gen/configfile.cpp rename to driver/configfile.cpp index 7796d382..5adc2653 100644 --- a/gen/configfile.cpp +++ b/driver/configfile.cpp @@ -8,7 +8,7 @@ #include "libconfig.h++" -#include "gen/configfile.h" +#include "driver/configfile.h" #include "mars.h" diff --git a/gen/configfile.h b/driver/configfile.h similarity index 100% rename from gen/configfile.h rename to driver/configfile.h diff --git a/driver/main.cpp b/driver/main.cpp index 633f7dc5..19c40f6f 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -40,8 +40,7 @@ #include "gen/cl_helpers.h" using namespace opts; -#include "gen/configfile.h" - +#include "driver/configfile.h" #include "driver/toobj.h" #if POSIX From 36d4a57297fccb267eb854ddbfc7370a9e1012a8 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Sat, 7 Apr 2012 14:12:10 +0100 Subject: [PATCH 6/6] Default to building ldc as a static library. Added BUILD_SHARED flag to enable dynamic libraries --- CMakeLists.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6936adac..e4065d0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -267,13 +267,23 @@ endif(USE_METADATA) # # Set up the main ldc/ldc2 target. # +if(BUILD_SHARED) + set(LDC_LIB_TYPE SHARED) +else(BUILD_SHARED) + set(LDC_LIB_TYPE STATIC) +endif(BUILD_SHARED) + set(LDC_LIB LDCShared) -add_library(${LDC_LIB} SHARED ${LDC_SOURCE_FILES}) +add_library(${LDC_LIB} ${LDC_LIB_TYPE} ${LDC_SOURCE_FILES}) # Build ldc set_target_properties( ${LDC_LIB} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib + ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib + ARCHIVE_OUTPUT_NAME ldc + LIBRARY_OUTPUT_NAME ldc + RUNTIME_OUTPUT_NAME ldc COMPILE_FLAGS "${LLVM_CXXFLAGS} ${LIBCONFIG_CXXFLAGS} -Wno-deprecated -Wno-write-strings -fexceptions" )