diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c4f7690..ee25577d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,12 +59,7 @@ endif (NOT DEFINED SYSCONF_INSTALL_DIR) set(D_VERSION 2 CACHE STRING "D language version") set(PROGRAM_PREFIX "" CACHE STRING "prepended to ldc binary name") set(PROGRAM_SUFFIX "" CACHE STRING "appended to ldc binary name") -set(LIB_SUFFIX "" CACHE STRING "take empty string or 64. Directory where lib will be installed: lib or lib64") -set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX} CACHE PATH "Directory where lib will be installed") set(CONF_INST_DIR ${SYSCONF_INSTALL_DIR} CACHE PATH "Set ldc.conf directory for installation") -set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX} CACHE PATH "output dir for built libraries") -set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/d CACHE PATH "Directory where will be put header files") -set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build as shared library or as static library") option(USE_BOEHM_GC "use the Boehm garbage collector internally") option(GENERATE_OFFTI "generate complete ClassInfo.offTi arrays") option(USE_METADATA "use metadata and related custom optimization passes") @@ -210,7 +205,6 @@ add_definitions( -DIN_LLVM -D_DH -DOPAQUE_VTBLS - #-DDISABLE_DEBUG_INFO -DLDC_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}" ) @@ -268,16 +262,7 @@ install(TARGETS ${LDC_EXE} 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) -if(D_VERSION EQUAL 2) - install(DIRECTORY ${PROJECT_BINARY_DIR}/runtime/import/core DESTINATION ${INCLUDE_INSTALL_DIR}) - install(DIRECTORY ${PROJECT_SOURCE_DIR}/phobos DESTINATION ${INCLUDE_INSTALL_DIR} PATTERN ".git" EXCLUDE ) - install(DIRECTORY ${LIBRARY_OUTPUT_PATH} DESTINATION ${CMAKE_INSTALL_PREFIX} USE_SOURCE_PERMISSIONS) - install(FILES ${PROJECT_SOURCE_DIR}/${RUNTIME}/import/object.di DESTINATION ${INCLUDE_INSTALL_DIR}/ldc) - install(DIRECTORY ${PROJECT_SOURCE_DIR}/${RUNTIME}/import/ldc DESTINATION ${INCLUDE_INSTALL_DIR}) -else(D_VERSION EQUAL 2) - install(DIRECTORY ${PROJECT_SOURCE_DIR}/${RUNTIME}/internal/ldc/ DESTINATION ${INCLUDE_INSTALL_DIR}/ldc) - install(DIRECTORY ${PROJECT_SOURCE_DIR}/runtime/import/ldc DESTINATION ${INCLUDE_INSTALL_DIR}) -endif(D_VERSION EQUAL 2) + if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") install(DIRECTORY bash_completion.d DESTINATION ${CONF_INST_DIR}) endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") diff --git a/dmd/mars.c b/dmd/mars.c index b27520c4..c7e8db93 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -61,7 +61,7 @@ Global::Global() written = "written by Walter Bright and Tomas Lindquist Olsen"; version = "v1.067"; ldc_version = "LDC trunk"; - llvm_version = "LLVM 2.9"; + llvm_version = "LLVM 3.0"; global.structalign = 8; // This should only be used as a global, so the other fields are diff --git a/dmd/mem.c b/dmd/mem.c index 3660cd85..35aec3cf 100644 --- a/dmd/mem.c +++ b/dmd/mem.c @@ -262,4 +262,8 @@ void Mem::mark(void *pointer) { } +void Mem::setStackBottom(void */*stackbottom*/) +{ +} + #endif // USE_BOEHM_GC diff --git a/dmd2/declaration.h b/dmd2/declaration.h index ddf0758a..1c3431df 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -361,6 +361,7 @@ struct VarDeclaration : Declaration // debug description llvm::DIVariable debugVariable; + llvm::DISubprogram debugFunc; #endif }; diff --git a/dmd2/mars.c b/dmd2/mars.c index 59ffa92e..f05ea012 100644 --- a/dmd2/mars.c +++ b/dmd2/mars.c @@ -103,7 +103,7 @@ Global::Global() version = "v2.056"; #if IN_LLVM ldc_version = "LDC trunk"; - llvm_version = "LLVM 2.9"; + llvm_version = "LLVM 3.0"; #endif global.structalign = 8; diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 0bae1993..62b97266 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -758,9 +758,8 @@ void DtoCatAssignElement(Loc& loc, Type* arrayType, DValue* array, Expression* e LLValue* appendedArray = gIR->CreateCallOrInvoke(fn, args, ".appendedArray").getInstruction(); appendedArray = DtoAggrPaint(appendedArray, DtoType(arrayType)); - LLValue* val = DtoExtractValue(appendedArray, 1, ".ptr"); + LLValue* val = DtoArrayPtr(array); val = DtoGEP1(val, oldLength, "lastElem"); - val = DtoBitCast(val, DtoType(arrayType->nextOf()->pointerTo())); DtoAssign(loc, new DVarValue(arrayType->nextOf(), val), expVal); callPostblit(loc, exp, val); } diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index 2c41e106..d0615348 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -211,14 +211,11 @@ AsmStatement::toIR(IRState * irs) IRAsmBlock* asmblock = irs->asmBlock; assert(asmblock); - #ifndef DISABLE_DEBUG_INFO // debug info - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + DtoDwarfStopPoint(loc.linnum); - if (! asmcode) - return; + if (!asmcode) + return; static std::string i_cns = "i"; static std::string p_cns = "i"; diff --git a/gen/classes.cpp b/gen/classes.cpp index a8fb39f7..30c1296f 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -293,7 +293,7 @@ DValue* DtoCastClass(DValue* val, Type* _to) // get the from class ClassDeclaration* cd = fc->sym->isClassDeclaration(); DtoResolveClass(cd); // add this - IrTypeClass* typeclass = fc->irtype->isClass(); + IrTypeClass* typeclass = stripModifiers(fc)->irtype->isClass(); // find interface impl diff --git a/gen/declarations.cpp b/gen/declarations.cpp index b985ddee..b3cd6f3a 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -174,11 +174,8 @@ void VarDeclaration::codegen(Ir* p) ir.irGlobal->constInit = initVal; gvar->setInitializer(initVal); - #ifndef DISABLE_DEBUG_INFO // do debug info - if (global.params.symdebug) - DtoDwarfGlobalVariable(gvar, this); - #endif + DtoDwarfGlobalVariable(gvar, this); } } } diff --git a/gen/functions.cpp b/gen/functions.cpp index be8b1f11..5188dd0f 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -642,11 +642,8 @@ void DtoDefineFunction(FuncDeclaration* fd) return; } - #ifndef DISABLE_DEBUG_INFO // debug info - if (global.params.symdebug) - fd->ir.irFunc->diSubprogram = DtoDwarfSubProgram(fd); - #endif + fd->ir.irFunc->diSubprogram = DtoDwarfSubProgram(fd); Type* t = fd->type->toBasetype(); TypeFunction* f = (TypeFunction*)t; @@ -685,10 +682,8 @@ void DtoDefineFunction(FuncDeclaration* fd) llvm::Instruction* allocaPoint = new llvm::AllocaInst(LLType::getInt32Ty(gIR->context()), "alloca point", beginbb); irfunction->allocapoint = allocaPoint; - #ifndef DISABLE_DEBUG_INFO // debug info - after all allocas, but before any llvm.dbg.declare etc - if (global.params.symdebug) DtoDwarfFuncStart(fd); - #endif + DtoDwarfFuncStart(fd); // this hack makes sure the frame pointer elimination optimization is disabled. // this this eliminates a bunch of inline asm related issues. @@ -716,10 +711,7 @@ void DtoDefineFunction(FuncDeclaration* fd) fd->vthis->ir.irLocal = new IrLocal(fd->vthis); fd->vthis->ir.irLocal->value = thismem; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfLocalVariable(thismem, fd->vthis); - #endif + DtoDwarfLocalVariable(thismem, fd->vthis); #if DMDV1 if (fd->vthis->nestedref) @@ -729,6 +721,15 @@ void DtoDefineFunction(FuncDeclaration* fd) #endif } + // give the 'nestArg' storage + if (f->fty.arg_nest) + { + LLValue *nestArg = irfunction->nestArg; + LLValue *val = DtoRawAlloca(nestArg->getType(), 0, "nestedFrame"); + DtoStore(nestArg, val); + irfunction->nestArg = val; + } + // give arguments storage // and debug info if (fd->parameters) @@ -771,10 +772,8 @@ void DtoDefineFunction(FuncDeclaration* fd) irloc->value = mem; } - #ifndef DISABLE_DEBUG_INFO if (global.params.symdebug && !(isaArgument(irloc->value) && isaArgument(irloc->value)->hasByValAttr()) && !refout) DtoDwarfLocalVariable(irloc->value, vd); - #endif } } @@ -836,9 +835,7 @@ void DtoDefineFunction(FuncDeclaration* fd) // in automatically, so we do it here. // pass the previous block into this block - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) DtoDwarfFuncEnd(fd); - #endif + DtoDwarfFuncEnd(fd); if (func->getReturnType() == LLType::getVoidTy(gIR->context())) { llvm::ReturnInst::Create(gIR->context(), gIR->scopebb()); } diff --git a/gen/linker.cpp b/gen/linker.cpp index 1be12301..24874e50 100644 --- a/gen/linker.cpp +++ b/gen/linker.cpp @@ -266,7 +266,7 @@ int linkObjToExecutable(const char* argv0) // create path to exe llvm::sys::Path exedir(llvm::sys::path::parent_path(gExePath.str())); - if (!llvm::sys::fs::exists(exedir.str())) + if (!exedir.empty() && !llvm::sys::fs::exists(exedir.str())) { exedir.createDirectoryOnDisk(true, &errstr); if (!errstr.empty()) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 6c168404..48e10d66 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -202,11 +202,8 @@ void DtoAssert(Module* M, Loc loc, DValue* msg) // call gIR->CreateCallOrInvoke(fn, args); - #ifndef DISABLE_DEBUG_INFO // end debug info - if (global.params.symdebug) - DtoDwarfFuncEnd(gIR->func()->decl); - #endif + DtoDwarfFuncEnd(gIR->func()->decl); // after assert is always unreachable gIR->ir->CreateUnreachable(); @@ -518,12 +515,10 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op) gIR->ir->CreateStore(r, l); } - #ifndef DISABLE_DEBUG_INFO DVarValue *var = lhs->isVar(); - VarDeclaration *varDecl = var ? var->var : 0; - if (global.params.symdebug && varDecl && varDecl->debugVariable) - DtoDwarfValue(rhs->getRVal(), lhs->isVar()->var); - #endif + VarDeclaration *vd = var ? var->var : 0; + if (vd) + DtoDwarfValue(DtoLoad(var->getLVal()), vd); } /****************************************************************************************/ @@ -937,11 +932,8 @@ void DtoConstInitGlobal(VarDeclaration* vd) gvar->setInitializer(initVal); - #ifndef DISABLE_DEBUG_INFO // do debug info - if (global.params.symdebug) - DtoDwarfGlobalVariable(gvar, vd); - #endif + DtoDwarfGlobalVariable(gvar, vd); } } @@ -1065,10 +1057,7 @@ DValue* DtoDeclarationExp(Dsymbol* declaration) //allocainst->setAlignment(vd->type->alignsize()); // TODO vd->ir.irLocal->value = allocainst; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfLocalVariable(allocainst, vd); - #endif + DtoDwarfLocalVariable(allocainst, vd); } else { @@ -1196,12 +1185,8 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr) if (!addr && (!var->ir.irLocal || !var->ir.irLocal->value)) { addr = DtoAlloca(var->type, var->toChars()); - - #ifndef DISABLE_DEBUG_INFO // add debug info - if (global.params.symdebug) - DtoDwarfLocalVariable(addr, var); - #endif + DtoDwarfLocalVariable(addr, var); } // referenced by nested function? diff --git a/gen/main.cpp b/gen/main.cpp index 3ca170a2..5cc83088 100644 --- a/gen/main.cpp +++ b/gen/main.cpp @@ -85,8 +85,8 @@ static cl::list debuglibs("debuglib", void printVersion() { printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n", global.ldc_version, global.version, global.llvm_version, global.copyright, global.written); - printf("D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n" - "LDC Homepage: http://www.dsource.org/projects/ldc\n"); + printf("D Language Documentation: http://d-programming-language.org/index.html\n" + "LDC Homepage: https://github.com/ldc-developers/ldc\n"); } // Helper function to handle -d-debug=* and -d-version=* diff --git a/gen/nested.cpp b/gen/nested.cpp index cdac766e..cafb9fb6 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -6,6 +6,7 @@ #include "gen/logger.h" #include "gen/tollvm.h" #include "gen/functions.h" +#include "gen/todebug.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/CommandLine.h" @@ -120,6 +121,10 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) return new DVarValue(astype, vd, val); } + LLValue *dwarfValue = 0; + std::vector dwarfAddr; + LLType *int64Ty = LLType::getInt64Ty(gIR->context()); + // get the nested context LLValue* ctx = 0; if (irfunc->decl->isMember2()) @@ -135,10 +140,15 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) #endif ctx = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); } - else if (irfunc->nestedVar) + else if (irfunc->nestedVar) { ctx = irfunc->nestedVar; - else - ctx = irfunc->nestArg; + dwarfValue = ctx; + } else { + ctx = DtoLoad(irfunc->nestArg); + dwarfValue = irfunc->nestArg; + if (global.params.symdebug) + dwarfOpDeref(dwarfAddr); + } assert(ctx); DtoCreateNestedContextType(vdparent->isFuncDeclaration()); @@ -174,21 +184,32 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) Logger::println("Same depth"); } else { // Load frame pointer and index that... + if (dwarfValue && global.params.symdebug) { + dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedDepth); + dwarfOpDeref(dwarfAddr); + } Logger::println("Lower depth"); val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth); Logger::cout() << "Frame index: " << *val << '\n'; val = DtoAlignedLoad(val, (std::string(".frame.") + vdparent->toChars()).c_str()); Logger::cout() << "Frame: " << *val << '\n'; } + + if (dwarfValue && global.params.symdebug) + dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedIndex); val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars()); Logger::cout() << "Addr: " << *val << '\n'; Logger::cout() << "of type: " << *val->getType() << '\n'; if (vd->ir.irLocal->byref || byref) { val = DtoAlignedLoad(val); + //dwarfOpDeref(dwarfAddr); Logger::cout() << "Was byref, now: " << *val << '\n'; Logger::cout() << "of type: " << *val->getType() << '\n'; } + if (dwarfValue && global.params.symdebug) + DtoDwarfLocalVariable(dwarfValue, vd, dwarfAddr); + return new DVarValue(astype, vd, val); } else { @@ -283,7 +304,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) } // otherwise, it may have gotten a context from the caller else if (irfunc->nestArg) - val = irfunc->nestArg; + val = DtoLoad(irfunc->nestArg); // or just have a this argument else if (irfunc->thisArg) { @@ -542,6 +563,8 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { assert(cd); assert(cd->vthis); src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis")); + } else { + src = DtoLoad(src); } DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE), getABITypeAlign(getVoidPtrType())); @@ -613,6 +636,8 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { else #endif src = DtoLoad(DtoGEPi(thisval, 0, cd->vthis->ir.irField->index, ".vthis")); + } else { + src = DtoLoad(src); } if (depth > 1) { src = DtoBitCast(src, getVoidPtrType()); @@ -669,6 +694,12 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { vd->ir.irLocal->value = gep; vd->ir.irLocal->byref = false; } + + if (global.params.symdebug) { + LLSmallVector addr; + dwarfOpOffset(addr, frameType, vd->ir.irLocal->nestedIndex); + DtoDwarfLocalVariable(frame, vd, addr); + } } } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) { // Propagate context arg properties if the context arg is passed on unmodified. diff --git a/gen/statements.cpp b/gen/statements.cpp index 8cb84dd7..af0e24f0 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -52,10 +52,8 @@ void ReturnStatement::toIR(IRState* p) Logger::println("ReturnStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); // is there a return value expression? if (exp || (!exp && (p->topfunc() == p->mainFunc)) ) @@ -84,10 +82,8 @@ void ReturnStatement::toIR(IRState* p) // emit scopes DtoEnclosingHandlers(loc, NULL); - #ifndef DISABLE_DEBUG_INFO // emit dbg end function - if (global.params.symdebug) DtoDwarfFuncEnd(f->decl); - #endif + DtoDwarfFuncEnd(f->decl); // emit ret llvm::ReturnInst::Create(gIR->context(), p->scopebb()); @@ -158,9 +154,7 @@ void ReturnStatement::toIR(IRState* p) // emit scopes DtoEnclosingHandlers(loc, NULL); - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); - #endif + DtoDwarfFuncEnd(p->func()->decl); llvm::ReturnInst::Create(gIR->context(), v, p->scopebb()); } } @@ -169,10 +163,7 @@ void ReturnStatement::toIR(IRState* p) { assert(p->topfunc()->getReturnType() == LLType::getVoidTy(gIR->context())); DtoEnclosingHandlers(loc, NULL); - - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); - #endif + DtoDwarfFuncEnd(p->func()->decl); llvm::ReturnInst::Create(gIR->context(), p->scopebb()); } @@ -189,10 +180,8 @@ void ExpStatement::toIR(IRState* p) Logger::println("ExpStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); if (exp) { if (global.params.llvmAnnotate) @@ -243,11 +232,8 @@ void IfStatement::toIR(IRState* p) Logger::println("IfStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif - + // start a dwarf lexical block + DtoDwarfBlockStart(loc); if (match) DtoRawVarDeclaration(match); @@ -271,8 +257,12 @@ void IfStatement::toIR(IRState* p) gIR->scope() = IRScope(ifbb,elsebb); // do scoped statements - if (ifbody) + + if (ifbody) { + DtoDwarfBlockStart(ifbody->loc); ifbody->toIR(p); + DtoDwarfBlockEnd(); + } if (!gIR->scopereturned()) { llvm::BranchInst::Create(endbb,gIR->scopebb()); } @@ -280,12 +270,17 @@ void IfStatement::toIR(IRState* p) if (elsebody) { //assert(0); gIR->scope() = IRScope(elsebb,endbb); + DtoDwarfBlockStart(elsebody->loc); elsebody->toIR(p); if (!gIR->scopereturned()) { llvm::BranchInst::Create(endbb,gIR->scopebb()); } + DtoDwarfBlockEnd(); } + // end the dwarf lexical block + DtoDwarfBlockEnd(); + // rewrite the scope gIR->scope() = IRScope(endbb,oldend); } @@ -318,8 +313,11 @@ void ScopeStatement::toIR(IRState* p) else p->scope().end = endbb;*/ - if (statement) + if (statement) { + DtoDwarfBlockStart(statement->loc); statement->toIR(p); + DtoDwarfBlockEnd(); + } /*p->scope().end = oldend; Logger::println("Erasing scope endbb"); @@ -333,10 +331,8 @@ void WhileStatement::toIR(IRState* p) Logger::println("WhileStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // start a dwarf lexical block + DtoDwarfBlockStart(loc); // create while blocks llvm::BasicBlock* oldend = gIR->scopeend(); @@ -374,6 +370,9 @@ void WhileStatement::toIR(IRState* p) // rewrite the scope gIR->scope() = IRScope(endbb,oldend); + + // end the dwarf lexical block + DtoDwarfBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -383,10 +382,8 @@ void DoStatement::toIR(IRState* p) Logger::println("DoStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // start a dwarf lexical block + DtoDwarfBlockStart(loc); // create while blocks llvm::BasicBlock* oldend = gIR->scopeend(); @@ -421,6 +418,9 @@ void DoStatement::toIR(IRState* p) // rewrite the scope gIR->scope() = IRScope(endbb,oldend); + + // end the dwarf lexical block + DtoDwarfBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -430,10 +430,8 @@ void ForStatement::toIR(IRState* p) Logger::println("ForStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // start new dwarf lexical block + DtoDwarfBlockStart(loc); // create for blocks llvm::BasicBlock* oldend = gIR->scopeend(); @@ -444,7 +442,7 @@ void ForStatement::toIR(IRState* p) // init if (init != 0) - init->toIR(p); + init->toIR(p); // move into the for condition block, ie. start the loop assert(!gIR->scopereturned()); @@ -498,6 +496,9 @@ void ForStatement::toIR(IRState* p) // rewrite the scope gIR->scope() = IRScope(endbb,oldend); + + // end the dwarf lexical block + DtoDwarfBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -512,10 +513,8 @@ void BreakStatement::toIR(IRState* p) if (p->scopereturned()) return; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); if (ident != 0) { Logger::println("ident = %s", ident->toChars()); @@ -569,10 +568,8 @@ void ContinueStatement::toIR(IRState* p) Logger::println("ContinueStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); if (ident != 0) { Logger::println("ident = %s", ident->toChars()); @@ -637,19 +634,22 @@ void TryFinallyStatement::toIR(IRState* p) Logger::println("TryFinallyStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); // if there's no finalbody or no body, things are simple if (!finalbody) { - if (body) + if (body) { + DtoDwarfBlockStart(body->loc); body->toIR(p); + DtoDwarfBlockEnd(); + } return; } if (!body) { + DtoDwarfBlockStart(finalbody->loc); finalbody->toIR(p); + DtoDwarfBlockEnd(); return; } @@ -684,7 +684,9 @@ void TryFinallyStatement::toIR(IRState* p) p->scope() = IRScope(trybb,finallybb); assert(body); + DtoDwarfBlockStart(body->loc); body->toIR(p); + DtoDwarfBlockEnd(); // terminate try BB if (!p->scopereturned()) @@ -698,7 +700,9 @@ void TryFinallyStatement::toIR(IRState* p) // do finally block // p->scope() = IRScope(finallybb,landingpadbb); + DtoDwarfBlockStart(finalbody->loc); finalbody->toIR(p); + DtoDwarfBlockEnd(); // terminate finally //TODO: isn't it an error to have a 'returned' finally block? @@ -717,10 +721,8 @@ void TryCatchStatement::toIR(IRState* p) Logger::println("TryCatchStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); // create basic blocks llvm::BasicBlock* oldend = p->scopeend(); @@ -756,7 +758,9 @@ void TryCatchStatement::toIR(IRState* p) p->scope() = IRScope(trybb,landingpadbb); assert(body); + DtoDwarfBlockStart(body->loc); body->toIR(p); + DtoDwarfBlockEnd(); if (!gIR->scopereturned()) llvm::BranchInst::Create(endbb, p->scopebb()); @@ -775,17 +779,13 @@ void ThrowStatement::toIR(IRState* p) Logger::println("ThrowStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); assert(exp); DValue* e = exp->toElemDtor(p); - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) DtoDwarfFuncEnd(gIR->func()->decl); - #endif + DtoDwarfFuncEnd(gIR->func()->decl); llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_throw_exception"); //Logger::cout() << "calling: " << *fn << '\n'; @@ -861,10 +861,8 @@ void SwitchStatement::toIR(IRState* p) Logger::println("SwitchStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); llvm::BasicBlock* oldbb = gIR->scopebb(); llvm::BasicBlock* oldend = gIR->scopeend(); @@ -1041,7 +1039,9 @@ void CaseStatement::toIR(IRState* p) p->scope() = IRScope(bodyBB, p->scopeend()); assert(statement); + DtoDwarfBlockStart(statement->loc); statement->toIR(p); + DtoDwarfBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -1066,7 +1066,9 @@ void DefaultStatement::toIR(IRState* p) p->scope() = IRScope(bodyBB, p->scopeend()); assert(statement); + DtoDwarfBlockStart(statement->loc); statement->toIR(p); + DtoDwarfBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -1080,10 +1082,8 @@ void UnrolledLoopStatement::toIR(IRState* p) if (!statements || !statements->dim) return; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // start a dwarf lexical block + DtoDwarfBlockStart(loc); // DMD doesn't fold stuff like continue/break, and since this isn't really a loop // we have to keep track of each statement and jump to the next/end on continue/break @@ -1139,6 +1139,9 @@ void UnrolledLoopStatement::toIR(IRState* p) if (!p->scopereturned()) p->ir->CreateBr(endbb); p->scope() = IRScope(endbb,oldend); + + // end the dwarf lexical block + DtoDwarfBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -1148,10 +1151,8 @@ void ForeachStatement::toIR(IRState* p) Logger::println("ForeachStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // start a dwarf lexical block + DtoDwarfBlockStart(loc); //assert(arguments->dim == 1); assert(value != 0); @@ -1266,6 +1267,9 @@ void ForeachStatement::toIR(IRState* p) } llvm::BranchInst::Create(condbb, p->scopebb()); + // end the dwarf lexical block + DtoDwarfBlockEnd(); + // end p->scope() = IRScope(endbb,oldend); } @@ -1279,10 +1283,8 @@ void ForeachRangeStatement::toIR(IRState* p) Logger::println("ForeachRangeStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // start a dwarf lexical block + DtoDwarfBlockStart(loc); // evaluate lwr/upr assert(lwr->type->isintegral()); @@ -1371,6 +1373,9 @@ void ForeachRangeStatement::toIR(IRState* p) // jump to condition llvm::BranchInst::Create(condbb, p->scopebb()); + // end the dwarf lexical block + DtoDwarfBlockEnd(); + // END p->scope() = IRScope(endbb,oldend); } @@ -1430,10 +1435,7 @@ void GotoStatement::toIR(IRState* p) Logger::println("GotoStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + DtoDwarfStopPoint(loc.linnum); llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergoto", p->topfunc(), oldend); @@ -1450,10 +1452,7 @@ void GotoDefaultStatement::toIR(IRState* p) Logger::println("GotoDefaultStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + DtoDwarfStopPoint(loc.linnum); llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotodefault", p->topfunc(), oldend); @@ -1474,10 +1473,7 @@ void GotoCaseStatement::toIR(IRState* p) Logger::println("GotoCaseStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + DtoDwarfStopPoint(loc.linnum); llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotocase", p->topfunc(), oldend); @@ -1501,10 +1497,7 @@ void WithStatement::toIR(IRState* p) Logger::println("WithStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + DtoDwarfBlockStart(loc); assert(exp); @@ -1518,6 +1511,8 @@ void WithStatement::toIR(IRState* p) if (body) body->toIR(p); + + DtoDwarfBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -1533,10 +1528,8 @@ void SynchronizedStatement::toIR(IRState* p) Logger::println("SynchronizedStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); // enter lock if (exp) @@ -1552,7 +1545,9 @@ void SynchronizedStatement::toIR(IRState* p) // emit body p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingSynchro(this),NULL,NULL)); + DtoDwarfBlockStart(body->loc); body->toIR(p); + DtoDwarfBlockEnd(); p->func()->gen->targetScopes.pop_back(); // exit lock @@ -1572,10 +1567,8 @@ void VolatileStatement::toIR(IRState* p) Logger::println("VolatileStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); - #endif + // emit dwarf stop point + DtoDwarfStopPoint(loc.linnum); // mark in-volatile // FIXME diff --git a/gen/todebug.cpp b/gen/todebug.cpp index 18db8014..277d1fc1 100644 --- a/gen/todebug.cpp +++ b/gen/todebug.cpp @@ -20,8 +20,6 @@ using namespace llvm::dwarf; -#ifndef DISABLE_DEBUG_INFO - ////////////////////////////////////////////////////////////////////////////////////////////////// // get the module the symbol is in, or - for template instances - the current module @@ -44,12 +42,24 @@ static Module* getDefinedModule(Dsymbol* s) ////////////////////////////////////////////////////////////////////////////////////////////////// +static llvm::DIDescriptor getCurrentScope() +{ + IrFunction *fn = gIR->func(); + if (fn->diLexicalBlocks.empty()) { + assert((llvm::MDNode*)fn->diSubprogram != 0); + return fn->diSubprogram; + } + return fn->diLexicalBlocks.top(); +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + static llvm::DIType dwarfTypeDescription_impl(Type* type, const char* c_name); static llvm::DIType dwarfTypeDescription(Type* type, const char* c_name); ////////////////////////////////////////////////////////////////////////////////////////////////// -llvm::DIFile DtoDwarfFile(Loc loc) +static llvm::DIFile DtoDwarfFile(Loc loc) { llvm::SmallString<128> path(loc.filename ? loc.filename : ""); llvm::sys::fs::make_absolute(path); @@ -180,9 +190,6 @@ static llvm::DIType dwarfCompositeType(Type* type) // elements std::vector elems; - // pointer to ir->diCompositeType - llvm::DIType *diCompositeType = 0; - llvm::DIType derivedFrom; assert((t->ty == Tstruct || t->ty == Tclass) && @@ -213,36 +220,12 @@ static llvm::DIType dwarfCompositeType(Type* type) if ((llvm::MDNode*)ir->diCompositeType != 0) return ir->diCompositeType; - diCompositeType = &ir->diCompositeType; name = sd->toChars(); linnum = sd->loc.linnum; file = DtoDwarfFile(sd->loc); // set diCompositeType to handle recursive types properly - if (t->ty == Tclass) { - ir->diCompositeType = gIR->dibuilder.createClassType( - llvm::DIDescriptor(file), - name, // name - file, // compile unit where defined - linnum, // line number where defined - getTypeBitSize(T), // size in bits - getABITypeAlign(T)*8, // alignment in bits - 0, // offset in bits, - llvm::DIType::FlagFwdDecl, // flags - derivedFrom, // DerivedFrom - llvm::DIArray(0) - ); - } else { - ir->diCompositeType = gIR->dibuilder.createStructType( - llvm::DIDescriptor(file), - name, // name - file, // compile unit where defined - linnum, // line number where defined - getTypeBitSize(T), // size in bits - getABITypeAlign(T)*8, // alignment in bits - llvm::DIType::FlagFwdDecl, // flags - llvm::DIArray(0) - ); - } + if (!ir->diCompositeType) + ir->diCompositeType = gIR->dibuilder.createTemporaryType(); if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one { @@ -296,8 +279,9 @@ static llvm::DIType dwarfCompositeType(Type* type) ); } - if (diCompositeType) - *diCompositeType = ret; + ir->diCompositeType.replaceAllUsesWith(ret); + ir->diCompositeType = ret; + return ret; } @@ -333,7 +317,7 @@ static void dwarfDeclare(LLValue* var, llvm::DIVariable divar) ////////////////////////////////////////////////////////////////////////////////////////////////// -llvm::DIType dwarfArrayType(Type* type) { +static llvm::DIType dwarfArrayType(Type* type) { LLType* T = DtoType(type); Type* t = type->toBasetype(); @@ -387,11 +371,17 @@ static llvm::DIType dwarfTypeDescription(Type* type, const char* c_name) ////////////////////////////////////////////////////////////////////////////////////////////////// -void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd) +void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd, llvm::ArrayRef addr) { + if (!global.params.symdebug) + return; + Logger::println("D to dwarf local variable"); LOG_SCOPE; + if (gIR->func()->diSubprogram == vd->debugFunc) // ensure that the debug variable is created only once + return; + // get type description llvm::DIType TD = dwarfTypeDescription(vd->type, NULL); if ((llvm::MDNode*)TD == 0) @@ -406,15 +396,28 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd) else tag = DW_TAG_auto_variable; - vd->debugVariable = gIR->dibuilder.createLocalVariable( - tag, // tag - gIR->func()->diSubprogram, // context - vd->toChars(), // name - DtoDwarfFile(vd->loc), // file - vd->loc.linnum, // line num - TD, // type - true // preserve - ); + if (addr.empty()) { + vd->debugVariable = gIR->dibuilder.createLocalVariable( + tag, // tag + getCurrentScope(), // scope + vd->toChars(), // name + DtoDwarfFile(vd->loc), // file + vd->loc.linnum, // line num + TD, // type + true // preserve + ); + } else { + vd->debugVariable = gIR->dibuilder.createComplexVariable( + tag, // tag + getCurrentScope(), // scope + vd->toChars(), // name + DtoDwarfFile(vd->loc), // file + vd->loc.linnum, // line num + TD, // type + addr + ); + } + vd->debugFunc = gIR->func()->diSubprogram; // declare dwarfDeclare(ll, vd->debugVariable); @@ -424,6 +427,9 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd) void DtoDwarfCompileUnit(Module* m) { + if (!global.params.symdebug) + return; + Logger::println("D to dwarf compile_unit"); LOG_SCOPE; @@ -444,7 +450,7 @@ void DtoDwarfCompileUnit(Module* m) global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D, srcname, srcpath, - "LDC (http://www.dsource.org/projects/ldc)", + "LDC (https://github.com/ldc-developers/ldc)", false, // isOptimized TODO llvm::StringRef(), // Flags TODO 1 // Runtime Version TODO @@ -455,6 +461,9 @@ void DtoDwarfCompileUnit(Module* m) llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd) { + if (!global.params.symdebug) + return llvm::DISubprogram(); + Logger::println("D to dwarf subprogram"); LOG_SCOPE; @@ -481,6 +490,9 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd) llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname) { + if (!global.params.symdebug) + return llvm::DISubprogram(); + Logger::println("D to dwarf subprogram"); LOG_SCOPE; @@ -503,6 +515,9 @@ llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd) { + if (!global.params.symdebug) + return llvm::DIGlobalVariable(); + Logger::println("D to dwarf global_variable"); LOG_SCOPE; @@ -514,22 +529,23 @@ llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclarati void DtoDwarfFuncStart(FuncDeclaration* fd) { + if (!global.params.symdebug) + return; + Logger::println("D to dwarf funcstart"); LOG_SCOPE; assert((llvm::MDNode*)fd->ir.irFunc->diSubprogram != 0); DtoDwarfStopPoint(fd->loc.linnum); - /* fd->ir.irFunc->diLexicalBlock = gIR->difactory.CreateLexicalBlock( - fd->ir.irFunc->diSubprogram, // context - DtoDwarfFile(fd->loc, DtoDwarfCompileUnit(getDefinedModule(fd))), // file - fd->loc.linnum - );*/ } ////////////////////////////////////////////////////////////////////////////////////////////////// void DtoDwarfFuncEnd(FuncDeclaration* fd) { + if (!global.params.symdebug) + return; + Logger::println("D to dwarf funcend"); LOG_SCOPE; @@ -538,22 +554,60 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd) ////////////////////////////////////////////////////////////////////////////////////////////////// +void DtoDwarfBlockStart(Loc loc) +{ + if (!global.params.symdebug) + return; + + Logger::println("D to dwarf block start"); + LOG_SCOPE; + + llvm::DILexicalBlock block = gIR->dibuilder.createLexicalBlock( + getCurrentScope(), // scope + DtoDwarfFile(loc), // file + loc.linnum, // line + 0 // column + ); + gIR->func()->diLexicalBlocks.push(block); + DtoDwarfStopPoint(loc.linnum); +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +void DtoDwarfBlockEnd() +{ + if (!global.params.symdebug) + return; + + Logger::println("D to dwarf block end"); + LOG_SCOPE; + + IrFunction *fn = gIR->func(); + assert(!fn->diLexicalBlocks.empty()); + fn->diLexicalBlocks.pop(); +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + void DtoDwarfStopPoint(unsigned ln) { + if (!global.params.symdebug) + return; + Logger::println("D to dwarf stoppoint at line %u", ln); LOG_SCOPE; - llvm::DebugLoc loc = llvm::DebugLoc::get(ln, 0, gIR->func()->diSubprogram); + llvm::DebugLoc loc = llvm::DebugLoc::get(ln, 0, getCurrentScope()); gIR->ir->SetCurrentDebugLocation(loc); } ////////////////////////////////////////////////////////////////////////////////////////////////// -void DtoDwarfValue(LLValue* var, VarDeclaration* vd) +void DtoDwarfValue(LLValue *val, VarDeclaration* vd) { - if (llvm::isa(vd->ir.irLocal->value) == 0) + if (!global.params.symdebug || !vd->debugVariable) return; - - llvm::Instruction *instr = gIR->dibuilder.insertDbgValueIntrinsic(vd->ir.irLocal->value, 0, vd->debugVariable, gIR->scopebb()); + + llvm::Instruction *instr = gIR->dibuilder.insertDbgValueIntrinsic(val, 0, vd->debugVariable, gIR->scopebb()); instr->setDebugLoc(gIR->ir->getCurrentDebugLocation()); } @@ -561,7 +615,8 @@ void DtoDwarfValue(LLValue* var, VarDeclaration* vd) void DtoDwarfModuleEnd() { + if (!global.params.symdebug) + return; + gIR->dibuilder.finalize(); } - -#endif diff --git a/gen/todebug.h b/gen/todebug.h index 8518da56..77b9071e 100644 --- a/gen/todebug.h +++ b/gen/todebug.h @@ -1,7 +1,8 @@ #ifndef LDC_GEN_TODEBUG_H #define LDC_GEN_TODEBUG_H -#ifndef DISABLE_DEBUG_INFO +#include "gen/tollvm.h" +#include "gen/irstate.h" void RegisterDwarfSymbols(llvm::Module* mod); @@ -28,17 +29,20 @@ llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char void DtoDwarfFuncStart(FuncDeclaration* fd); void DtoDwarfFuncEnd(FuncDeclaration* fd); +void DtoDwarfBlockStart(Loc loc); +void DtoDwarfBlockEnd(); void DtoDwarfStopPoint(unsigned ln); -void DtoDwarfValue(LLValue* var, VarDeclaration* vd); +void DtoDwarfValue(LLValue *val, VarDeclaration* vd); /** * Emits all things necessary for making debug info for a local variable vd. * @param ll LLVM Value of the variable. * @param vd Variable declaration to emit debug info for. */ -void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd); +void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd, + llvm::ArrayRef addr = llvm::ArrayRef()); /** * Emits all things necessary for making debug info for a global variable vd. @@ -50,7 +54,37 @@ llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclarati void DtoDwarfModuleEnd(); +template +void dwarfOpOffset(T &addr, LLStructType *type, int index) +{ + if (!global.params.symdebug) + return; -#endif // DISABLE_DEBUG_INFO + uint64_t offset = gTargetData->getStructLayout(type)->getElementOffset(index); + LLType *int64Ty = LLType::getInt64Ty(gIR->context()); + addr.push_back(LLConstantInt::get(int64Ty, llvm::DIBuilder::OpPlus)); + addr.push_back(LLConstantInt::get(int64Ty, offset)); +} + +template +void dwarfOpOffset(T &addr, LLValue *val, int index) +{ + if (!global.params.symdebug) + return; + + LLStructType *type = isaStruct(val->getType()->getContainedType(0)); + assert(type); + dwarfOpOffset(addr, type, index); +} + +template +void dwarfOpDeref(T &addr) +{ + if (!global.params.symdebug) + return; + + LLType *int64Ty = LLType::getInt64Ty(gIR->context()); + addr.push_back(LLConstantInt::get(int64Ty, llvm::DIBuilder::OpDeref)); +} #endif // LDC_GEN_TODEBUG_H diff --git a/gen/toir.cpp b/gen/toir.cpp index 2401b96d..d248e332 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -948,7 +948,7 @@ DValue* CallExp::toElem(IRState* p) LLValue* ptr = exp2->toElem(p)->getRVal(); llvm::StoreInst* ret = gIR->ir->CreateStore(val, ptr, "tmp"); ret->setAtomic(llvm::AtomicOrdering(atomicOrdering)); - ret->setAlignment(exp1->type->alignsize()); + ret->setAlignment(getTypeAllocSize(val->getType())); return NULL; // atomic load instruction } else if (fndecl->llvmInternal == LLVMatomic_load) { @@ -957,7 +957,7 @@ DValue* CallExp::toElem(IRState* p) LLValue* ptr = exp->toElem(p)->getRVal(); Type* retType = exp->type->nextOf(); llvm::LoadInst* val = gIR->ir->CreateLoad(ptr, "tmp"); - val->setAlignment(retType->alignsize()); + val->setAlignment(getTypeAllocSize(val->getType())); val->setAtomic(llvm::AtomicOrdering(atomicOrdering)); return new DImValue(retType, val); // cmpxchg instruction @@ -1441,39 +1441,8 @@ DValue* IndexExp::toElem(IRState* p) arrptr = DtoGEP(l->getRVal(), zero, r->getRVal()); } else if (e1type->ty == Tarray) { - if(global.params.useArrayBounds) { -#if 1 - /* - Workaround for a bug in llvm 2.8 which appears only when - all optimizations are off. - Example: - int a[] = new int[5]; - - a[0] = 100; - a[1] = 1; - a[2] = 2; - a[3] = 3; - a[4] = 4; - - for (int i = 0; i < a.length-1; i++) - printf("%d\n", a[i+1]); // Error would be around here - Output: - 100 - 100 - 100 - 100 - As you can see from the example, the index always is 0. - To avoid the issue we store the index before array bounds - checking. - */ - if (optLevel() == 0 && !r->isLVal()) { - LLValue *tmp = DtoAlloca(r->getType()); - DtoStore(r->getRVal(), tmp); - r = new DVarValue(r->getType(), tmp); - } -#endif + if(global.params.useArrayBounds) DtoArrayBoundsCheck(loc, l, r); - } arrptr = DtoArrayPtr(l); arrptr = DtoGEP1(arrptr,r->getRVal()); } @@ -2584,7 +2553,7 @@ DValue* FuncExp::toElem(IRState* p) ) cval = irfn->nestedVar; else if (irfn->nestArg) - cval = irfn->nestArg; + cval = DtoLoad(irfn->nestArg); #if DMDV2 // TODO: should we enable that for D1 as well? else if (irfn->thisArg) diff --git a/gen/toobj.cpp b/gen/toobj.cpp index 0a18409a..6f6071bf 100644 --- a/gen/toobj.cpp +++ b/gen/toobj.cpp @@ -115,11 +115,8 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) // allocate the target abi gABI = TargetABI::getTarget(); - #ifndef DISABLE_DEBUG_INFO // debug info - if (global.params.symdebug) - DtoDwarfCompileUnit(this); - #endif + DtoDwarfCompileUnit(this); // handle invalid 'objectø module if (!ClassDeclaration::object) { @@ -158,11 +155,8 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) } } - // finilize debugging - #ifndef DISABLE_DEBUG_INFO - if (global.params.symdebug) - DtoDwarfModuleEnd(); - #endif + // finilize debug info + DtoDwarfModuleEnd(); // generate ModuleInfo genmoduleinfo(); @@ -355,10 +349,7 @@ static llvm::Function* build_module_function(const std::string &name, const std: IRBuilder<> builder(bb); // debug info - #ifndef DISABLE_DEBUG_INFO - if(global.params.symdebug) - DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); - #endif + DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); // Call ctor's typedef std::list::const_iterator FuncIterator; @@ -479,11 +470,7 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) IRBuilder<> builder(bb); // debug info - #ifndef DISABLE_DEBUG_INFO - llvm::DISubprogram subprog; - if(global.params.symdebug) - subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()); - #endif + llvm::DISubprogram subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()); // get current beginning LLValue* curbeg = builder.CreateLoad(mref, "current"); diff --git a/ir/irfunction.h b/ir/irfunction.h index 3393c4a7..03cb12cd 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -99,7 +99,7 @@ struct IrFunction : IrBase llvm::Value* _argptr; llvm::DISubprogram diSubprogram; - llvm::DILexicalBlock diLexicalBlock; + std::stack diLexicalBlocks; }; #endif diff --git a/ir/irlandingpad.cpp b/ir/irlandingpad.cpp index 93da79be..ddc7d495 100644 --- a/ir/irlandingpad.cpp +++ b/ir/irlandingpad.cpp @@ -5,6 +5,7 @@ #include "gen/logger.h" #include "gen/classes.h" #include "gen/llvmhelpers.h" +#include "gen/todebug.h" #include "ir/irlandingpad.h" IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end) @@ -12,6 +13,7 @@ IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end) { target = llvm::BasicBlock::Create(gIR->context(), "catch", gIR->topfunc(), end); gIR->scope() = IRScope(target,end); + DtoDwarfBlockStart(catchstmt->loc); // assign storage to catch var if(catchstmt->var) { @@ -50,6 +52,7 @@ IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end) catchType = catchstmt->type->toBasetype()->isClassHandle(); assert(catchType); catchType->codegen(Type::sir); + DtoDwarfBlockEnd(); } IRLandingPadInfo::IRLandingPadInfo(Statement* finallystmt) diff --git a/ldc2.conf.in b/ldc2.conf.in index 09cd5b1d..aab1a26e 100644 --- a/ldc2.conf.in +++ b/ldc2.conf.in @@ -10,7 +10,7 @@ default: "-I@PROJECT_BINARY_DIR@/../import", "-I@RUNTIME_DIR@/import", "-I@RUNTIME_DIR@/src", - "-L-L@PROJECT_BINARY_DIR@/../lib", + "-L-L@PROJECT_BINARY_DIR@/../lib", @MUTILIB_ADDITIONAL_PATH@ "-defaultlib=@RUNTIME_AIO@", "-debuglib=@RUNTIME_AIO@" ]; diff --git a/ldc2.rebuild.conf.in b/ldc2.rebuild.conf.in index 4947fe77..c95b3269 100644 --- a/ldc2.rebuild.conf.in +++ b/ldc2.rebuild.conf.in @@ -1,2 +1,2 @@ [Environment] -DFLAGS=-I@INCLUDE_INSTALL_DIR@/phobos -I-I@INCLUDE_INSTALL_DIR@/ldc -I@INCLUDE_INSTALL_DIR@ -L-L@CMAKE_INSTALL_LIBDIR@ -defaultlib=@RUNTIME_AIO@ -debuglib=@RUNTIME_AIO@ +DFLAGS=-I-I@INCLUDE_INSTALL_DIR@/ldc -I@INCLUDE_INSTALL_DIR@ -L-L@CMAKE_INSTALL_LIBDIR@ -defaultlib=@RUNTIME_AIO@ -debuglib=@RUNTIME_AIO@ diff --git a/ldc2_install.conf.in b/ldc2_install.conf.in index ab5a41ee..a7409bbb 100644 --- a/ldc2_install.conf.in +++ b/ldc2_install.conf.in @@ -7,10 +7,9 @@ default: // 'switches' holds array of string that are appends to the command line // arguments before they are parsed. switches = [ - "-I@INCLUDE_INSTALL_DIR@/phobos", "-I@INCLUDE_INSTALL_DIR@/ldc", "-I@INCLUDE_INSTALL_DIR@", - "-L-L@CMAKE_INSTALL_LIBDIR@", + "-L-L@CMAKE_INSTALL_LIBDIR@", @MUTILIB_ADDITIONAL_INSTALL_PATH@ "-defaultlib=lphobos2", "-debuglib=lphobos2" ]; diff --git a/ldc2_phobos.conf.in b/ldc2_phobos.conf.in index 301aaa23..0399e7e0 100644 --- a/ldc2_phobos.conf.in +++ b/ldc2_phobos.conf.in @@ -7,11 +7,11 @@ default: // 'switches' holds array of string that are appends to the command line // arguments before they are parsed. switches = [ - "-I@PROJECT_BINARY_DIR@/../import", + "-I@CMAKE_BINARY_DIR@/import", "-I@RUNTIME_DIR@/import", "-I@RUNTIME_DIR@/src", "-I@PHOBOS2_DIR@/", - "-L-L@PROJECT_BINARY_DIR@/../lib", + "-L-L@PROJECT_BINARY_DIR@/../lib", @MUTILIB_ADDITIONAL_PATH@ "-defaultlib=lphobos2", "-debuglib=lphobos2" ]; diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 0f20892d..5894203b 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -2,9 +2,23 @@ project(runtime) cmake_minimum_required(VERSION 2.6) -option(BUILD_SHARED_LIBS "build the runtime as shared libraries (linux only)") -option(BUILD_BC_LIBS "build the runtime as bytecode libraries") -option(BUILD_SINGLE_LIB "build single runtime library" ON) +# +# Main configuration. +# + +include(CheckTypeSize) +check_type_size(void* ptr_size) + +if(${ptr_size} MATCHES "^8$") ## if it's 64-bit OS + set(MULTILIB OFF CACHE BOOL "Build both 64-bit and 32-bit libraries") +ENDIF(${ptr_size} MATCHES "^8$") + +set(BUILD_BC_LIBS OFF CACHE BOOL "Build the runtime as bytecode libraries") +set(BUILD_SINGLE_LIB ON CACHE BOOL "Build single runtime library") +set(LIB_SUFFIX "" CACHE STRING "Takes an empty string or 64. Directory where lib will be installed: lib or lib64") +set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/d CACHE PATH "Directory where will be put header files") +set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build as shared library or as static library") +set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX} CACHE PATH "Directory where lib will be installed") set(D_FLAGS -g -w -d CACHE STRING "runtime build flags, separated by ;") if(BUILD_SHARED_LIBS) @@ -26,6 +40,10 @@ endif(D_VERSION EQUAL 1) get_directory_property(PROJECT_PARENT_DIR DIRECTORY ${PROJECT_SOURCE_DIR} PARENT_DIRECTORY) set(RUNTIME_DIR ${PROJECT_PARENT_DIR}/${RUNTIME} CACHE PATH "runtime source dir") +# +# Gather source files. +# + if(D_VERSION EQUAL 1) # copy imports to runtime dir set(LDC_IMPORTS) @@ -66,7 +84,7 @@ elseif(D_VERSION EQUAL 2) set(RUNTIME_CC druntime-core) set(RUNTIME_GC druntime-gc-basic) set(RUNTIME_DC druntime-rt-ldc) - set(RUNTIME_AIO druntime-ldc) + set(RUNTIME_AIO ldruntime) set(RUNTIME_DC_DIR ${RUNTIME_DIR}/src/rt) set(RUNTIME_GC_DIR ${RUNTIME_DIR}/src/gc) set(RUNTIME_INCLUDE ${RUNTIME_DIR}/src) @@ -143,12 +161,42 @@ elseif(D_VERSION EQUAL 2) endif(PHOBOS2_DIR) endif(D_VERSION EQUAL 1) +# should only be necessary if run independently from ldc cmake project +if(NOT LDC_LOC) + if(NOT LDC_EXE) + if(D_VERSION EQUAL 1) + set(LDC_EXE ldc) + elseif(D_VERSION EQUAL 2) + set(LDC_EXE ldc2) + endif(D_VERSION EQUAL 1) + endif(NOT LDC_EXE) + + find_program(LDC_LOC ${LDC_EXE} ${PROJECT_BINARY_DIR}/../bin DOC "path to ldc binary") + if(NOT LDC_LOC) + message(SEND_ERROR "ldc not found") + endif(NOT LDC_LOC) + set(LDC_EXE_NAME ${LDC_EXE}) +endif(NOT LDC_LOC) + +# +# Create configuration files. +# + +if(MULTILIB) + set(MUTILIB_ADDITIONAL_PATH "\n \"-L-L${CMAKE_BINARY_DIR}/lib32\",") + set(MUTILIB_ADDITIONAL_INSTALL_PATH "\n \"-L-L${CMAKE_INSTALL_PREFIX}/lib32\",") +endif(MULTILIB) + configure_file(${PROJECT_PARENT_DIR}/${CONFIG_NAME}.conf.in ${PROJECT_BINARY_DIR}/../bin/${LDC_EXE}.conf) # Prepare the config files for installation in bin. configure_file(${PROJECT_PARENT_DIR}/${LDC_EXE}_install.conf.in ${PROJECT_BINARY_DIR}/../bin/${LDC_EXE}_install.conf) configure_file(${PROJECT_PARENT_DIR}/${LDC_EXE}.rebuild.conf.in ${PROJECT_BINARY_DIR}/../bin/${LDC_EXE}_install.rebuild.conf) -macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH) +# +# Macros. +# + +macro(dc INPUT_D OUTLIST_O OUTLIST_BC MOREFLAGS PATH SUFFIX) if ("${PATH}" STREQUAL "") file(RELATIVE_PATH output ${RUNTIME_DIR} ${INPUT_D}) else ("${PATH}" STREQUAL "") @@ -161,8 +209,8 @@ macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH) else ("${path}" STREQUAL "") set(output ${path}/${name}) endif ("${path}" STREQUAL "") - set(OUTPUT_O ${PROJECT_BINARY_DIR}/${output}.o) - set(OUTPUT_BC ${PROJECT_BINARY_DIR}/${output}.bc) + set(OUTPUT_O ${PROJECT_BINARY_DIR}/${output}${SUFFIX}.o) + set(OUTPUT_BC ${PROJECT_BINARY_DIR}/${output}${SUFFIX}.bc) list(APPEND ${OUTLIST_O} ${OUTPUT_O}) list(APPEND ${OUTLIST_BC} ${OUTPUT_BC}) @@ -172,7 +220,7 @@ macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH) else (INDEX EQUAL -1) string(REGEX REPLACE "src/ldc" "src/core" output ${output}) string(REGEX REPLACE "^src/" "" di_output ${output}) - set(DI_CMD -Hf=${PROJECT_BINARY_DIR}/import/${di_output}.di) + set(DI_CMD -Hf=${CMAKE_BINARY_DIR}/import/${di_output}.di) list(REMOVE_AT GENERATE_DI ${INDEX}) endif (INDEX EQUAL -1) @@ -181,7 +229,7 @@ macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH) OUTPUT ${OUTPUT_O} ${OUTPUT_BC} - COMMAND ${LDC_LOC} --output-o --output-bc -c -I${INCDIR} -I${RUNTIME_GC_DIR} ${INPUT_D} -of${OUTPUT_O} ${DI_CMD} ${D_FLAGS} ${MOREFLAGS} + COMMAND ${LDC_LOC} --output-o --output-bc -c -I${RUNTIME_INCLUDE} -I${RUNTIME_GC_DIR} ${INPUT_D} -of${OUTPUT_O} ${DI_CMD} ${D_FLAGS} ${MOREFLAGS} WORKING_DIRECTORY ${PROJECT_PARENT_DIR} DEPENDS ${LDC_LOC} ${INPUT_D} @@ -190,96 +238,175 @@ macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH) ) endmacro(dc) -foreach(f ${CORE_D}) - dc(${f} CORE_O CORE_BC ${RUNTIME_INCLUDE} "-disable-invariants" "") -endforeach(f) +macro(build_runtime d_flags c_flags ld_flags lib_suffix path_suffix) + set(output_path ${CMAKE_BINARY_DIR}/lib${path_suffix}) -foreach(f ${GC_D}) - dc(${f} GC_O GC_BC ${RUNTIME_INCLUDE} "-disable-invariants" "") -endforeach(f) + set(target_suffix "") + if(NOT "${lib_suffix}" STREQUAL "") + set(target_suffix "_${lib_suffix}") + endif(NOT "${lib_suffix}" STREQUAL "") + if(NOT "${path_suffix}" STREQUAL "") + set(target_suffix "${target_suffix}_${path_suffix}") + endif(NOT "${path_suffix}" STREQUAL "") -foreach(f ${DCRT_D}) - if(D_VERSION EQUAL 1) - dc(${f} DCRT_O DCRT_BC ${RUNTIME_INCLUDE} "" ${RUNTIME_DC_DIR}) - else(D_VERSION EQUAL 1) - dc(${f} DCRT_O DCRT_BC ${RUNTIME_INCLUDE} "" "") - endif(D_VERSION EQUAL 1) -endforeach(f) - -if(EXISTS ${PROJECT_PARENT_DIR}/${RUNTIME}) - if(BUILD_SINGLE_LIB) - add_library(${RUNTIME_AIO} ${D_LIBRARY_TYPE} ${CORE_O} ${CORE_C} ${GC_O} ${DCRT_O} ${DCRT_C}) - set(LIBS ${RUNTIME_AIO}) - else(BUILD_SINGLE_LIB) - add_library(${RUNTIME_CC} ${D_LIBRARY_TYPE} ${CORE_O} ${CORE_C}) - add_library(${RUNTIME_GC} ${D_LIBRARY_TYPE} ${GC_O}) - add_library(${RUNTIME_DC} ${D_LIBRARY_TYPE} ${DCRT_O} ${DCRT_C}) - set(LIBS - ${RUNTIME_CC} - ${RUNTIME_GC} - ${RUNTIME_DC} - ) - endif(BUILD_SINGLE_LIB) -endif(EXISTS ${PROJECT_PARENT_DIR}/${RUNTIME}) - -if(BUILD_BC_LIBS) - find_program(LLVM_AR_EXE llvm-ar ${LLVM_INSTDIR}/bin DOC "path to llvm-ar tool") - if(NOT LLVM_AR_EXE) - message(SEND_ERROR "llvm-ar not found") - endif(NOT LLVM_AR_EXE) - - add_library(${RUNTIME_CC}-c ${CORE_C}) - add_library(${RUNTIME_DC}-c ${DCRT_C}) - list(APPEND LIBS - ${RUNTIME_CC}-c - ${RUNTIME_DC}-c - ) - add_custom_command( - OUTPUT bclibs - COMMAND ${LLVM_AR_EXE} rs lib${RUNTIME_CC}-bc.a ${CORE_BC} - COMMAND ${LLVM_AR_EXE} rs lib${RUNTIME_GC}-bc.a ${GC_BC} - # cannot parse genobj.bc if built with -g - # COMMAND ${LLVM_AR_EXE} rs lib${RUNTIME_DC}-bc.a ${DCRT_BC} - WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} - DEPENDS - ${CORE_BC} - ${GC_BC} - ${DCRT_BC} - ${LDC_IMPORTS} - ) - set(BCLIBS bclibs) -endif(BUILD_BC_LIBS) - -set_target_properties( - ${LIBS} PROPERTIES - LINKER_LANGUAGE C - ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} - LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} -) - -# BCLIBS is empty if BUILD_BC_LIBS is not selected -add_custom_target(runtime DEPENDS ${LIBS} ${BCLIBS}) - -if(PHOBOS2_DIR) - foreach(f ${PHOBOS2_D}) - dc(${f} PHOBOS2_O PHOBOS2_BC ${RUNTIME_DIR}/src/ "-I${PHOBOS2_DIR}" ${PHOBOS2_DIR}) + set(CORE_O "") + set(CORE_BC "") + foreach(f ${CORE_D}) + dc(${f} CORE_O CORE_BC "${d_flags};-disable-invariants" "" "${target_suffix}") endforeach(f) - add_library(lphobos2 ${D_LIBRARY_TYPE} - ${ZLIB_C} - ${PHOBOS2_O} - ${CORE_O} - ${CORE_C} - ${GC_O} - ${DCRT_O} - ${DCRT_C} - ) - add_dependencies(lphobos2 runtime) + set(GC_O "") + set(GC_BC "") + foreach(f ${GC_D}) + dc(${f} GC_O GC_BC "${d_flags};-disable-invariants" "" "${target_suffix}") + endforeach(f) + + set(DCRT_O "") + set(DCRT_BC "") + foreach(f ${DCRT_D}) + if(D_VERSION EQUAL 1) + dc(${f} DCRT_O DCRT_BC "${d_flags}" ${RUNTIME_DC_DIR} "${target_suffix}") + else(D_VERSION EQUAL 1) + dc(${f} DCRT_O DCRT_BC "${d_flags}" "" "${target_suffix}") + endif(D_VERSION EQUAL 1) + endforeach(f) + + if(EXISTS ${PROJECT_PARENT_DIR}/${RUNTIME}) + if(BUILD_SINGLE_LIB) + add_library(${RUNTIME_AIO}${target_suffix} + ${D_LIBRARY_TYPE} + ${CORE_O} + ${CORE_C} + ${GC_O} + ${DCRT_O} + ${DCRT_C} + ) + set(LIBS ${RUNTIME_AIO}) + set_target_properties(${RUNTIME_AIO}${target_suffix} PROPERTIES OUTPUT_NAME ${RUNTIME_AIO}${lib_suffix}) + else(BUILD_SINGLE_LIB) + add_library(${RUNTIME_CC}${target_suffix} ${D_LIBRARY_TYPE} ${CORE_O} ${CORE_C}) + add_library(${RUNTIME_GC}${target_suffix} ${D_LIBRARY_TYPE} ${GC_O}) + add_library(${RUNTIME_DC}${target_suffix} ${D_LIBRARY_TYPE} ${DCRT_O} ${DCRT_C}) + set_target_properties(${RUNTIME_CC}${target_suffix} PROPERTIES OUTPUT_NAME ${RUNTIME_CC}${lib_suffix}) + set_target_properties(${RUNTIME_GC}${target_suffix} PROPERTIES OUTPUT_NAME ${RUNTIME_GC}${lib_suffix}) + set_target_properties(${RUNTIME_DC}${target_suffix} PROPERTIES OUTPUT_NAME ${RUNTIME_DC}${lib_suffix}) + set(LIBS + ${RUNTIME_CC}${lib_suffix} + ${RUNTIME_GC}${lib_suffix} + ${RUNTIME_DC}${lib_suffix} + ) + endif(BUILD_SINGLE_LIB) + endif(EXISTS ${PROJECT_PARENT_DIR}/${RUNTIME}) + + if(BUILD_BC_LIBS) + find_program(LLVM_AR_EXE llvm-ar ${LLVM_INSTDIR}/bin DOC "path to llvm-ar tool") + if(NOT LLVM_AR_EXE) + message(SEND_ERROR "llvm-ar not found") + endif(NOT LLVM_AR_EXE) + + add_library(${RUNTIME_CC}-c ${CORE_C}) + add_library(${RUNTIME_DC}-c ${DCRT_C}) + list(APPEND LIBS + ${RUNTIME_CC}-c + ${RUNTIME_DC}-c + ) + add_custom_command( + OUTPUT bclibs + COMMAND ${LLVM_AR_EXE} rs lib${RUNTIME_CC}-bc.a ${CORE_BC} + COMMAND ${LLVM_AR_EXE} rs lib${RUNTIME_GC}-bc.a ${GC_BC} + # cannot parse genobj.bc if built with -g + # COMMAND ${LLVM_AR_EXE} rs lib${RUNTIME_DC}-bc.a ${DCRT_BC} + WORKING_DIRECTORY ${output_path} + DEPENDS + ${CORE_BC} + ${GC_BC} + ${DCRT_BC} + ${LDC_IMPORTS} + ) + set(BCLIBS bclibs) + endif(BUILD_BC_LIBS) + + if(D_VERSION EQUAL 2) + if(NOT PROJECT_BINARY_DIR STREQUAL "${PROJECT_SOURCE_DIR}") + file(COPY ${PROJECT_PARENT_DIR}/${RUNTIME} DESTINATION ${PROJECT_BINARY_DIR}/../) + file(COPY ${PROJECT_PARENT_DIR}/phobos DESTINATION ${PROJECT_BINARY_DIR}/../) + endif(NOT PROJECT_BINARY_DIR STREQUAL "${PROJECT_SOURCE_DIR}") + endif(D_VERSION EQUAL 2) + set_target_properties( - lphobos2 PROPERTIES + ${LIBS} PROPERTIES LINKER_LANGUAGE C - ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} - LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} + ARCHIVE_OUTPUT_DIRECTORY ${output_path} + LIBRARY_OUTPUT_DIRECTORY ${output_path} + RUNTIME_OUTPUT_DIRECTORY ${output_path} + COMPILE_FLAGS "${c_flags}" + LINK_FLAGS "${ld_flags}" ) - add_custom_target(phobos2 DEPENDS lphobos2) + install(TARGETS ${LIBS} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${path_suffix}) + + # BCLIBS is empty if BUILD_BC_LIBS is not selected + add_custom_target(runtime${target_suffix} DEPENDS ${LIBS} ${BCLIBS}) + + if(PHOBOS2_DIR) + set(PHOBOS2_O "") + set(PHOBOS2_BC "") + foreach(f ${PHOBOS2_D}) + dc(${f} PHOBOS2_O PHOBOS2_BC "${d_flags};-I${PHOBOS2_DIR}" ${PHOBOS2_DIR} "${target_suffix}") + endforeach(f) + + add_library(lphobos2${target_suffix} ${D_LIBRARY_TYPE} + ${ZLIB_C} + ${PHOBOS2_O} + ${CORE_O} + ${CORE_C} + ${GC_O} + ${DCRT_O} + ${DCRT_C} + ) + add_dependencies(lphobos2${target_suffix} runtime) + set_target_properties( + lphobos2${target_suffix} PROPERTIES + OUTPUT_NAME lphobos2${lib_suffix} + LINKER_LANGUAGE C + ARCHIVE_OUTPUT_DIRECTORY ${output_path} + LIBRARY_OUTPUT_DIRECTORY ${output_path} + RUNTIME_OUTPUT_DIRECTORY ${output_path} + COMPILE_FLAGS "${c_flags}" + LINK_FLAGS "${ld_flags}" + ) + install(TARGETS lphobos2${target_suffix} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${path_suffix}) + add_dependencies(phobos2 DEPENDS lphobos2${target_suffix}) + endif(PHOBOS2_DIR) +endmacro(build_runtime d_flags c_flags ld_flags lib_suffix path_suffix) + +# +# Set up build targets. +# + +if(PHOBOS2_DIR) + add_custom_target(phobos2) endif(PHOBOS2_DIR) +build_runtime("" "" "" "" "${LIB_SUFFIX}") +set(GENERATE_DI "") +if(MULTILIB) + build_runtime("-m32" "-m32" "-m32" "" "32") +endif(MULTILIB) + +# +# Install target. +# + +if(D_VERSION EQUAL 2) + install(DIRECTORY ${CMAKE_BINARY_DIR}/import/core DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.di") + if(PHOBOS2_DIR) + install(DIRECTORY ${PHOBOS2_DIR}/std DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.d") + install(DIRECTORY ${PHOBOS2_DIR}/etc DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.d") + install(FILES ${PHOBOS2_DIR}/crc32.d DESTINATION ${INCLUDE_INSTALL_DIR}) + endif(PHOBOS2_DIR) + install(FILES ${RUNTIME_DIR}/import/object.di DESTINATION ${INCLUDE_INSTALL_DIR}/ldc) + install(FILES ${RUNTIME_DIR}/src/ldc/bitop.d DESTINATION ${INCLUDE_INSTALL_DIR}/core) + install(DIRECTORY ${RUNTIME_DIR}/import/ldc DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.di") +else(D_VERSION EQUAL 2) + install(DIRECTORY ${PROJECT_SOURCE_DIR}/${RUNTIME}/internal/ldc/ DESTINATION ${INCLUDE_INSTALL_DIR}/ldc) + install(DIRECTORY ${PROJECT_SOURCE_DIR}/runtime/import/ldc DESTINATION ${INCLUDE_INSTALL_DIR}) +endif(D_VERSION EQUAL 2)