From 01e3e372fa47ef2cfe94e3cc688c9b69f5e7db30 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 28 Feb 2015 22:12:42 +0100 Subject: [PATCH 001/101] Win64 ABI fix: return non-POD structs via sret. And get rid of obsolete integer rewrites on Win64 and PPC. --- gen/abi-generic.h | 116 ++++++++++++++++++++++++++++++++++++++------- gen/abi-ppc64.cpp | 14 +++--- gen/abi-win64.cpp | 53 ++++++++++----------- gen/abi-x86-64.cpp | 37 +-------------- 4 files changed, 131 insertions(+), 89 deletions(-) diff --git a/gen/abi-generic.h b/gen/abi-generic.h index ac2c78fc3d9..2b0ae84b6fc 100644 --- a/gen/abi-generic.h +++ b/gen/abi-generic.h @@ -21,6 +21,64 @@ #include "gen/structs.h" #include "gen/tollvm.h" +struct LLTypeMemoryLayout +{ + // Structs and static arrays are folded recursively to scalars or anonymous structs. + // Pointer types are folded to an integer type. + static LLType* fold(LLType* type) + { + // T* => integer + if (type->isPointerTy()) + return LLIntegerType::get(gIR->context(), getTypeBitSize(type)); + + if (LLStructType* structType = isaStruct(type)) + { + unsigned numElements = structType->getNumElements(); + + // fold each element + std::vector elements; + elements.reserve(numElements); + for (unsigned i = 0; i < numElements; ++i) + elements.push_back(fold(structType->getElementType(i))); + + // single element? then discard wrapping struct + if (numElements == 1) + return elements[0]; + + return LLStructType::get(gIR->context(), elements, structType->isPacked()); + } + + if (LLArrayType* arrayType = isaArray(type)) + { + unsigned numElements = arrayType->getNumElements(); + LLType* foldedElementType = fold(arrayType->getElementType()); + + // single element? then fold to scalar + if (numElements == 1) + return foldedElementType; + + // otherwise: convert to struct of N folded elements + std::vector elements(numElements, foldedElementType); + return LLStructType::get(gIR->context(), elements); + } + + return type; + } + + // Checks two LLVM types for memory-layout equivalency. + static bool typesAreEquivalent(LLType* a, LLType* b) + { + if (a == b) + return true; + if (!a || !b) + return false; + + return fold(a) == fold(b); + } +}; + +////////////////////////////////////////////////////////////////////////////// + /// Removes padding fields for (non-union-containing!) structs struct RemoveStructPadding : ABIRewrite { /// get a rewritten value back to its original form @@ -58,6 +116,44 @@ struct RemoveStructPadding : ABIRewrite { */ struct IntegerRewrite : ABIRewrite { + static LLType* getIntegerType(unsigned minSizeInBytes) + { + if (minSizeInBytes > 8) + return NULL; + + unsigned size = minSizeInBytes; + switch (minSizeInBytes) { + case 0: + size = 1; + break; + case 3: + size = 4; + break; + case 5: + case 6: + case 7: + size = 8; + break; + default: + break; + } + + return LLIntegerType::get(gIR->context(), size * 8); + } + + static bool isObsoleteFor(LLType* llType) + { + if (!llType->isSized()) // e.g., opaque types + { + IF_LOG Logger::cout() << "IntegerRewrite: not rewriting non-sized type " + << *llType << '\n'; + return true; + } + + LLType* integerType = getIntegerType(getTypeStoreSize(llType)); + return LLTypeMemoryLayout::typesAreEquivalent(llType, integerType); + } + LLValue* get(Type* dty, DValue* dv) { LLValue* integer = dv->getRVal(); @@ -77,29 +173,13 @@ struct IntegerRewrite : ABIRewrite { assert(dty == dv->getType()); LLValue* address = getAddressOf(dv); - LLType* integerType = type(dty, NULL); + LLType* integerType = getIntegerType(dty->size()); return loadFromMemory(address, integerType, ".IntegerRewrite_putResult"); } LLType* type(Type* t, LLType*) { - unsigned size = t->size(); - switch (size) { - case 0: - size = 1; - break; - case 3: - size = 4; - break; - case 5: - case 6: - case 7: - size = 8; - break; - default: - break; - } - return LLIntegerType::get(gIR->context(), size * 8); + return getIntegerType(t->size()); } }; diff --git a/gen/abi-ppc64.cpp b/gen/abi-ppc64.cpp index 1357524c476..c2f1c894e43 100644 --- a/gen/abi-ppc64.cpp +++ b/gen/abi-ppc64.cpp @@ -66,15 +66,12 @@ struct PPC64TargetABI : TargetABI { void rewriteFunctionType(TypeFunction* tf, IrFuncTy &fty) { // EXPLICIT PARAMETERS - for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) { IrFuncTyArg& arg = **I; - if (arg.byref) - continue; - - rewriteArgument(fty, arg); + if (!arg.byref) + rewriteArgument(fty, arg); } } @@ -86,8 +83,11 @@ struct PPC64TargetABI : TargetABI { { if (canRewriteAsInt(ty)) { - arg.rewrite = &integerRewrite; - arg.ltype = integerRewrite.type(arg.type, arg.ltype); + if (!IntegerRewrite::isObsoleteFor(arg.ltype)) + { + arg.rewrite = &integerRewrite; + arg.ltype = integerRewrite.type(arg.type, arg.ltype); + } } else { diff --git a/gen/abi-win64.cpp b/gen/abi-win64.cpp index a1b685d69e1..a79899baf39 100644 --- a/gen/abi-win64.cpp +++ b/gen/abi-win64.cpp @@ -78,7 +78,7 @@ struct Win64TargetABI : TargetABI // * structs/static arrays/complex numbers which can NOT be rewritten as integers (isComposite(t) && !canRewriteAsInt(t)) || // * 80-bit real and ireal - ((t->ty == Tfloat80 || t->ty == Timaginary80) && realIs80bits()); + (realIs80bits() && (t->ty == Tfloat80 || t->ty == Timaginary80)); } }; @@ -113,45 +113,33 @@ bool Win64TargetABI::returnInArg(TypeFunction* tf) Type* rt = tf->next->toBasetype(); - // * everything <= 64 bits and of a size that is a power of 2 - // (incl. 2x32-bit cfloat) is returned in a register (RAX, or + // * all POD types <= 64 bits and of a size that is a power of 2 + // (incl. 2x32-bit cfloat) are returned in a register (RAX, or // XMM0 for single float/ifloat/double/idouble) // * all other structs/static arrays/complex numbers and 80-bit // real/ireal are returned via struct-return (sret) - return isPassedWithByvalSemantics(rt); + return (rt->ty == Tstruct && !((TypeStruct*)rt)->sym->isPOD()) + || isPassedWithByvalSemantics(rt); } bool Win64TargetABI::passByVal(Type* t) { - t = t->toBasetype(); - - // FIXME: LLVM doesn't support ByVal on Win64 yet - //return isPassedWithByvalSemantics(t); return false; } void Win64TargetABI::rewriteFunctionType(TypeFunction* tf, IrFuncTy &fty) { // RETURN VALUE - if (!tf->isref) - { - Type* rt = fty.ret->type->toBasetype(); - if (isComposite(rt) && canRewriteAsInt(rt)) - { - fty.ret->rewrite = &integerRewrite; - fty.ret->ltype = integerRewrite.type(fty.ret->type, fty.ret->ltype); - } - } + if (!fty.ret->byref && fty.ret->type->toBasetype()->ty != Tvoid) + rewriteArgument(fty, *fty.ret); // EXPLICIT PARAMETERS for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) { IrFuncTyArg& arg = **I; - if (arg.byref) - continue; - - rewriteArgument(fty, arg); + if (!arg.byref) + rewriteArgument(fty, arg); } // extern(D): reverse parameter order for non variadics, for DMD-compliance @@ -161,15 +149,10 @@ void Win64TargetABI::rewriteFunctionType(TypeFunction* tf, IrFuncTy &fty) void Win64TargetABI::rewriteArgument(IrFuncTy& fty, IrFuncTyArg& arg) { - Type* ty = arg.type->toBasetype(); + LLType* originalLType = arg.ltype; + Type* t = arg.type->toBasetype(); - if (isComposite(ty) && canRewriteAsInt(ty)) - { - arg.rewrite = &integerRewrite; - arg.ltype = integerRewrite.type(arg.type, arg.ltype); - } - // FIXME: this should actually be handled by LLVM and the ByVal arg attribute - else if (isPassedWithByvalSemantics(ty)) + if (isPassedWithByvalSemantics(t)) { // these types are passed byval: // the caller allocates a copy and then passes a pointer to the copy @@ -182,4 +165,16 @@ void Win64TargetABI::rewriteArgument(IrFuncTy& fty, IrFuncTyArg& arg) .add(LDC_ATTRIBUTE(NoAlias)) .add(LDC_ATTRIBUTE(NoCapture)); } + else if (isComposite(t) && canRewriteAsInt(t) && !IntegerRewrite::isObsoleteFor(originalLType)) + { + arg.rewrite = &integerRewrite; + arg.ltype = integerRewrite.type(arg.type, arg.ltype); + } + + IF_LOG if (arg.rewrite) + { + Logger::println("Rewriting argument type %s", t->toChars()); + LOG_SCOPE; + Logger::cout() << *originalLType << " => " << *arg.ltype << '\n'; + } } diff --git a/gen/abi-x86-64.cpp b/gen/abi-x86-64.cpp index 2d5b1e7db63..89ae63058a0 100644 --- a/gen/abi-x86-64.cpp +++ b/gen/abi-x86-64.cpp @@ -94,39 +94,6 @@ namespace { } } // namespace dmd_abi - // Checks two LLVM types for memory-layout equivalency. - // A pointer type is equivalent to any other pointer type. - bool typesAreEquivalent(LLType* a, LLType* b) { - if (a == b) - return true; - if (!a || !b) - return false; - - LLStructType* structA; - while ((structA = isaStruct(a)) && structA->getNumElements() == 1) - a = structA->getElementType(0); - - LLStructType* structB; - while ((structB = isaStruct(b)) && structB->getNumElements() == 1) - b = structB->getElementType(0); - - if (a == b || (a->isPointerTy() && b->isPointerTy())) - return true; - - if (!(structA && structB) || - structA->isPacked() != structB->isPacked() || - structA->getNumElements() != structB->getNumElements()) { - return false; - } - - for (unsigned i = 0; i < structA->getNumElements(); ++i) { - if (!typesAreEquivalent(structA->getElementType(i), structB->getElementType(i))) - return false; - } - - return true; - } - LLType* getAbiType(Type* ty) { return dmd_abi::getAbiType(ty->toBasetype()); } @@ -319,7 +286,7 @@ void X86_64TargetABI::rewriteArgument(IrFuncTyArg& arg, RegCount& regCount) { Type* t = arg.type->toBasetype(); LLType* abiTy = getAbiType(t); - if (abiTy && !typesAreEquivalent(abiTy, originalLType)) { + if (abiTy && !LLTypeMemoryLayout::typesAreEquivalent(abiTy, originalLType)) { IF_LOG { Logger::println("Rewriting argument type %s", t->toChars()); LOG_SCOPE; @@ -346,7 +313,7 @@ void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf, IrFuncTy &fty) { regCount = RegCount(); // initialize // RETURN VALUE - if (!tf->isref && !fty.arg_sret && tf->next->toBasetype()->ty != Tvoid) { + if (!fty.ret->byref && fty.ret->type->toBasetype()->ty != Tvoid) { Logger::println("x86-64 ABI: Transforming return type"); LOG_SCOPE; RegCount dummy; From 73df563a3aacf1c9a43fd37fbfa0921806c673a9 Mon Sep 17 00:00:00 2001 From: Dan Olson Date: Sun, 8 Mar 2015 23:42:02 -0700 Subject: [PATCH 002/101] Fix cmake bug when ldc is a submodule Allow ldc to be a submodule. This uses changes from https://github.com/rpavlik/cmake-modules. (cherry picked from commit 0be5ead42e6049f8e51453a82a17b1770646a1a2) --- cmake/Modules/GetGitRevisionDescription.cmake | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmake/Modules/GetGitRevisionDescription.cmake b/cmake/Modules/GetGitRevisionDescription.cmake index 19f8432f2a5..1cd8d86f554 100644 --- a/cmake/Modules/GetGitRevisionDescription.cmake +++ b/cmake/Modules/GetGitRevisionDescription.cmake @@ -40,7 +40,7 @@ set(__get_git_revision_description YES) get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) function(get_git_head_revision _refspecvar _hashvar) - set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}") + set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(GIT_DIR "${GIT_PARENT_DIR}/.git") while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") @@ -53,6 +53,13 @@ function(get_git_head_revision _refspecvar _hashvar) endif() set(GIT_DIR "${GIT_PARENT_DIR}/.git") endwhile() + # check if this is a submodule + if(NOT IS_DIRECTORY ${GIT_DIR}) + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) + endif() set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") if(NOT EXISTS "${GIT_DATA}") file(MAKE_DIRECTORY "${GIT_DATA}") From d24fc71a81ccfd04bd5989ba3339bd08f9f60b83 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 16 Mar 2015 00:10:36 +0100 Subject: [PATCH 003/101] Win64 ABI: Treat dynamic arrays and delegates as structs. I.e., pass them explicitly ByVal and return them via sret. --- gen/abi-win64.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/gen/abi-win64.cpp b/gen/abi-win64.cpp index a79899baf39..7dc22f0af72 100644 --- a/gen/abi-win64.cpp +++ b/gen/abi-win64.cpp @@ -47,11 +47,16 @@ struct Win64TargetABI : TargetABI void rewriteArgument(IrFuncTy& fty, IrFuncTyArg& arg); private: - // Returns true if the D type is a composite (struct/static array/complex number). - bool isComposite(Type* t) + // Returns true if the D type is an aggregate: + // * struct + // * static/dynamic array + // * delegate + // * complex number + bool isAggregate(Type* t) { - return t->ty == Tstruct || t->ty == Tsarray - || t->iscomplex(); // treat complex numbers as structs too + TY ty = t->ty; + return ty == Tstruct || ty == Tsarray || ty == Tarray || ty == Tdelegate + || t->iscomplex(); } // Returns true if the D type can be bit-cast to an integer of the same size. @@ -75,8 +80,9 @@ struct Win64TargetABI : TargetABI bool isPassedWithByvalSemantics(Type* t) { return - // * structs/static arrays/complex numbers which can NOT be rewritten as integers - (isComposite(t) && !canRewriteAsInt(t)) || + // * aggregates which can NOT be rewritten as integers + // (size > 64 bits or not a power of 2) + (isAggregate(t) && !canRewriteAsInt(t)) || // * 80-bit real and ireal (realIs80bits() && (t->ty == Tfloat80 || t->ty == Timaginary80)); } @@ -116,8 +122,7 @@ bool Win64TargetABI::returnInArg(TypeFunction* tf) // * all POD types <= 64 bits and of a size that is a power of 2 // (incl. 2x32-bit cfloat) are returned in a register (RAX, or // XMM0 for single float/ifloat/double/idouble) - // * all other structs/static arrays/complex numbers and 80-bit - // real/ireal are returned via struct-return (sret) + // * all other types are returned via struct-return (sret) return (rt->ty == Tstruct && !((TypeStruct*)rt)->sym->isPOD()) || isPassedWithByvalSemantics(rt); } @@ -165,7 +170,7 @@ void Win64TargetABI::rewriteArgument(IrFuncTy& fty, IrFuncTyArg& arg) .add(LDC_ATTRIBUTE(NoAlias)) .add(LDC_ATTRIBUTE(NoCapture)); } - else if (isComposite(t) && canRewriteAsInt(t) && !IntegerRewrite::isObsoleteFor(originalLType)) + else if (isAggregate(t) && canRewriteAsInt(t) && !IntegerRewrite::isObsoleteFor(originalLType)) { arg.rewrite = &integerRewrite; arg.ltype = integerRewrite.type(arg.type, arg.ltype); From 626875d595d6345fa035d3ef8502480e94fba426 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 16 Mar 2015 00:16:16 +0100 Subject: [PATCH 004/101] Win64 ABI: Return 80-bit real/ireal on x87 stack. Just like DMD. Inline assembly in druntime/phobos depends on this. Only relevant for MinGW-w64 as MSVC uses 64-bit real. --- gen/abi-win64.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gen/abi-win64.cpp b/gen/abi-win64.cpp index 7dc22f0af72..25d4972c694 100644 --- a/gen/abi-win64.cpp +++ b/gen/abi-win64.cpp @@ -119,6 +119,10 @@ bool Win64TargetABI::returnInArg(TypeFunction* tf) Type* rt = tf->next->toBasetype(); + // * let LLVM return 80-bit real/ireal on the x87 stack, for DMD compliance + if (realIs80bits() && (rt->ty == Tfloat80 || rt->ty == Timaginary80)) + return false; + // * all POD types <= 64 bits and of a size that is a power of 2 // (incl. 2x32-bit cfloat) are returned in a register (RAX, or // XMM0 for single float/ifloat/double/idouble) From fa6c7002ee1b0333fce80eb6c78623b5ccdb4484 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 21 Mar 2015 17:43:21 +0100 Subject: [PATCH 005/101] Get rid of LDC workarounds in Phobos. --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index c56a25fde69..92d5870574b 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit c56a25fde691cae9a3cc125ae7232dc1dbcd7ced +Subproject commit 92d5870574b661ee1ce5a0ba7950df818b39372f From a473a2aa2c8f43c39222c025bed598499c8b926a Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 21 Mar 2015 19:09:31 +0100 Subject: [PATCH 006/101] LLVM 3.7: Do not declare -boundscheck twice --- driver/cl_options.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index f513d63e43e..65827f8da5f 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -334,8 +334,10 @@ class BoundsChecksAdapter { } }; +#if LDC_LLVM_VER < 307 cl::opt boundsChecksOld("boundscheck", cl::desc("(*) Enable array bounds check (deprecated, use -boundscheck=on|off)")); +#endif cl::opt boundsChecksNew("boundscheck", cl::desc("(*) Enable array bounds check"), From c0e23d6814d64bfbdca0a9d1e827a5574e1dbe1c Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 22 Mar 2015 13:55:53 +0100 Subject: [PATCH 007/101] LLVM 3.7: llvm::GetElementPtrInst() requires the pointed-to type. Currently, the pointer type is passed which causes an assertion. Also add assertion to verify that parameter ptr is really of a pointer type. --- gen/tollvm.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 7da2111dc28..80160e1fd88 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -307,9 +307,11 @@ LLIntegerType* DtoSize_t() LLValue* DtoGEP1(LLValue* ptr, LLValue* i0, const char* var, llvm::BasicBlock* bb) { + LLPointerType* p = isaPointer(ptr); + assert(p && "GEP expects a pointer type"); return llvm::GetElementPtrInst::Create( #if LDC_LLVM_VER >= 307 - ptr->getType(), + p->getElementType(), #endif ptr, i0, var, bb ? bb : gIR->scopebb()); } @@ -318,10 +320,12 @@ LLValue* DtoGEP1(LLValue* ptr, LLValue* i0, const char* var, llvm::BasicBlock* b LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var, llvm::BasicBlock* bb) { + LLPointerType* p = isaPointer(ptr); + assert(p && "GEP expects a pointer type"); LLValue* v[] = { i0, i1 }; return llvm::GetElementPtrInst::Create( #if LDC_LLVM_VER >= 307 - ptr->getType(), + p->getElementType(), #endif ptr, v, var, bb ? bb : gIR->scopebb()); } @@ -330,9 +334,11 @@ LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var, llvm::B LLValue* DtoGEPi1(LLValue* ptr, unsigned i, const char* var, llvm::BasicBlock* bb) { + LLPointerType* p = isaPointer(ptr); + assert(p && "GEP expects a pointer type"); return llvm::GetElementPtrInst::Create( #if LDC_LLVM_VER >= 307 - ptr->getType(), + p->getElementType(), #endif ptr, DtoConstUint(i), var, bb ? bb : gIR->scopebb()); } @@ -341,10 +347,12 @@ LLValue* DtoGEPi1(LLValue* ptr, unsigned i, const char* var, llvm::BasicBlock* b LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var, llvm::BasicBlock* bb) { + LLPointerType* p = isaPointer(ptr); + assert(p && "GEP expects a pointer type"); LLValue* v[] = { DtoConstUint(i0), DtoConstUint(i1) }; return llvm::GetElementPtrInst::Create( #if LDC_LLVM_VER >= 307 - ptr->getType(), + p->getElementType(), #endif ptr, v, var, bb ? bb : gIR->scopebb()); } From 1b7bca65b2c3e13bdca58aeb5287ae38bc8839a0 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Wed, 25 Mar 2015 19:05:12 +0100 Subject: [PATCH 008/101] LLVM 3.7: Include of is required --- driver/toobj.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/driver/toobj.cpp b/driver/toobj.cpp index dc60a87a180..eb1e641ab6e 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -31,6 +31,9 @@ #if LDC_LLVM_VER < 304 #include "llvm/Support/PathV1.h" #endif +#if LDC_LLVM_VER >= 307 +#include "llvm/Support/Path.h" +#endif #include "llvm/Target/TargetMachine.h" #if LDC_LLVM_VER >= 307 #include "llvm/Analysis/TargetTransformInfo.h" From 3a6d7bad96ace44a57a1d0262217874d7d63b1d1 Mon Sep 17 00:00:00 2001 From: kai Date: Sat, 28 Mar 2015 18:20:45 +0100 Subject: [PATCH 009/101] Fix for issue #874. After running `git gc` cmake may fail to configure the build. `git gc` deleted the file `.git/refs/head/merge-2.067` (my current branch) and moved the reference into file `.git/packed-refs`. This file is not parsed for the reference. Solution is (a) parse `.git/packed-refs` if ref is not found or (b) use git rev-parse --symbolic-full-name HEAD to get the reference and git show-ref --hash ${HEAD_REF} to get the hash. This commits uses solution (a). --- cmake/Modules/GetGitRevisionDescription.cmake.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/Modules/GetGitRevisionDescription.cmake.in b/cmake/Modules/GetGitRevisionDescription.cmake.in index 6faa374a8d9..940c42af02c 100644 --- a/cmake/Modules/GetGitRevisionDescription.cmake.in +++ b/cmake/Modules/GetGitRevisionDescription.cmake.in @@ -26,6 +26,12 @@ if(HEAD_CONTENTS MATCHES "ref") elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}") configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) set(HEAD_HASH "${HEAD_REF}") + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() endif() else() # detached HEAD From 7c835c2738b559a71b8a53ebfd6831624eb1f18c Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 28 Mar 2015 19:01:48 +0100 Subject: [PATCH 010/101] 2nd try at issue #874. The problem from issue #874 has another variant: If .git/logs/refs/heads/merge-2.067 exists then this ref is returned as hash value(!). This is plain wrong. Solution is again to look up `.git/packed-refs`. --- cmake/Modules/GetGitRevisionDescription.cmake.in | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmake/Modules/GetGitRevisionDescription.cmake.in b/cmake/Modules/GetGitRevisionDescription.cmake.in index 940c42af02c..6d8b708efe5 100644 --- a/cmake/Modules/GetGitRevisionDescription.cmake.in +++ b/cmake/Modules/GetGitRevisionDescription.cmake.in @@ -23,9 +23,6 @@ if(HEAD_CONTENTS MATCHES "ref") string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") if(EXISTS "@GIT_DIR@/${HEAD_REF}") configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) - elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}") - configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) - set(HEAD_HASH "${HEAD_REF}") else() configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) From f8bddb3e996bb0c57392ca0ca231a0563783aa55 Mon Sep 17 00:00:00 2001 From: kai Date: Fri, 3 Apr 2015 12:56:46 +0200 Subject: [PATCH 011/101] Add AssemblyAnnotationWriter. Outputs debug information as comments in .ll file. Provided by Trass3r. --- driver/toobj.cpp | 170 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 1 deletion(-) diff --git a/driver/toobj.cpp b/driver/toobj.cpp index eb1e641ab6e..842bff2ecb3 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -14,8 +14,10 @@ #include "gen/optimizer.h" #include "gen/programs.h" #if LDC_LLVM_VER >= 305 +#include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/Verifier.h" #else +#include "llvm/Assembly/AssemblyAnnotationWriter.h" #include "llvm/Analysis/Verifier.h" #endif #include "llvm/Bitcode/ReaderWriter.h" @@ -142,6 +144,171 @@ static void assemble(const std::string &asmpath, const std::string &objpath) ////////////////////////////////////////////////////////////////////////////////////////// +namespace +{ + using namespace llvm; + static void printDebugLoc(const DebugLoc& debugLoc, formatted_raw_ostream& os) + { + os << debugLoc.getLine() << ":" << debugLoc.getCol(); +#if LDC_LLVM_VER >= 307 + if (MDLocation *IDL = debugLoc.getInlinedAt()) + { + os << "@"; + printDebugLoc(IDL, os); + } +#else + if (MDNode *N = debugLoc.getInlinedAt(getGlobalContext())) + { + DebugLoc IDL = DebugLoc::getFromDILocation(N); + if (!IDL.isUnknown()) + { + os << "@"; + printDebugLoc(IDL, os); + } + } +#endif + } + + class AssemblyAnnotator : public AssemblyAnnotationWriter + { + // Find the MDNode which corresponds to the DISubprogram data that described F. + static MDNode* FindSubprogram(const Function *F, DebugInfoFinder &Finder) + { +#if LDC_LLVM_VER >= 305 + for (DISubprogram Subprogram : Finder.subprograms()) { +#else + for (DebugInfoFinder::iterator I = Finder.subprogram_begin(), + E = Finder.subprogram_end(); + I != E; ++I) { + DISubprogram Subprogram(*I); +#endif + if (Subprogram.describes(F)) return Subprogram; + } +#if LDC_LLVM_VER >= 305 + return nullptr; +#else + return 0; +#endif + } + + static llvm::StringRef GetDisplayName(const Function *F) + { + llvm::DebugInfoFinder Finder; +#if LDC_LLVM_VER >= 303 + Finder.processModule(*F->getParent()); +#else + Finder.processModule(const_cast(*F->getParent())); +#endif + if (MDNode* N = FindSubprogram(F, Finder)) + { + llvm::DISubprogram sub(N); + return sub.getDisplayName(); + } + return ""; + } + + public: + void emitFunctionAnnot(const Function* F, formatted_raw_ostream& os) LLVM_OVERRIDE + { + os << "; [#uses = " << F->getNumUses() << ']'; + + // show demangled name + llvm::StringRef funcName = GetDisplayName(F); + if (!funcName.empty()) + os << " [display name = " << funcName << ']'; + + os << '\n'; + } + + void printInfoComment(const Value& val, formatted_raw_ostream& os) LLVM_OVERRIDE + { + bool padding = false; + if (!val.getType()->isVoidTy()) + { + os.PadToColumn(50); + padding = true; + os << "; [#uses = " << val.getNumUses() << " type = " << *val.getType() << ']'; + } + + const Instruction* instr = dyn_cast(&val); + if (!instr) + return; + +#if LDC_LLVM_VER >= 307 + if (const DebugLoc &debugLoc = instr->getDebugLoc()) +#else + const DebugLoc& debugLoc = instr->getDebugLoc(); + if (!debugLoc.isUnknown()) +#endif + { + if (!padding) + { + os.PadToColumn(50); + padding = true; + os << ';'; + } + os << " [debug line = "; + printDebugLoc(debugLoc, os); + os << ']'; + } + if (const DbgDeclareInst* DDI = dyn_cast(instr)) + { + DIVariable Var(DDI->getVariable()); + if (!padding) + { + os.PadToColumn(50); + os << ";"; + } + os << " [debug variable = " << Var.getName() << ']'; + } + else if (const DbgValueInst* DVI = dyn_cast(instr)) + { + DIVariable Var(DVI->getVariable()); + if (!padding) + { + os.PadToColumn(50); + os << ";"; + } + os << " [debug variable = " << Var.getName() << ']'; + } + else if (const CallInst* callinstr = dyn_cast(instr)) + { + const Function* F = callinstr->getCalledFunction(); + if (!F) + return; + + StringRef funcName = GetDisplayName(F); + if (!funcName.empty()) + { + if (!padding) + { + os.PadToColumn(50); + os << ";"; + } + os << " [display name = " << funcName << ']'; + } + } + else if (const InvokeInst* invokeinstr = dyn_cast(instr)) + { + const Function* F = invokeinstr->getCalledFunction(); + if (!F) + return; + + StringRef funcName = GetDisplayName(F); + if (!funcName.empty()) + { + if (!padding) + { + os.PadToColumn(50); + os << ";"; + } + os << " [display name = " << funcName << ']'; + } + } + } + }; +} // end of anonymous namespace + void writeModule(llvm::Module* m, std::string filename) { // run optimizer @@ -222,7 +389,8 @@ void writeModule(llvm::Module* m, std::string filename) ); fatal(); } - m->print(aos, NULL); + AssemblyAnnotator annotator; + m->print(aos, &annotator); } // write native assembly From 1b3abdbb1432d46f6fa65e223b68fa0a7194d5f4 Mon Sep 17 00:00:00 2001 From: kai Date: Fri, 3 Apr 2015 23:32:08 +0200 Subject: [PATCH 012/101] Fix a missed big-endian issue. Most of the big-endian issue in the upstream frontend are now fixed. This commit https://github.com/D-Programming-Language/dmd/commit/79b2cd183fcf261d78c624a1d4b29a2ef19b0a07 has a change we have not yet implemented. --- dmd2/lexer.c | 4 ++-- dmd2/lexer.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dmd2/lexer.c b/dmd2/lexer.c index 288a2fd1044..af18014e34b 100644 --- a/dmd2/lexer.c +++ b/dmd2/lexer.c @@ -108,14 +108,14 @@ const char *Token::toChars() switch (value) { case TOKint32v: - sprintf(&buffer[0],"%d",int32value); + sprintf(&buffer[0], "%d", (d_int32)int64value); break; case TOKuns32v: case TOKcharv: case TOKwcharv: case TOKdcharv: - sprintf(&buffer[0],"%uU",uns32value); + sprintf(&buffer[0], "%uU", (d_uns32)uns64value); break; case TOKint64v: diff --git a/dmd2/lexer.h b/dmd2/lexer.h index feef131c0be..544ff9e4868 100644 --- a/dmd2/lexer.h +++ b/dmd2/lexer.h @@ -200,8 +200,10 @@ struct Token union { // Integers +#if !IN_LLVM d_int32 int32value; d_uns32 uns32value; +#endif d_int64 int64value; d_uns64 uns64value; From a4924c50e18ec1ea3280315e66783fd4755be3b3 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 4 Apr 2015 01:37:14 +0200 Subject: [PATCH 013/101] LLVM 3.7: llvm::ConstantExpr::getElementPtr() wants element type. This is the same change like the one on the GEP instruction. --- gen/arrays.cpp | 4 ++++ gen/toconstelem.cpp | 33 ++++++++++++++++++++++++++++++++- gen/toir.cpp | 14 +++++++++++++- gen/tollvm.cpp | 16 +++++++++++++--- ir/irclass.cpp | 6 ++++++ 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/gen/arrays.cpp b/gen/arrays.cpp index ccaf38c969d..b8dda90aad4 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -384,7 +384,11 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit) LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) }; +#if LDC_LLVM_VER >= 307 + LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(isaPointer(gvar)->getElementType(), gvar, idxs, true); +#else LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(gvar, idxs, true); +#endif gep = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(llelemty)); return DtoConstSlice(DtoConstSize_t(arrlen), gep, arrty); diff --git a/gen/toconstelem.cpp b/gen/toconstelem.cpp index a468db3d0e9..d9760be7599 100644 --- a/gen/toconstelem.cpp +++ b/gen/toconstelem.cpp @@ -205,7 +205,11 @@ class ToConstElemVisitor : public Visitor llvm::ConstantInt* zero = LLConstantInt::get(LLType::getInt32Ty(gIR->context()), 0, false); LLConstant* idxs[2] = { zero, zero }; +#if LDC_LLVM_VER >= 307 + LLConstant* arrptr = llvm::ConstantExpr::getGetElementPtr(isaPointer(gvar)->getElementType(), gvar, idxs, true); +#else LLConstant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar, idxs, true); +#endif if (t->ty == Tpointer) { @@ -235,7 +239,11 @@ class ToConstElemVisitor : public Visitor { llvm::Constant* ptr = toConstElem(e->e1); dinteger_t idx = undoStrideMul(e->loc, t1b, e->e2->toInteger()); +#if LDC_LLVM_VER >= 307 + result = llvm::ConstantExpr::getGetElementPtr(isaPointer(ptr)->getElementType(), ptr, DtoConstSize_t(idx)); +#else result = llvm::ConstantExpr::getGetElementPtr(ptr, DtoConstSize_t(idx)); +#endif } else { @@ -257,7 +265,11 @@ class ToConstElemVisitor : public Visitor dinteger_t idx = undoStrideMul(e->loc, t1b, e->e2->toInteger()); llvm::Constant* negIdx = llvm::ConstantExpr::getNeg(DtoConstSize_t(idx)); +#if LDC_LLVM_VER >= 307 + result = llvm::ConstantExpr::getGetElementPtr(isaPointer(ptr)->getElementType(), ptr, negIdx); +#else result = llvm::ConstantExpr::getGetElementPtr(ptr, negIdx); +#endif } else { @@ -311,7 +323,11 @@ class ToConstElemVisitor : public Visitor Type *type = vd->type->toBasetype(); if (type->ty == Tarray || type->ty == Tdelegate) { LLConstant* idxs[2] = { DtoConstSize_t(0), DtoConstSize_t(1) }; +#if LDC_LLVM_VER >= 307 + value = llvm::ConstantExpr::getGetElementPtr(isaPointer(value)->getElementType(), value, idxs, true); +#else value = llvm::ConstantExpr::getGetElementPtr(value, idxs, true); +#endif } result = DtoBitCast(value, DtoType(tb)); } @@ -376,7 +392,11 @@ class ToConstElemVisitor : public Visitor if (e->offset % elemSize == 0) { // We can turn this into a "nice" GEP. - result = llvm::ConstantExpr::getGetElementPtr(base, + result = llvm::ConstantExpr::getGetElementPtr( +#if LDC_LLVM_VER >= 307 + LLType::getInt8Ty(gIR->context()), +#endif + base, DtoConstSize_t(e->offset / elemSize)); } else @@ -384,6 +404,9 @@ class ToConstElemVisitor : public Visitor // Offset isn't a multiple of base type size, just cast to i8* and // apply the byte offset. result = llvm::ConstantExpr::getGetElementPtr( +#if LDC_LLVM_VER >= 307 + getVoidPtrType(), +#endif DtoBitCast(base, getVoidPtrType()), DtoConstSize_t(e->offset)); } @@ -430,7 +453,11 @@ class ToConstElemVisitor : public Visitor LLConstant* idxs[2] = { DtoConstSize_t(0), index }; LLConstant *val = isaConstant(getIrGlobal(vd)->value); val = DtoBitCast(val, DtoType(vd->type->pointerTo())); +#if LDC_LLVM_VER >= 307 + LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(isaPointer(val)->getElementType(), val, idxs, true); +#else LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(val, idxs, true); +#endif // bitcast to requested type assert(e->type->toBasetype()->ty == Tpointer); @@ -561,7 +588,11 @@ class ToConstElemVisitor : public Visitor // build a constant dynamic array reference with the .ptr field pointing into store LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) }; +#if LDC_LLVM_VER >= 307 + LLConstant* globalstorePtr = llvm::ConstantExpr::getGetElementPtr(isaPointer(store)->getElementType(), store, idxs, true); +#else LLConstant* globalstorePtr = llvm::ConstantExpr::getGetElementPtr(store, idxs, true); +#endif result = DtoConstSlice(DtoConstSize_t(e->elements->dim), globalstorePtr); } diff --git a/gen/toir.cpp b/gen/toir.cpp index a20c7b2a533..10bf2d8d08a 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -365,7 +365,11 @@ class ToElemVisitor : public Visitor llvm::ConstantInt* zero = LLConstantInt::get(LLType::getInt32Ty(gIR->context()), 0, false); LLConstant* idxs[2] = { zero, zero }; +#if LDC_LLVM_VER >= 307 + LLConstant* arrptr = llvm::ConstantExpr::getGetElementPtr(isaPointer(gvar)->getElementType(), gvar, idxs, true); +#else LLConstant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar, idxs, true); +#endif if (dtype->ty == Tarray) { LLConstant* clen = LLConstantInt::get(DtoSize_t(), e->len, false); @@ -1785,7 +1789,7 @@ class ToElemVisitor : public Visitor offset = LLConstantInt::get(DtoSize_t(), static_cast(-1), true); post = llvm::GetElementPtrInst::Create( #if LDC_LLVM_VER >= 307 - val->getType(), + isaPointer(val)->getElementType(), #endif val, offset, "", p->scopebb()); } @@ -2836,14 +2840,22 @@ class ToElemVisitor : public Visitor LLConstant* initval = arrayConst(keysInits, indexType); LLConstant* globalstore = new LLGlobalVariable(*gIR->module, initval->getType(), false, LLGlobalValue::InternalLinkage, initval, ".aaKeysStorage"); +#if LDC_LLVM_VER >= 307 + LLConstant* slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true); +#else LLConstant* slice = llvm::ConstantExpr::getGetElementPtr(globalstore, idxs, true); +#endif slice = DtoConstSlice(DtoConstSize_t(e->keys->dim), slice); LLValue* keysArray = DtoAggrPaint(slice, funcTy->getParamType(1)); initval = arrayConst(valuesInits, vtype); globalstore = new LLGlobalVariable(*gIR->module, initval->getType(), false, LLGlobalValue::InternalLinkage, initval, ".aaValuesStorage"); +#if LDC_LLVM_VER >= 307 + slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true); +#else slice = llvm::ConstantExpr::getGetElementPtr(globalstore, idxs, true); +#endif slice = DtoConstSlice(DtoConstSize_t(e->keys->dim), slice); LLValue* valuesArray = DtoAggrPaint(slice, funcTy->getParamType(2)); diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 80160e1fd88..bc9223c6e28 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -361,8 +361,14 @@ LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var, llvm:: LLConstant* DtoGEPi(LLConstant* ptr, unsigned i0, unsigned i1) { + LLPointerType* p = isaPointer(ptr); + assert(p && "GEP expects a pointer type"); LLValue* v[] = { DtoConstUint(i0), DtoConstUint(i1) }; - return llvm::ConstantExpr::getGetElementPtr(ptr, v, true); + return llvm::ConstantExpr::getGetElementPtr( +#if LDC_LLVM_VER >= 307 + p->getElementType(), +#endif + ptr, v, true); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -491,14 +497,18 @@ LLConstant* DtoConstFP(Type* t, longdouble value) LLConstant* DtoConstString(const char* str) { llvm::StringRef s(str ? str : ""); - LLConstant* init = llvm::ConstantDataArray::getString(gIR->context(), s, true); + llvm::Constant* init = llvm::ConstantDataArray::getString(gIR->context(), s, true); llvm::GlobalVariable* gvar = new llvm::GlobalVariable( *gIR->module, init->getType(), true, llvm::GlobalValue::InternalLinkage, init, ".str"); gvar->setUnnamedAddr(true); LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) }; return DtoConstSlice( DtoConstSize_t(s.size()), - llvm::ConstantExpr::getGetElementPtr(gvar, idxs, true), + llvm::ConstantExpr::getGetElementPtr( +#if LDC_LLVM_VER >= 307 + init->getType(), +#endif + gvar, idxs, true), Type::tchar->arrayOf() ); } diff --git a/ir/irclass.cpp b/ir/irclass.cpp index ae66359afda..9ac45d233c4 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -301,6 +301,9 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance llvm::GlobalVariable* interfaceInfosZ = getInterfaceArraySymbol(); llvm::Constant* c = llvm::ConstantExpr::getGetElementPtr( +#if LDC_LLVM_VER >= 307 + isaPointer(interfaceInfosZ)->getElementType(), +#endif interfaceInfosZ, idxs, true); constants.push_back(c); @@ -513,6 +516,9 @@ LLConstant * IrAggr::getClassInfoInterfaces() }; LLConstant* ptr = llvm::ConstantExpr::getGetElementPtr( +#if LDC_LLVM_VER >= 307 + isaPointer(classInterfacesArray)->getElementType(), +#endif classInterfacesArray, idxs, true); // return as a slice From 13fb3f2acee8dbf9feaf8128b1a7b0f5eb295ca0 Mon Sep 17 00:00:00 2001 From: kai Date: Fri, 3 Apr 2015 16:28:37 +0200 Subject: [PATCH 014/101] Fix for issue #855. Linking several modules together seems to trigger assertions with identified structs. In debug builds, the assertion !(Pair.first != Ty && Pair.second == Ty) && "mapping to a source type" is raised. In non-debug builds, you often get a D exception saying "Enforcement failed". Reason seems to be the use of the some type object in different modules. E.g. module A imports from module B the struct S. Then both modules refer to the same identifed llvm::StructType object. This causes the errors. The behaviour may be an LLVM bug. There is no test case for this situation. This affects all supported LLVM versions. If the target module is changed (e.g. use of llvmModule[0] instead of an empty module) then the error occurs in other LLVM versions, too. This commit uses the following workaround: - target module is llvmModule[0] (instead of an empty module) - each other module is first linked into an empty module and then into the target module. This is really ugly but avoids the error. There is no new test case required because runnable/A16.d already checks it. --- driver/main.cpp | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/driver/main.cpp b/driver/main.cpp index af859b198e5..fbc2c09887d 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -1384,21 +1384,41 @@ int main(int argc, char **argv) char* moduleName = m->toChars(); #endif -#if LDC_LLVM_VER >= 303 - llvm::Module *dest = new llvm::Module(moduleName, context); - llvm::Linker linker(dest); +#if LDC_LLVM_VER >= 306 + llvm::Linker linker(llvmModules[0]); +#elif LDC_LLVM_VER >= 303 + llvm::Linker linker(new llvm::Module(moduleName, context)); #else llvm::Linker linker("ldc", moduleName, context); #endif std::string errormsg; +#if LDC_LLVM_VER >= 306 + for (size_t i = 1; i < llvmModules.size(); i++) +#else for (size_t i = 0; i < llvmModules.size(); i++) +#endif { #if LDC_LLVM_VER >= 306 - linker.linkInModule(llvmModules[i]); + // Issue #855: There seems to be a problem with identified structs. + // If a module imports a class or struct from another module and + // both modules are compiled together then both modules use the + // same type object. The error happens if the type is already + // remapped in one module and then the other module is linked. + // The workaround seems to be to do the linking twice, always + // uniquing all identified structs. + // + // This replaces the line: + // linker.linkInModule(llvmModules[i]); + // + // TODO: Check LLVM bug database if this is a bug. + llvm::Linker dummy(new llvm::Module("dummy module", context)); + dummy.linkInModule(llvmModules[i]); + linker.linkInModule(dummy.getModule()); + dummy.deleteModule(); #else #if LDC_LLVM_VER >= 303 - if (linker.linkInModule(llvmModules[i], llvm::Linker::DestroySource, &errormsg)) + if (linker.linkInModule(llvmModules[i], &errormsg)) #else if (linker.LinkInModule(llvmModules[i], &errormsg)) #endif @@ -1411,8 +1431,10 @@ int main(int argc, char **argv) writeModule(linker.getModule(), filename); global.params.objfiles->push(const_cast(filename)); -#if LDC_LLVM_VER >= 303 - delete dest; +#if LDC_LLVM_VER >= 304 + linker.deleteModule(); +#elif LDC_LLVM_VER == 303 + delete linker.getModule(); #endif } From e3a047628587cec3a4778a1e3aeaaf1aeac8eb2d Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 5 Apr 2015 03:21:25 +0200 Subject: [PATCH 015/101] Allow failure for Travis multilib tests Temporary fix until I understand the environment problem. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3a27ee1b7e5..5090837dbc3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,8 +45,6 @@ env: - LLVM_PACKAGE="llvm-3.3 llvm-3.3-dev" TEST_DEBUG=1 - LLVM_PACKAGE="llvm-3.3 llvm-3.3-dev" - LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" TEST_DEBUG=1 - - LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" OPTS="-DMULTILIB=ON" TEST_BITNESS=32 - - LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" OPTS="-DMULTILIB=ON" TEST_BITNESS=64 - LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" TEST_DEBUG=1 OPTS="-DBUILD_SHARED_LIBS=ON" - LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" OPTS="-DBUILD_SHARED_LIBS=ON" - LLVM_PACKAGE="llvm-3.5 llvm-3.5-dev libedit2 libedit-dev" TEST_DEBUG=1 @@ -57,6 +55,8 @@ env: - LLVM_PACKAGE="llvm-3.7 llvm-3.7-dev libedit2 libedit-dev" matrix: allow_failures: + - env: LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" OPTS="-DMULTILIB=ON" TEST_BITNESS=32 + - env: LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" OPTS="-DMULTILIB=ON" TEST_BITNESS=64 - env: LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" TEST_DEBUG=1 - env: LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" - env: LLVM_PACKAGE="llvm-3.7 llvm-3.7-dev libedit2 libedit-dev" TEST_DEBUG=1 From d906bb108732b47bf066922b4448b227c1534146 Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 5 Apr 2015 03:43:34 +0200 Subject: [PATCH 016/101] Remove 2 unused include files --- dmd2/lib.h | 47 ----------------------------------------------- dmd2/total.h | 46 ---------------------------------------------- 2 files changed, 93 deletions(-) delete mode 100644 dmd2/lib.h delete mode 100644 dmd2/total.h diff --git a/dmd2/lib.h b/dmd2/lib.h deleted file mode 100644 index 465fb4ea1a5..00000000000 --- a/dmd2/lib.h +++ /dev/null @@ -1,47 +0,0 @@ - -/* Compiler implementation of the D programming language - * Copyright (c) 1999-2014 by Digital Mars - * All Rights Reserved - * written by Walter Bright - * http://www.digitalmars.com - * Distributed under the Boost Software License, Version 1.0. - * http://www.boost.org/LICENSE_1_0.txt - * https://github.com/D-Programming-Language/dmd/blob/master/src/lib.h - */ - -#ifndef DMD_LIB_H -#define DMD_LIB_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -Library *LibMSCoff_factory(); -Library *LibOMF_factory(); -Library *LibElf_factory(); -Library *LibMach_factory(); - -class Library -{ - public: - static Library *factory() - { -#if TARGET_WINDOS - return global.params.is64bit ? LibMSCoff_factory() : LibOMF_factory(); -#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS - return LibElf_factory(); -#elif TARGET_OSX - return LibMach_factory(); -#else - assert(0); // unsupported system -#endif - } - - virtual void setFilename(const char *dir, const char *filename) = 0; - virtual void addObject(const char *module_name, void *buf, size_t buflen) = 0; - virtual void addLibrary(void *buf, size_t buflen) = 0; - virtual void write() = 0; -}; - -#endif /* DMD_LIB_H */ - diff --git a/dmd2/total.h b/dmd2/total.h deleted file mode 100644 index 42f38765e53..00000000000 --- a/dmd2/total.h +++ /dev/null @@ -1,46 +0,0 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://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. - -#ifndef DMD_TOTAL_H -#define DMD_TOTAL_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include -#include -#include -#include -#include - -#include "root.h" -#include "stringtable.h" - -#include "arraytypes.h" -#include "mars.h" -#include "lexer.h" -#include "parse.h" -#include "identifier.h" -#include "enum.h" -#include "aggregate.h" -#include "mtype.h" -#include "expression.h" -#include "declaration.h" -#include "statement.h" -#include "scope.h" -#include "import.h" -#include "module.h" -#include "id.h" -#include "cond.h" -#include "version.h" -#include "lib.h" - -#endif /* DMD_TOTAL_H */ From fcf13ab2d4969702d60dbd9ed9fb6f4b1ac5473a Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 5 Apr 2015 04:46:15 +0200 Subject: [PATCH 017/101] Fix builtin version of llvm.minnum.# and llvm.maxnum.# This fixes a failing test with LLVM 3.6. --- dmd2/builtin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd2/builtin.c b/dmd2/builtin.c index 96dddd8e7e9..6c01821f81d 100644 --- a/dmd2/builtin.c +++ b/dmd2/builtin.c @@ -166,7 +166,7 @@ Expression *eval_llvmminnum(Loc loc, FuncDeclaration *fd, Expressions *arguments assert(arg0->op == TOKfloat64); Expression *arg1 = (*arguments)[1]; assert(arg1->op == TOKfloat64); - return new RealExp(loc, fmin(arg0->toReal(), arg1->toReal()), type); + return new RealExp(loc, fminl(arg0->toReal(), arg1->toReal()), type); } Expression *eval_llvmmaxnum(Loc loc, FuncDeclaration *fd, Expressions *arguments) @@ -176,7 +176,7 @@ Expression *eval_llvmmaxnum(Loc loc, FuncDeclaration *fd, Expressions *arguments assert(arg0->op == TOKfloat64); Expression *arg1 = (*arguments)[1]; assert(arg1->op == TOKfloat64); - return new RealExp(loc, fmax(arg0->toReal(), arg1->toReal()), type); + return new RealExp(loc, fmaxl(arg0->toReal(), arg1->toReal()), type); } Expression *eval_llvmfloor(Loc loc, FuncDeclaration *fd, Expressions *arguments) From 014627d6a60219266a67b5991b226535c5b09285 Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 5 Apr 2015 14:20:31 +0200 Subject: [PATCH 018/101] Code cleanup: Replace NULL with false in dibuilder. Removes some warnings. --- gen/dibuilder.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index eaa94aa3d3d..104a9b2bde0 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -189,7 +189,7 @@ llvm::DIType ldc::DIBuilder::CreateEnumType(Type *type) getABITypeAlign(T)*8, // align (bits) DBuilder.getOrCreateArray(subscripts) // subscripts #if LDC_LLVM_VER >= 302 - , CreateTypeDescription(te->sym->memtype, NULL) + , CreateTypeDescription(te->sym->memtype, false) #endif ); } @@ -203,7 +203,7 @@ llvm::DIType ldc::DIBuilder::CreatePointerType(Type *type) // find base type Type *nt = t->nextOf(); - llvm::DIType basetype = CreateTypeDescription(nt, NULL); + llvm::DIType basetype = CreateTypeDescription(nt, false); return DBuilder.createPointerType( basetype, @@ -230,7 +230,7 @@ llvm::DIType ldc::DIBuilder::CreateVectorType(Type *type) { DBuilder.getOrCreateSubrange(0, Dim) }; - llvm::DIType basetype = CreateTypeDescription(te, NULL); + llvm::DIType basetype = CreateTypeDescription(te, false); return DBuilder.createVectorType( getTypeBitSize(T), // size (bits) @@ -494,7 +494,7 @@ llvm::DIType ldc::DIBuilder::CreateSArrayType(Type *type) subscripts.push_back(subscript); t = t->nextOf(); } - llvm::DIType basetype = CreateTypeDescription(t, NULL); + llvm::DIType basetype = CreateTypeDescription(t, false); return DBuilder.createArrayType( getTypeBitSize(T), // size (bits) @@ -896,7 +896,7 @@ llvm::DIGlobalVariable ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable * #endif CreateFile(vd->loc), // file vd->loc.linnum, // line num - CreateTypeDescription(vd->type, NULL), // type + CreateTypeDescription(vd->type, false), // type vd->protection == PROTprivate, // is local to unit ll // value ); From 505f18ca2a81a4bb598b4bd620284837aa4a933b Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Thu, 26 Mar 2015 22:48:53 +0100 Subject: [PATCH 019/101] Add coverage analysis ("-cov=...") to ldc2 --- dmd2/mars.h | 5 +- dmd2/module.c | 2 + dmd2/module.h | 5 ++ driver/cl_options.cpp | 34 ++++++++++++ driver/ldmd.cpp | 16 +++--- driver/main.cpp | 2 + gen/coverage.cpp | 51 +++++++++++++++++ gen/coverage.h | 22 ++++++++ gen/module.cpp | 124 ++++++++++++++++++++++++++++++++++++++++++ gen/runtime.cpp | 17 ++++++ gen/statements.cpp | 28 ++++++++++ gen/toir.cpp | 3 + 12 files changed, 300 insertions(+), 9 deletions(-) create mode 100644 gen/coverage.cpp create mode 100644 gen/coverage.h diff --git a/dmd2/mars.h b/dmd2/mars.h index aaecf257b57..6b5044e9f46 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -170,8 +170,6 @@ struct Param #else bool pic; // generate position-independent-code for shared libs bool color; // use ANSI colors in console output - bool cov; // generate code coverage data - unsigned char covPercent; // 0..100 code coverage percentage required bool nofloat; // code should not pull in floating point support bool ignoreUnsupportedPragmas; // rather than error on them bool enforcePropertySyntax; @@ -180,6 +178,9 @@ struct Param bool allInst; // generate code for all template instantiations #endif + bool cov; // generate code coverage data + unsigned char covPercent; // 0..100 code coverage percentage required + const char *argv0; // program name Strings *imppath; // array of char*'s of where to look for import modules Strings *fileImppath; // array of char*'s of where to look for file import modules diff --git a/dmd2/module.c b/dmd2/module.c index c7dce9348b4..a6de5e3bd73 100644 --- a/dmd2/module.c +++ b/dmd2/module.c @@ -147,6 +147,8 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do this->doDocComment = doDocComment; this->doHdrGen = doHdrGen; this->arrayfuncs = 0; + d_cover_valid = NULL; + d_cover_data = NULL; #endif } diff --git a/dmd2/module.h b/dmd2/module.h index 60f46fbb0e4..35a2718ff32 100644 --- a/dmd2/module.h +++ b/dmd2/module.h @@ -214,6 +214,11 @@ class Module : public Package // array ops emitted in this module already AA *arrayfuncs; + + // Coverage analysis + llvm::GlobalVariable* d_cover_valid; // private immutable size_t[] _d_cover_valid; + llvm::GlobalVariable* d_cover_data; // private uint[] _d_cover_data; + std::vector d_cover_valid_init; // initializer for _d_cover_valid #endif Module *isModule() { return this; } diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index 65827f8da5f..ab7a023e3f6 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -23,6 +23,34 @@ namespace opts { +/* Option parser that defaults to zero when no explicit number is given. + * i.e.: -cov --> value = 0 + * -cov=9 --> value = 9 + * -cov=101 --> error, value must be in range [0..100] + */ +struct CoverageParser : public cl::parser { +#if LDC_LLVM_VER >= 307 + CoverageParser(cl::Option &O) : cl::parser(O) {} +#endif + + bool parse(cl::Option &O, llvm::StringRef ArgName, llvm::StringRef Arg, unsigned char &Val) + { + if (Arg == "") { + Val = 0; + return false; + } + + if (Arg.getAsInteger(0, Val)) + return O.error("'" + Arg + "' value invalid for required coverage percentage"); + + if (Val > 100) { + return O.error("Required coverage percentage must be <= 100"); + } + return false; + } +}; + + // Positional options first, in order: cl::list fileList( cl::Positional, cl::desc("files")); @@ -412,6 +440,12 @@ cl::opt color("color", cl::desc("Force colored console output"), cl::location(global.params.color)); +cl::opt coverageAnalysis("cov", + cl::desc("Compile-in code coverage analysis\n(use -cov=n for n% minimum required coverage)"), + cl::location(global.params.covPercent), + cl::ValueOptional, + cl::init(127)); + static cl::extrahelp footer("\n" "-d-debug can also be specified without options, in which case it enables all\n" "debug checks (i.e. (asserts, boundchecks, contracts and invariants) as well\n" diff --git a/driver/ldmd.cpp b/driver/ldmd.cpp index f07d2dc2cc9..d5a765b6bb1 100644 --- a/driver/ldmd.cpp +++ b/driver/ldmd.cpp @@ -234,11 +234,10 @@ Usage:\n\ files.d D source files\n\ @cmdfile read arguments from cmdfile\n\ -c do not link\n\ - -color[=on|off] force colored console output on or off\n" -#if 0 -" -cov do code coverage analysis\n" -#endif -" -D generate documentation\n\ + -color[=on|off] force colored console output on or off\n\ + -cov do code coverage analysis\n\ + -cov=nnn require at least nnn%% code coverage\n\ + -D generate documentation\n\ -Dddocdir write documentation file to docdir directory\n\ -Dffilename write documentation file to filename\n\ -d allow deprecated features\n\ @@ -599,7 +598,10 @@ Params parseArgs(size_t originalArgc, char** originalArgv, const std::string &ld goto Lerror; } else if (strcmp(p + 1, "cov") == 0) - result.coverage = true; + // For "-cov=...", the whole cmdline switch is forwarded to LDC. + // For plain "-cov", the cmdline switch must be explicitly forwarded + // and result.coverage must be set to true to that effect. + result.coverage = (p[4] != '='); else if (strcmp(p + 1, "shared") == 0 // backwards compatibility with old switch || strcmp(p + 1, "dylib") == 0 @@ -935,7 +937,7 @@ void buildCommandLine(std::vector& r, const Params& p) { if (p.allowDeprecated) r.push_back("-d"); if (p.compileOnly) r.push_back("-c"); - if (p.coverage) warning("Coverage report generation not yet supported by LDC."); + if (p.coverage) r.push_back("-cov"); if (p.emitSharedLib) r.push_back("-shared"); if (p.pic) r.push_back("-relocation-model=pic"); if (p.emitMap) warning("Map file generation not yet supported by LDC."); diff --git a/driver/main.cpp b/driver/main.cpp index fbc2c09887d..a4c9e54a669 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -373,6 +373,8 @@ static void parseCommandLine(int argc, char **argv, Strings &sourceFiles, bool & global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno; global.params.output_s = opts::output_s ? OUTPUTFLAGset : OUTPUTFLAGno; + global.params.cov = (global.params.covPercent <= 100); + templateLinkage = opts::linkonceTemplates ? LLGlobalValue::LinkOnceODRLinkage : LLGlobalValue::WeakODRLinkage; diff --git a/gen/coverage.cpp b/gen/coverage.cpp new file mode 100644 index 00000000000..133da00f60c --- /dev/null +++ b/gen/coverage.cpp @@ -0,0 +1,51 @@ +//===-- gen/coverage.h - Code Coverage Analysis -----------------*- C++ -*-===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// + +#include "gen/coverage.h" + +#include "mars.h" +#include "module.h" +#include "gen/irstate.h" +#include "gen/logger.h" + +void emitCoverageLinecountInc(Loc &loc) { + // Only emit coverage increment for locations in the source of the current module + // (for example, 'inlined' methods from other source files should be skipped). + if ( global.params.cov && (loc.linnum != 0) && loc.filename + && (gIR->module->getModuleIdentifier().compare(loc.filename) == 0) ) + { + unsigned line = loc.linnum-1; // convert to 0-based line# index + assert(line < gIR->dmodule->numlines); + { + IF_LOG Logger::println("Coverage: increment _d_cover_data[%d]", line); + + // Get GEP into _d_cover_data array + LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(line) }; + LLValue* ptr = llvm::ConstantExpr::getGetElementPtr(gIR->dmodule->d_cover_data, idxs, true); + + // Do an atomic increment, so this works when multiple threads are executed. + gIR->ir->CreateAtomicRMW( + llvm::AtomicRMWInst::Add, + ptr, + DtoConstUint(1), + llvm::Monotonic + ); + } + + { + unsigned num_sizet_bits = gDataLayout->getTypeSizeInBits(DtoSize_t()); + unsigned idx = line / num_sizet_bits; + unsigned bitidx = line % num_sizet_bits; + + IF_LOG Logger::println(" _d_cover_valid[%d] |= (1 << %d)", idx, bitidx); + + gIR->dmodule->d_cover_valid_init[idx] |= (size_t(1) << bitidx); + } + } +} \ No newline at end of file diff --git a/gen/coverage.h b/gen/coverage.h new file mode 100644 index 00000000000..7e9cc88f8a5 --- /dev/null +++ b/gen/coverage.h @@ -0,0 +1,22 @@ +//===-- gen/coverage.h - Code Coverage Analysis -----------------*- C++ -*-===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains functions to generate code for code coverage analysis. +// The coverage analysis is enabled by the "-cov" commandline switch. +// +//===----------------------------------------------------------------------===// + +#ifndef LDC_GEN_COVERAGE_H +#define LDC_GEN_COVERAGE_H + +struct Loc; + +void emitCoverageLinecountInc(Loc &loc); + +#endif diff --git a/gen/module.cpp b/gen/module.cpp index 66fc48d0a80..12a8ce0f345 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -555,6 +555,119 @@ static void build_llvm_used_array(IRState* p) llvmUsed->setSection("llvm.metadata"); } +// Add module-private variables and functions for coverage analysis. +static void addCoverageAnalysis(Module* m) +{ + IF_LOG { + Logger::println("Adding coverage analysis for module %s (%d lines)", m->srcfile->toChars(), m->numlines); + Logger::indent(); + } + + // size_t[# source lines / # bits in sizeTy] _d_cover_valid + LLValue* d_cover_valid_slice = NULL; + { + unsigned Dsizet_bits = gDataLayout->getTypeSizeInBits(DtoSize_t()); + size_t array_size = (m->numlines + (Dsizet_bits-1)) / Dsizet_bits; // ceil + + // Work around a bug in the interface of druntime's _d_cover_register2 + // https://issues.dlang.org/show_bug.cgi?id=14417 + // For safety, make the array large enough such that the slice passed to _d_cover_register2 is completely valid. + array_size = m->numlines; + + IF_LOG Logger::println("Build private variable: size_t[%d] _d_cover_valid", array_size); + + llvm::ArrayType* type = llvm::ArrayType::get(DtoSize_t(), array_size); + llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type); + m->d_cover_valid = new llvm::GlobalVariable(*gIR->module, type, true, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_valid"); + LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) }; + d_cover_valid_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), + llvm::ConstantExpr::getGetElementPtr(m->d_cover_valid, idxs, true) ); + + // Assert that initializer array elements have enough bits + assert(sizeof(m->d_cover_valid_init[0])*8 >= gDataLayout->getTypeSizeInBits(DtoSize_t())); + m->d_cover_valid_init.resize(array_size); + } + + // uint[# source lines] _d_cover_data + LLValue* d_cover_data_slice = NULL; + { + IF_LOG Logger::println("Build private variable: uint[%d] _d_cover_data", m->numlines); + + LLArrayType* type = LLArrayType::get(LLType::getInt32Ty(gIR->context()), m->numlines); + llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type); + m->d_cover_data = new llvm::GlobalVariable(*gIR->module, type, false, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_data"); + LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) }; + d_cover_data_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), + llvm::ConstantExpr::getGetElementPtr(m->d_cover_data, idxs, true) ); + } + + // Create "static constructor" that calls _d_cover_register2(string filename, size_t[] valid, uint[] data, ubyte minPercent) + // Build ctor name + LLFunction* ctor = NULL; + std::string ctorname = "_D"; + ctorname += mangle(gIR->dmodule); + ctorname += "12_coverageanalysisCtor1FZv"; + { + IF_LOG Logger::println("Build Coverage Analysis constructor: %s", ctorname.c_str()); + + LLFunctionType* ctorTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); + ctor = LLFunction::Create(ctorTy, LLGlobalValue::InternalLinkage, ctorname, gIR->module); + ctor->setCallingConv(gABI->callingConv(LINKd)); + // Set function attributes. See functions.cpp:DtoDefineFunction() + if (global.params.targetTriple.getArch() == llvm::Triple::x86_64) + { + ctor->addFnAttr(LDC_ATTRIBUTE(UWTable)); + } + + llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "", ctor); + IRBuilder<> builder(bb); + + // Set up call to _d_cover_register2 + llvm::Function* fn = LLVM_D_GetRuntimeFunction(Loc(), gIR->module, "_d_cover_register2"); + LLValue* args[] = { + getIrModule(m)->fileName->getInitializer(), + d_cover_valid_slice, + d_cover_data_slice, + DtoConstUbyte(global.params.covPercent) + }; + // Check if argument types are correct + for (unsigned i = 0; i < 4; ++i) { + assert(args[i]->getType() == fn->getFunctionType()->getParamType(i)); + } + + llvm::CallInst* call = builder.CreateCall(fn, args); + + builder.CreateRetVoid(); + } + + // Add the ctor to the module's static ctors list. TODO: This is quite the hack. + { + IF_LOG Logger::println("Add %s to module's shared static constructor list", ctorname.c_str()); + FuncDeclaration* fd = FuncDeclaration::genCfunc(NULL, Type::tvoid, ctorname.c_str()); + fd->linkage = LINKd; + IrFunction* irfunc = getIrFunc(fd, true); + irfunc->func = ctor; + gIR->sharedCtors.push_back(fd); + } + + IF_LOG Logger::undent(); +} + +// Initialize _d_cover_valid for coverage analysis +static void addCoverageAnalysisInitializer(Module* m) { + IF_LOG Logger::println("Adding coverage analysis _d_cover_valid initializer"); + + size_t array_size = m->d_cover_valid_init.size(); + + llvm::ArrayType* type = llvm::ArrayType::get(DtoSize_t(), array_size); + std::vector arrayInits(array_size); + for (size_t i=0; id_cover_valid_init[i]); + } + m->d_cover_valid->setInitializer(llvm::ConstantArray::get(type, arrayInits)); +} + static void codegenModule(Module* m) { // debug info @@ -667,8 +780,19 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context) LLVM_D_InitRuntime(); + // Note, skip pseudo-modules for coverage analysis + if ( global.params.cov && !mname.equals("__entrypoint.d") && !mname.equals("__main.d") ) + { + addCoverageAnalysis(this); + } + codegenModule(this); + if ( gIR->dmodule->d_cover_valid ) + { + addCoverageAnalysisInitializer(this); + } + gIR = NULL; if (llvmForceLogging && !logenabled) diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 682deddcd02..2dbc5061bec 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -1021,4 +1021,21 @@ static void LLVM_D_BuildRuntimeModule() llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, params, false); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); } + + // extern (C) void _d_cover_register2(string filename, size_t[] valid, uint[] data, ubyte minPercent) + // as defined in druntime/rt/cover.d. + if (global.params.cov) { + llvm::StringRef fname("_d_cover_register2"); + + LLType* params[] = { + stringTy, + rt_array(sizeTy), + rt_array(intTy), + byteTy + }; + + LLFunctionType* fty = LLFunctionType::get(voidTy, params, false); + llvm::Function* fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, fname, M); + fn->setCallingConv(gABI->callingConv(LINKc)); + } } diff --git a/gen/statements.cpp b/gen/statements.cpp index 455b217b572..ccc8215693b 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -14,6 +14,7 @@ #include "port.h" #include "gen/abi.h" #include "gen/arrays.h" +#include "gen/coverage.h" #include "gen/dvalue.h" #include "gen/irstate.h" #include "gen/llvm.h" @@ -102,6 +103,7 @@ static LLValue* call_string_switch_runtime(llvm::Value* table, Expression* e) return call.getInstruction(); } + ////////////////////////////////////////////////////////////////////////////// /* A visitor to walk entire tree of statements. @@ -372,6 +374,8 @@ class ToIRVisitor : public Visitor { // emit dwarf stop point gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + emitCoverageLinecountInc(stmt->loc); + // is there a return value expression? if (stmt->exp || (!stmt->exp && (irs->topfunc() == irs->mainFunc)) ) { @@ -491,6 +495,8 @@ class ToIRVisitor : public Visitor { // emit dwarf stop point gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + emitCoverageLinecountInc(stmt->loc); + if (stmt->exp) { elem* e; // a cast(void) around the expression is allowed, but doesn't require any code @@ -516,6 +522,8 @@ class ToIRVisitor : public Visitor { // start a dwarf lexical block gIR->DBuilder.EmitBlockStart(stmt->loc); + emitCoverageLinecountInc(stmt->loc); + if (stmt->match) DtoRawVarDeclaration(stmt->match); @@ -626,6 +634,7 @@ class ToIRVisitor : public Visitor { gIR->scope() = IRScope(whilebb, endbb); // create the condition + emitCoverageLinecountInc(stmt->condition->loc); DValue* cond_e = toElemDtor(stmt->condition); LLValue* cond_val = DtoCast(stmt->loc, cond_e, Type::tbool)->getRVal(); delete cond_e; @@ -686,6 +695,7 @@ class ToIRVisitor : public Visitor { gIR->scope() = IRScope(condbb,endbb); // create the condition + emitCoverageLinecountInc(stmt->condition->loc); DValue* cond_e = toElemDtor(stmt->condition); LLValue* cond_val = DtoCast(stmt->loc, cond_e, Type::tbool)->getRVal(); delete cond_e; @@ -742,6 +752,7 @@ class ToIRVisitor : public Visitor { llvm::Value* cond_val; if (stmt->condition) { + emitCoverageLinecountInc(stmt->condition->loc); DValue* cond_e = toElemDtor(stmt->condition); cond_val = DtoCast(stmt->loc, cond_e, Type::tbool)->getRVal(); delete cond_e; @@ -769,6 +780,7 @@ class ToIRVisitor : public Visitor { // increment if (stmt->increment) { + emitCoverageLinecountInc(stmt->increment->loc); DValue* inc = toElemDtor(stmt->increment); delete inc; } @@ -800,6 +812,8 @@ class ToIRVisitor : public Visitor { // emit dwarf stop point gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + emitCoverageLinecountInc(stmt->loc); + if (stmt->ident != 0) { IF_LOG Logger::println("ident = %s", stmt->ident->toChars()); @@ -861,6 +875,8 @@ class ToIRVisitor : public Visitor { // emit dwarf stop point gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + emitCoverageLinecountInc(stmt->loc); + if (stmt->ident != 0) { IF_LOG Logger::println("ident = %s", stmt->ident->toChars()); @@ -1076,6 +1092,8 @@ class ToIRVisitor : public Visitor { // emit dwarf stop point gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + emitCoverageLinecountInc(stmt->loc); + assert(stmt->exp); DValue* e = toElemDtor(stmt->exp); @@ -1103,6 +1121,8 @@ class ToIRVisitor : public Visitor { // emit dwarf stop point gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + emitCoverageLinecountInc(stmt->loc); + llvm::BasicBlock* oldbb = gIR->scopebb(); llvm::BasicBlock* oldend = gIR->scopeend(); @@ -1283,6 +1303,7 @@ class ToIRVisitor : public Visitor { assert(stmt->statement); gIR->DBuilder.EmitBlockStart(stmt->statement->loc); + emitCoverageLinecountInc(stmt->loc); stmt->statement->accept(this); gIR->DBuilder.EmitBlockEnd(); } @@ -1310,6 +1331,7 @@ class ToIRVisitor : public Visitor { assert(stmt->statement); gIR->DBuilder.EmitBlockStart(stmt->statement->loc); + emitCoverageLinecountInc(stmt->loc); stmt->statement->accept(this); gIR->DBuilder.EmitBlockEnd(); } @@ -1671,6 +1693,8 @@ class ToIRVisitor : public Visitor { gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + emitCoverageLinecountInc(stmt->loc); + llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergoto", irs->topfunc(), oldend); @@ -1687,6 +1711,8 @@ class ToIRVisitor : public Visitor { gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + emitCoverageLinecountInc(stmt->loc); + llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotodefault", irs->topfunc(), oldend); @@ -1707,6 +1733,8 @@ class ToIRVisitor : public Visitor { gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + emitCoverageLinecountInc(stmt->loc); + llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotocase", irs->topfunc(), oldend); diff --git a/gen/toir.cpp b/gen/toir.cpp index 10bf2d8d08a..ccc4fc53c53 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -22,6 +22,7 @@ #include "gen/arrays.h" #include "gen/classes.h" #include "gen/complex.h" +#include "gen/coverage.h" #include "gen/dvalue.h" #include "gen/functions.h" #include "gen/irstate.h" @@ -2125,6 +2126,7 @@ class ToElemVisitor : public Visitor llvm::BranchInst::Create(andand, andandend, ubool, p->scopebb()); p->scope() = IRScope(andand, andandend); + emitCoverageLinecountInc(e->e2->loc); DValue* v = toElemDtor(e->e2); LLValue* vbool = 0; @@ -2172,6 +2174,7 @@ class ToElemVisitor : public Visitor llvm::BranchInst::Create(ororend,oror,ubool,p->scopebb()); p->scope() = IRScope(oror, ororend); + emitCoverageLinecountInc(e->e2->loc); DValue* v = toElemDtor(e->e2); LLValue* vbool = 0; From 76a34f2e3511d42e4d18a136e608e3158e6e579a Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 9 Apr 2015 22:14:12 +0200 Subject: [PATCH 020/101] LLVM 3.7: More metadata changes --- driver/toobj.cpp | 8 ++++++++ gen/dibuilder.cpp | 6 +++--- gen/dibuilder.h | 12 +++++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/driver/toobj.cpp b/driver/toobj.cpp index 842bff2ecb3..d17a672cc20 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -172,7 +172,11 @@ namespace class AssemblyAnnotator : public AssemblyAnnotationWriter { // Find the MDNode which corresponds to the DISubprogram data that described F. +#if LDC_LLVM_VER >= 307 + static MDSubprogram* FindSubprogram(const Function *F, DebugInfoFinder &Finder) +#else static MDNode* FindSubprogram(const Function *F, DebugInfoFinder &Finder) +#endif { #if LDC_LLVM_VER >= 305 for (DISubprogram Subprogram : Finder.subprograms()) { @@ -199,7 +203,11 @@ namespace #else Finder.processModule(const_cast(*F->getParent())); #endif +#if LDC_LLVM_VER >= 307 + if (MDSubprogram* N = FindSubprogram(F, Finder)) +#else if (MDNode* N = FindSubprogram(F, Finder)) +#endif { llvm::DISubprogram sub(N); return sub.getDisplayName(); diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 104a9b2bde0..9e6da6c949e 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -353,7 +353,7 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) llvm::StringRef name = sd->toChars(); unsigned linnum = sd->loc.linnum; llvm::DICompileUnit CU(GetCU()); - assert(CU && CU.Verify() && "Compilation unit missing or corrupted"); + assert(CU && "Compilation unit missing or corrupted"); llvm::DIFile file = CreateFile(sd->loc); llvm::DIType derivedFrom; @@ -657,7 +657,7 @@ llvm::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) LOG_SCOPE; llvm::DICompileUnit CU(GetCU()); - assert(CU && CU.Verify() && "Compilation unit missing or corrupted in DIBuilder::EmitSubProgram"); + assert(CU && "Compilation unit missing or corrupted in DIBuilder::EmitSubProgram"); llvm::DIFile file = CreateFile(fd->loc); @@ -691,7 +691,7 @@ llvm::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function* Fn, LOG_SCOPE; llvm::DICompileUnit CU(GetCU()); - assert(CU && CU.Verify() && "Compilation unit missing or corrupted in DIBuilder::EmitSubProgram"); + assert(CU && "Compilation unit missing or corrupted in DIBuilder::EmitSubProgram"); Loc loc(IR->dmodule, 0, 0); llvm::DIFile file(CreateFile(loc)); diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 1ab1dffa0d9..a64f5098e9b 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -78,13 +78,23 @@ typedef llvm::DIType DIFunctionType; class DIBuilder { IRState *const IR; - const llvm::MDNode *CUNode; llvm::DIBuilder DBuilder; +#if LDC_LLVM_VER >= 307 + const llvm::MDCompileUnit *CUNode; + + const llvm::MDCompileUnit *GetCU() + { + return CUNode; + } +#else + const llvm::MDNode *CUNode; + const llvm::MDNode *GetCU() { return CUNode; } +#endif public: DIBuilder(IRState *const IR, llvm::Module &M); From 4cf89bde2bfa15eba6e68012266c15e7b1ebdc41 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 9 Apr 2015 22:26:24 +0200 Subject: [PATCH 021/101] LLVM 3.7: ConstantExpr::getGetElementPtr() needs type --- gen/coverage.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gen/coverage.cpp b/gen/coverage.cpp index 133da00f60c..e2acc2117d6 100644 --- a/gen/coverage.cpp +++ b/gen/coverage.cpp @@ -27,7 +27,11 @@ void emitCoverageLinecountInc(Loc &loc) { // Get GEP into _d_cover_data array LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(line) }; - LLValue* ptr = llvm::ConstantExpr::getGetElementPtr(gIR->dmodule->d_cover_data, idxs, true); + LLValue* ptr = llvm::ConstantExpr::getGetElementPtr( +#if LDC_LLVM_VER >= 307 + LLType::getInt32Ty(gIR->context()), +#endif + gIR->dmodule->d_cover_data, idxs, true); // Do an atomic increment, so this works when multiple threads are executed. gIR->ir->CreateAtomicRMW( From 92c4361f2e21db799105ec6923b08003aa64ca93 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 9 Apr 2015 22:53:20 +0200 Subject: [PATCH 022/101] LLVM 3.7: Mote GEP-related changes --- gen/module.cpp | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/gen/module.cpp b/gen/module.cpp index 12a8ce0f345..516f3ed206c 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -325,7 +325,11 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) LLValue* curbeg = builder.CreateLoad(mref, "current"); // put current beginning as the next of this one - LLValue* gep = builder.CreateStructGEP(thismref, 0, "next"); + LLValue* gep = builder.CreateStructGEP( +#if LDC_LLVM_VER >= 307 + modulerefTy, +#endif + thismref, 0, "next"); builder.CreateStore(curbeg, gep); // replace beginning @@ -385,13 +389,21 @@ static void build_dso_ctor_dtor_body( minfoEnd->getType(), minfoUsedPointer->getType() }; - llvm::Value* record = b.CreateAlloca( - llvm::StructType::get(gIR->context(), memberTypes, false)); + llvm::StructType* stype = llvm::StructType::get(gIR->context(), memberTypes, false); + llvm::Value* record = b.CreateAlloca(stype); +#if LDC_LLVM_VER >= 307 + b.CreateStore(version, b.CreateStructGEP(stype, record, 0)); // version + b.CreateStore(dsoSlot, b.CreateStructGEP(stype, record, 1)); // slot + b.CreateStore(minfoBeg, b.CreateStructGEP(stype, record, 2)); + b.CreateStore(minfoEnd, b.CreateStructGEP(stype, record, 3)); + b.CreateStore(minfoUsedPointer, b.CreateStructGEP(stype, record, 4)); +#else b.CreateStore(version, b.CreateStructGEP(record, 0)); // version b.CreateStore(dsoSlot, b.CreateStructGEP(record, 1)); // slot b.CreateStore(minfoBeg, b.CreateStructGEP(record, 2)); b.CreateStore(minfoEnd, b.CreateStructGEP(record, 3)); b.CreateStore(minfoUsedPointer, b.CreateStructGEP(record, 4)); +#endif b.CreateCall(dsoRegistry, b.CreateBitCast(record, recordPtrTy)); b.CreateBr(endBB); @@ -580,8 +592,12 @@ static void addCoverageAnalysis(Module* m) llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type); m->d_cover_valid = new llvm::GlobalVariable(*gIR->module, type, true, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_valid"); LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) }; - d_cover_valid_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), - llvm::ConstantExpr::getGetElementPtr(m->d_cover_valid, idxs, true) ); + d_cover_valid_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), + llvm::ConstantExpr::getGetElementPtr( +#if LDC_LLVM_VER >= 307 + DtoSize_t(), +#endif + m->d_cover_valid, idxs, true) ); // Assert that initializer array elements have enough bits assert(sizeof(m->d_cover_valid_init[0])*8 >= gDataLayout->getTypeSizeInBits(DtoSize_t())); @@ -597,8 +613,12 @@ static void addCoverageAnalysis(Module* m) llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type); m->d_cover_data = new llvm::GlobalVariable(*gIR->module, type, false, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_data"); LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) }; - d_cover_data_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), - llvm::ConstantExpr::getGetElementPtr(m->d_cover_data, idxs, true) ); + d_cover_data_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), + llvm::ConstantExpr::getGetElementPtr( +#if LDC_LLVM_VER >= 307 + LLType::getInt32Ty(gIR->context()), +#endif + m->d_cover_data, idxs, true) ); } // Create "static constructor" that calls _d_cover_register2(string filename, size_t[] valid, uint[] data, ubyte minPercent) From 4fa7e98ebe5961c8e4c81c68eb78a9524ac04140 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 12 Apr 2015 14:16:09 +0200 Subject: [PATCH 023/101] LLVM 3.7: DIType.replaceAllUsesWith() is replaced by DIBuilder.replaceTemporary() --- gen/dibuilder.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 9e6da6c949e..f0a9d32a634 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -428,7 +428,11 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) ); } +#if LDC_LLVM_VER >= 307 + ir->diCompositeType = DBuilder.replaceTemporary(llvm::TempMDType(ir->diCompositeType), static_cast(ret.get())); +#else ir->diCompositeType.replaceAllUsesWith(ret); +#endif ir->diCompositeType = ret; return ret; From 8396fc941bb3da0bf2c8ac6cac9ef61733f61eff Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Mon, 13 Apr 2015 23:16:29 +0200 Subject: [PATCH 024/101] Modify `stripModifiers` to optionally work transitively. Strip modifiers transitively when testing whether to repaint return type. --- gen/llvmhelpers.cpp | 8 ++++++-- gen/llvmhelpers.h | 2 +- gen/tocall.cpp | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 3a7399e42ba..c536d64fd49 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1529,11 +1529,15 @@ size_t realignOffset(size_t offset, Type* type) ////////////////////////////////////////////////////////////////////////////////////////// -Type * stripModifiers( Type * type ) +Type * stripModifiers(Type * type, bool transitive) { if (type->ty == Tfunction) return type; - return type->castMod(0); + + if (transitive) + return type->unqualify(MODimmutable | MODconst | MODwild); + else + return type->castMod(0); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index f1b293da5b2..11bee428d32 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -197,7 +197,7 @@ LLFunctionType* DtoExtractFunctionType(LLType* type); /// DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* arguments, LLValue* retvar = 0); -Type* stripModifiers(Type* type); +Type* stripModifiers(Type* type, bool transitive = false); void printLabelName(std::ostream& target, const char* func_mangle, const char* label_name); diff --git a/gen/tocall.cpp b/gen/tocall.cpp index c4828f76bf3..afdc6c43c1f 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -494,8 +494,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* // repaint the type if necessary if (resulttype) { - Type* rbase = stripModifiers(resulttype->toBasetype()); - Type* nextbase = stripModifiers(tf->nextOf()->toBasetype()); + Type* rbase = stripModifiers(resulttype->toBasetype(), true); + Type* nextbase = stripModifiers(tf->nextOf()->toBasetype(), true); if (!rbase->equals(nextbase)) { IF_LOG Logger::println("repainting return value from '%s' to '%s'", tf->nextOf()->toChars(), rbase->toChars()); From efa96d69d86d4b2aa6b3d1f412b7c53399511e5b Mon Sep 17 00:00:00 2001 From: Dmitri Makarov Date: Mon, 13 Apr 2015 22:21:09 +0200 Subject: [PATCH 025/101] Cache global variables for string literals. --- dmd2/module.h | 5 +++++ gen/irstate.h | 15 +++++++++++++++ gen/toconstelem.cpp | 22 +++++++++++++++++++--- gen/toir.cpp | 28 ++++++++++++++++++++++------ gen/tollvm.cpp | 17 ++++++++++++----- 5 files changed, 73 insertions(+), 14 deletions(-) diff --git a/dmd2/module.h b/dmd2/module.h index 35a2718ff32..ac9900e499f 100644 --- a/dmd2/module.h +++ b/dmd2/module.h @@ -151,6 +151,11 @@ class Module : public Package void parse(); // syntactic parse #endif void importAll(Scope *sc); +#if IN_LLVM + using Package::semantic; + using Dsymbol::semantic2; + using Dsymbol::semantic3; +#endif void semantic(); // semantic analysis void semantic2(); // pass 2 semantic analysis void semantic3(); // pass 3 semantic analysis diff --git a/gen/irstate.h b/gen/irstate.h index f75f605c13f..2bba0749f92 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -30,6 +30,7 @@ #if LDC_LLVM_VER >= 305 #include "llvm/IR/CallSite.h" #else +#include #include "llvm/Support/CallSite.h" #endif @@ -198,6 +199,20 @@ struct IRState /// Whether to emit array bounds checking in the current function. bool emitArrayBoundsChecks(); + // Global variables bound to string literals. Once created such a + // variable is reused whenever the same string literal is + // referenced in the module. Caching them per module prevents the + // duplication of identical literals. +#if LDC_LLVM_VER >= 305 + llvm::StringMap stringLiteral1ByteCache; + llvm::StringMap stringLiteral2ByteCache; + llvm::StringMap stringLiteral4ByteCache; +#else + std::map stringLiteral1ByteCache; + std::map stringLiteral2ByteCache; + std::map stringLiteral4ByteCache; +#endif + #if LDC_LLVM_VER >= 303 /// Vector of options passed to the linker as metadata in object file. #if LDC_LLVM_VER >= 306 diff --git a/gen/toconstelem.cpp b/gen/toconstelem.cpp index d9760be7599..fe823e2c57a 100644 --- a/gen/toconstelem.cpp +++ b/gen/toconstelem.cpp @@ -177,6 +177,11 @@ class ToConstElemVisitor : public Visitor LLType* ct = voidToI8(DtoType(cty)); LLArrayType* at = LLArrayType::get(ct,endlen); +#if LDC_LLVM_VER >= 305 + llvm::StringMap* stringLiteralCache = 0; +#else + std::map* stringLiteralCache = 0; +#endif LLConstant* _init; switch (cty->size()) { @@ -184,12 +189,15 @@ class ToConstElemVisitor : public Visitor llvm_unreachable("Unknown char type"); case 1: _init = toConstantArray(ct, at, static_cast(e->string), e->len, nullterm); + stringLiteralCache = &(gIR->stringLiteral1ByteCache); break; case 2: _init = toConstantArray(ct, at, static_cast(e->string), e->len, nullterm); + stringLiteralCache = &(gIR->stringLiteral2ByteCache); break; case 4: _init = toConstantArray(ct, at, static_cast(e->string), e->len, nullterm); + stringLiteralCache = &(gIR->stringLiteral4ByteCache); break; } @@ -199,9 +207,17 @@ class ToConstElemVisitor : public Visitor return; } - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage; - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(*gIR->module, _init->getType(), true, _linkage, _init, ".str"); - gvar->setUnnamedAddr(true); + llvm::StringRef key(e->toChars()); + llvm::GlobalVariable* gvar = (stringLiteralCache->find(key) == + stringLiteralCache->end()) + ? 0 : (*stringLiteralCache)[key]; + if (gvar == 0) + { + llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::PrivateLinkage; + gvar = new llvm::GlobalVariable(*gIR->module, _init->getType(), true, _linkage, _init, ".str"); + gvar->setUnnamedAddr(true); + (*stringLiteralCache)[key] = gvar; + } llvm::ConstantInt* zero = LLConstantInt::get(LLType::getInt32Ty(gIR->context()), 0, false); LLConstant* idxs[2] = { zero, zero }; diff --git a/gen/toir.cpp b/gen/toir.cpp index ccc4fc53c53..a90b54c8ae8 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -340,6 +340,11 @@ class ToElemVisitor : public Visitor LLType* ct = voidToI8(DtoType(cty)); LLArrayType* at = LLArrayType::get(ct, e->len+1); +#if LDC_LLVM_VER >= 305 + llvm::StringMap* stringLiteralCache = 0; +#else + std::map* stringLiteralCache = 0; +#endif LLConstant* _init; switch (cty->size()) { @@ -347,22 +352,33 @@ class ToElemVisitor : public Visitor llvm_unreachable("Unknown char type"); case 1: _init = toConstantArray(ct, at, static_cast(e->string), e->len); + stringLiteralCache = &(gIR->stringLiteral1ByteCache); break; case 2: _init = toConstantArray(ct, at, static_cast(e->string), e->len); + stringLiteralCache = &(gIR->stringLiteral2ByteCache); break; case 4: _init = toConstantArray(ct, at, static_cast(e->string), e->len); + stringLiteralCache = &(gIR->stringLiteral4ByteCache); break; } - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage; - IF_LOG { - Logger::cout() << "type: " << *at << '\n'; - Logger::cout() << "init: " << *_init << '\n'; + llvm::StringRef key(e->toChars()); + llvm::GlobalVariable* gvar = (stringLiteralCache->find(key) == + stringLiteralCache->end()) + ? 0 : (*stringLiteralCache)[key]; + if (gvar == 0) + { + llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::PrivateLinkage; + IF_LOG { + Logger::cout() << "type: " << *at << '\n'; + Logger::cout() << "init: " << *_init << '\n'; + } + gvar = new llvm::GlobalVariable(*gIR->module, at, true, _linkage, _init, ".str"); + gvar->setUnnamedAddr(true); + (*stringLiteralCache)[key] = gvar; } - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(*gIR->module, at, true, _linkage, _init, ".str"); - gvar->setUnnamedAddr(true); llvm::ConstantInt* zero = LLConstantInt::get(LLType::getInt32Ty(gIR->context()), 0, false); LLConstant* idxs[2] = { zero, zero }; diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index bc9223c6e28..f20739ec2dc 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -497,16 +497,23 @@ LLConstant* DtoConstFP(Type* t, longdouble value) LLConstant* DtoConstString(const char* str) { llvm::StringRef s(str ? str : ""); - llvm::Constant* init = llvm::ConstantDataArray::getString(gIR->context(), s, true); - llvm::GlobalVariable* gvar = new llvm::GlobalVariable( - *gIR->module, init->getType(), true, llvm::GlobalValue::InternalLinkage, init, ".str"); - gvar->setUnnamedAddr(true); + llvm::GlobalVariable* gvar = (gIR->stringLiteral1ByteCache.find(s) == + gIR->stringLiteral1ByteCache.end()) + ? 0 : gIR->stringLiteral1ByteCache[s]; + if (gvar == 0) + { + llvm::Constant* init = llvm::ConstantDataArray::getString(gIR->context(), s, true); + gvar = new llvm::GlobalVariable(*gIR->module, init->getType(), true, + llvm::GlobalValue::PrivateLinkage, init, ".str"); + gvar->setUnnamedAddr(true); + gIR->stringLiteral1ByteCache[s] = gvar; + } LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) }; return DtoConstSlice( DtoConstSize_t(s.size()), llvm::ConstantExpr::getGetElementPtr( #if LDC_LLVM_VER >= 307 - init->getType(), + gvar->getInitializer()->getType(), #endif gvar, idxs, true), Type::tchar->arrayOf() From 3931fd7d2438fc295317787041b859c7fc55a7f8 Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Wed, 15 Apr 2015 21:41:10 +0200 Subject: [PATCH 026/101] Win64 ABI: do not (yet) return dynamic arrays via sret. The druntime calling code in gen/arrays.cpp to e.g. `_d_newarrayU` is not yet able to handle sret. --- gen/abi-win64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/abi-win64.cpp b/gen/abi-win64.cpp index 25d4972c694..a150aeb5dbe 100644 --- a/gen/abi-win64.cpp +++ b/gen/abi-win64.cpp @@ -55,7 +55,7 @@ struct Win64TargetABI : TargetABI bool isAggregate(Type* t) { TY ty = t->ty; - return ty == Tstruct || ty == Tsarray || ty == Tarray || ty == Tdelegate + return ty == Tstruct || ty == Tsarray || /*ty == Tarray ||*/ ty == Tdelegate || t->iscomplex(); } From 9ae1c682638eed46b88408acd36bee950e0fdfb3 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 16 Apr 2015 00:46:07 +0200 Subject: [PATCH 027/101] Inline assembly fix for MSVC: treat real ptr as 64-bit double. --- gen/asm-x86.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/gen/asm-x86.h b/gen/asm-x86.h index 5f936a3c6d6..532b9c7523d 100644 --- a/gen/asm-x86.h +++ b/gen/asm-x86.h @@ -2413,7 +2413,15 @@ namespace AsmParserx8664 { case Float_Ptr: type_suffix = 's'; break; case Double_Ptr: type_suffix = 'l'; break; - case Extended_Ptr: type_suffix = 't'; break; + case Extended_Ptr: +#if LDC_LLVM_VER >= 305 + // MS C runtime: real = 64-bit double + if (global.params.targetTriple.isWindowsMSVCEnvironment()) + type_suffix = 'l'; + else +#endif + type_suffix = 't'; + break; default: return false; } From 7a3ef8323be4a8d8a53cf0c821c2631804ad9c04 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Wed, 15 Apr 2015 22:58:12 +0200 Subject: [PATCH 028/101] LLVM 3.7: More metadata and output stream changes. --- driver/toobj.cpp | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/driver/toobj.cpp b/driver/toobj.cpp index d17a672cc20..d991204947d 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -110,8 +110,16 @@ static void codegenModule(llvm::TargetMachine &Target, llvm::Module& m, Target.addAnalysisPasses(Passes); #endif +#if LDC_LLVM_VER < 307 llvm::formatted_raw_ostream fout(out); - if (Target.addPassesToEmitFile(Passes, fout, fileType, codeGenOptLevel())) +#endif + if (Target.addPassesToEmitFile(Passes, +#if LDC_LLVM_VER >= 307 + out, +#else + fout, +#endif + fileType, codeGenOptLevel())) llvm_unreachable("no support for asm output"); Passes.run(m); @@ -178,19 +186,21 @@ namespace static MDNode* FindSubprogram(const Function *F, DebugInfoFinder &Finder) #endif { -#if LDC_LLVM_VER >= 305 - for (DISubprogram Subprogram : Finder.subprograms()) { +#if LDC_LLVM_VER >= 307 + for (DISubprogram Subprogram : Finder.subprograms()) + if (Subprogram->describes(F)) return Subprogram; + return nullptr; +#elif LDC_LLVM_VER >= 305 + for (DISubprogram Subprogram : Finder.subprograms()) + if (Subprogram.describes(F)) return Subprogram; + return nullptr; #else for (DebugInfoFinder::iterator I = Finder.subprogram_begin(), E = Finder.subprogram_end(); I != E; ++I) { DISubprogram Subprogram(*I); -#endif if (Subprogram.describes(F)) return Subprogram; } -#if LDC_LLVM_VER >= 305 - return nullptr; -#else return 0; #endif } @@ -209,8 +219,12 @@ namespace if (MDNode* N = FindSubprogram(F, Finder)) #endif { +#if LDC_LLVM_VER >= 307 + return N->getDisplayName(); +#else llvm::DISubprogram sub(N); return sub.getDisplayName(); +#endif } return ""; } @@ -267,7 +281,11 @@ namespace os.PadToColumn(50); os << ";"; } +#if LDC_LLVM_VER >= 307 + os << " [debug variable = " << Var->getName() << ']'; +#else os << " [debug variable = " << Var.getName() << ']'; +#endif } else if (const DbgValueInst* DVI = dyn_cast(instr)) { @@ -277,7 +295,11 @@ namespace os.PadToColumn(50); os << ";"; } +#if LDC_LLVM_VER >= 307 + os << " [debug variable = " << Var->getName() << ']'; +#else os << " [debug variable = " << Var.getName() << ']'; +#endif } else if (const CallInst* callinstr = dyn_cast(instr)) { From 31c31955114f79ab78f067031ea2a30b67f07672 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 17 Apr 2015 23:02:27 +0200 Subject: [PATCH 029/101] LLVM 3.7: More metadata changes. The accessible flags moved into a new class. Same is true for subroutine type. --- gen/dibuilder.cpp | 18 +++++++++++++----- gen/dibuilder.h | 4 +++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index f0a9d32a634..9ad45cccd94 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -23,6 +23,14 @@ //////////////////////////////////////////////////////////////////////////////// +#if LDC_LLVM_VER >= 307 +typedef llvm::DebugNode Access; +#else +typedef llvm::DIDescriptor Access; +#endif + +//////////////////////////////////////////////////////////////////////////////// + // get the module the symbol is in, or - for template instances - the current module Module *ldc::DIBuilder::getDefinedModule(Dsymbol *s) { @@ -255,14 +263,14 @@ llvm::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type, unsigned Flags = 0; switch (prot) { case PROTprivate: - Flags = llvm::DIDescriptor::FlagPrivate; + Flags = Access::FlagPrivate; break; case PROTprotected: - Flags = llvm::DIDescriptor::FlagProtected; + Flags = Access::FlagProtected; break; #if LDC_LLVM_VER >= 306 case PROTpublic: - Flags = llvm::DIDescriptor::FlagPublic; + Flags = Access::FlagPublic; break; #endif default: @@ -408,7 +416,7 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) getTypeBitSize(T), // size in bits getABITypeAlign(T)*8, // alignment in bits 0, // offset in bits, - llvm::DIDescriptor::FlagFwdDecl, // flags + Access::FlagFwdDecl, // flags derivedFrom, // DerivedFrom elemsArray ); @@ -420,7 +428,7 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) linnum, // line number where defined getTypeBitSize(T), // size in bits getABITypeAlign(T)*8, // alignment in bits - llvm::DIDescriptor::FlagFwdDecl, // flags + Access::FlagFwdDecl, // flags #if LDC_LLVM_VER >= 303 derivedFrom, // DerivedFrom #endif diff --git a/gen/dibuilder.h b/gen/dibuilder.h index a64f5098e9b..ece7b0951cc 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -69,7 +69,9 @@ extern const llvm::TargetData* gDataLayout; namespace ldc { -#if LDC_LLVM_VER >= 304 +#if LDC_LLVM_VER >= 307 +typedef llvm::MDSubroutineType* DIFunctionType; +#elif LDC_LLVM_VER >= 304 typedef llvm::DICompositeType DIFunctionType; #else typedef llvm::DIType DIFunctionType; From 7591a31df9cc796973a825d22db539fb840b0ede Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 17 Apr 2015 23:37:09 +0200 Subject: [PATCH 030/101] LLVM 3.7: Again more metadata changes. --- gen/dibuilder.cpp | 12 +++++++++++- gen/dibuilder.h | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 9ad45cccd94..3f88aa14aa5 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -61,7 +61,11 @@ llvm::LLVMContext &ldc::DIBuilder::getContext() return IR->context(); } +#if LDC_LLVM_VER >= 307 +llvm::MDScope* ldc::DIBuilder::GetCurrentScope() +#else llvm::DIDescriptor ldc::DIBuilder::GetCurrentScope() +#endif { IrFunction *fn = IR->func(); if (fn->diLexicalBlocks.empty()) @@ -81,6 +85,9 @@ void ldc::DIBuilder::Declare(llvm::Value *var, llvm::DIVariable divar llvm::Instruction *instr = DBuilder.insertDeclare(var, divar, #if LDC_LLVM_VER >= 306 diexpr, +#endif +#if LDC_LLVM_VER >= 307 + IR->ir->getCurrentDebugLocation(), #endif IR->scopebb()); instr->setDebugLoc(IR->ir->getCurrentDebugLocation()); @@ -437,7 +444,7 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) } #if LDC_LLVM_VER >= 307 - ir->diCompositeType = DBuilder.replaceTemporary(llvm::TempMDType(ir->diCompositeType), static_cast(ret.get())); + ir->diCompositeType = DBuilder.replaceTemporary(llvm::TempMDType(ir->diCompositeType), static_cast(ret)); #else ir->diCompositeType.replaceAllUsesWith(ret); #endif @@ -815,6 +822,9 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) llvm::Instruction *instr = DBuilder.insertDbgValueIntrinsic(val, 0, debugVariable, #if LDC_LLVM_VER >= 306 DBuilder.createExpression(), +#endif +#if LDC_LLVM_VER >= 307 + IR->ir->getCurrentDebugLocation(), #endif IR->scopebb()); instr->setDebugLoc(IR->ir->getCurrentDebugLocation()); diff --git a/gen/dibuilder.h b/gen/dibuilder.h index ece7b0951cc..22254cb3554 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -156,7 +156,11 @@ class DIBuilder private: llvm::LLVMContext &getContext(); Module *getDefinedModule(Dsymbol *s); +#if LDC_LLVM_VER >= 307 + llvm::MDScope* GetCurrentScope(); +#else llvm::DIDescriptor GetCurrentScope(); +#endif void Declare(llvm::Value *var, llvm::DIVariable divar #if LDC_LLVM_VER >= 306 , llvm::DIExpression diexpr From 73b53ff9a3b92ceb51a4779162b575f316969131 Mon Sep 17 00:00:00 2001 From: Dmitri Makarov Date: Fri, 17 Apr 2015 16:31:22 +0200 Subject: [PATCH 031/101] Add coverage testing. --- .travis.yml | 11 +++++++++++ CMakeLists.txt | 13 +++++++++++++ README.md | 9 ++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5090837dbc3..0c409a51def 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,6 +39,10 @@ install: if [[ "${LLVM_PACKAGE}" == *3\.[567]* ]] && [[ "${CXX}" == "clang++" ]]; then sudo apt-get install --allow-unauthenticated -qq clang-3.4; export CXX="clang++-3.4"; fi + - + if [[ "${OPTS}" == *TEST_COVERAGE*ON* ]]; then + sudo pip install cpp-coveralls; + fi env: - LLVM_PACKAGE="llvm-3.1 llvm-3.1-dev" - LLVM_PACKAGE="llvm-3.2 llvm-3.2-dev" @@ -49,6 +53,7 @@ env: - LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" OPTS="-DBUILD_SHARED_LIBS=ON" - LLVM_PACKAGE="llvm-3.5 llvm-3.5-dev libedit2 libedit-dev" TEST_DEBUG=1 - LLVM_PACKAGE="llvm-3.5 llvm-3.5-dev libedit2 libedit-dev" + - LLVM_PACKAGE="llvm-3.5 llvm-3.5-dev libedit2 libedit-dev" OPTS="-DTEST_COVERAGE=ON" - LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" TEST_DEBUG=1 - LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" - LLVM_PACKAGE="llvm-3.7 llvm-3.7-dev libedit2 libedit-dev" TEST_DEBUG=1 @@ -101,6 +106,12 @@ script: - ctest -j2 --verbose ${BUILD_SEL} - ctest -j2 --output-on-failure ${RUN_SEL} +after_success: + - + if [[ "${OPTS}" == *TEST_COVERAGE*ON* ]]; then + coveralls -e runtime -e tests -e vcbuild --gcov gcov-4.9 --gcov-options '\-lp' > /dev/null 2>&1; + fi + notifications: # Temporarily disabled due to time limit problems. # email: diff --git a/CMakeLists.txt b/CMakeLists.txt index 3904da9a378..f7444f5bc2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -381,6 +381,19 @@ if( NOT WIN32 OR CYGWIN ) endforeach() endif() +# +# Enable instrumentation for code coverage analysis +# +set(TEST_COVERAGE OFF CACHE BOOL "instrument compiler for code coverage analysis") +if(TEST_COVERAGE) + if(CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")) + append("-O0 -g -fprofile-arcs -ftest-coverage" EXTRA_CXXFLAGS) + append("--coverage" LLVM_LDFLAGS) + else() + message(WARNING "Coverage testing is not available.") + endif() +endif() + # # Set up the main ldc/ldc2 target. # diff --git a/README.md b/README.md index 16bd0c0c280..3cd6d468c4d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ LDC – the LLVM-based D Compiler =============================== -[![Build Status](https://travis-ci.org/ldc-developers/ldc.png?branch=master)](https://travis-ci.org/ldc-developers/ldc) [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=283332)](https://www.bountysource.com/trackers/283332-ldc?utm_source=283332&utm_medium=shield&utm_campaign=TRACKER_BADGE) +[![Build Status](https://travis-ci.org/ldc-developers/ldc.png?branch=master)][1] +[![Test Coverage](https://coveralls.io/repos/ldc-developers/ldc/badge.svg)][2] +[![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=283332)][3] The LDC project aims to provide a portable D programming language compiler with modern optimization and code generation capabilities. @@ -52,3 +54,8 @@ For further documentation, contributor information, etc. please see the D wiki: http://wiki.dlang.org/LDC Feedback of any kind is very much appreciated! + + +[1]: https://travis-ci.org/ldc-developers/ldc "Build Status" +[2]: https://coveralls.io/r/ldc-developers/ldc "Test Coverage" +[3]: https://www.bountysource.com/trackers/283332-ldc?utm_source=283332&utm_medium=shield&utm_campaign=TRACKER_BADGE "Bountysource" From 99372e6f838efa30ace8176df303f0f4d4bf2a7a Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Sun, 19 Apr 2015 11:45:54 +0200 Subject: [PATCH 032/101] Fix druntime debug builds of druntime (change of compiler flags) --- runtime/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index e99a4ddc5d6..815c9f217c9 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -322,7 +322,12 @@ macro(compile_druntime d_flags lib_suffix path_suffix outlist_o outlist_bc) # Always disable invariants for debug builds of core.* and gc.* (there # are/were some broken invariants around; druntime is always built in # release mode in upstream builds). - set(rt_flags "${d_flags};-disable-invariants") + if(${LDC_LLVM_VER} LESS 307) + set(rt_flags "${d_flags};-disable-invariants") + else () + set(rt_flags "${d_flags};-invariants=false") + endif() + if(BUILD_SHARED_LIBS) set(shared ";-d-version=Shared") else() From fdd449c4e5b3a6470517e284909dc2632de0575d Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 21 Apr 2015 22:50:47 +0200 Subject: [PATCH 033/101] LLVM 3.7: Metadata refactoring continues --- driver/toobj.cpp | 2 +- gen/dibuilder.cpp | 16 +++++++++++++--- gen/dibuilder.h | 30 ++++++++++++++++++++++++++++-- ir/irfunction.h | 5 +++++ ir/irtypeaggr.h | 4 ++++ ir/irvar.h | 5 +++++ 6 files changed, 56 insertions(+), 6 deletions(-) diff --git a/driver/toobj.cpp b/driver/toobj.cpp index d991204947d..420f6eb6bd1 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -187,7 +187,7 @@ namespace #endif { #if LDC_LLVM_VER >= 307 - for (DISubprogram Subprogram : Finder.subprograms()) + for (MDSubprogram* Subprogram : Finder.subprograms()) if (Subprogram->describes(F)) return Subprogram; return nullptr; #elif LDC_LLVM_VER >= 305 diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 3f88aa14aa5..39797cc56bb 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -411,7 +411,11 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) } } +#if LDC_LLVM_VER >= 307 + llvm::DebugNodeArray elemsArray = DBuilder.getOrCreateArray(elems); +#else llvm::DIArray elemsArray = DBuilder.getOrCreateArray(elems); +#endif llvm::DIType ret; if (t->ty == Tclass) { @@ -550,7 +554,9 @@ ldc::DIFunctionType ldc::DIBuilder::CreateFunctionType(Type *type) llvm::SmallVector Elts; #endif Elts.push_back(CreateTypeDescription(retType, true)); -#if LDC_LLVM_VER >= 306 +#if LDC_LLVM_VER >= 307 + llvm::MDTypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); +#elif LDC_LLVM_VER >= 306 llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); #else llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); @@ -579,7 +585,9 @@ ldc::DIFunctionType ldc::DIBuilder::CreateDelegateType(Type *type) llvm::DIType(NULL) #endif ); -#if LDC_LLVM_VER >= 306 +#if LDC_LLVM_VER >= 307 + llvm::MDTypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); +#elif LDC_LLVM_VER >= 306 llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); #else llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); @@ -722,7 +730,9 @@ llvm::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function* Fn, llvm::SmallVector Elts; #endif Elts.push_back(CreateTypeDescription(Type::tvoid, true)); -#if LDC_LLVM_VER >= 306 +#if LDC_LLVM_VER >= 307 + llvm::MDTypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); +#elif LDC_LLVM_VER >= 306 llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); #else llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 22254cb3554..48c62974389 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -67,6 +67,32 @@ extern const llvm::DataLayout* gDataLayout; extern const llvm::TargetData* gDataLayout; #endif +// LLVM 3.7: no more DIFoo wrappers for MDFoo* pointers +// Let's define primitive wrappers for backward compatibility, +// primarily for proper initialization with null. +#if LDC_LLVM_VER >= 307 +namespace llvm { + template + class DIWrapper + { + T* ptr; + public: + DIWrapper(T* ptr = nullptr) : ptr(ptr) {} + operator T*() { return ptr; } + T* operator ->() { return ptr; } + }; + + using DICompileUnit = DIWrapper; + using DIExpression = DIWrapper; + using DIFile = DIWrapper; + using DIGlobalVariable = DIWrapper; + using DILexicalBlock = DIWrapper; + using DISubprogram = DIWrapper; + using DIType = DIWrapper; + using DIVariable = DIWrapper; +} +#endif + namespace ldc { #if LDC_LLVM_VER >= 307 @@ -83,9 +109,9 @@ class DIBuilder llvm::DIBuilder DBuilder; #if LDC_LLVM_VER >= 307 - const llvm::MDCompileUnit *CUNode; + llvm::MDCompileUnit *CUNode; - const llvm::MDCompileUnit *GetCU() + llvm::MDCompileUnit *GetCU() { return CUNode; } diff --git a/ir/irfunction.h b/ir/irfunction.h index bbc68ac4d8d..d45737d9b6b 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -122,8 +122,13 @@ struct IrFunction llvm::Value* _arguments; llvm::Value* _argptr; +#if LDC_LLVM_VER >= 307 + llvm::MDSubprogram* diSubprogram = nullptr; + std::stack diLexicalBlocks; +#else llvm::DISubprogram diSubprogram; std::stack diLexicalBlocks; +#endif IrFuncTy irFty; }; diff --git a/ir/irtypeaggr.h b/ir/irtypeaggr.h index 9a7a18bed8d..4b042473af0 100644 --- a/ir/irtypeaggr.h +++ b/ir/irtypeaggr.h @@ -66,7 +66,11 @@ class IrTypeAggr : public IrType /// Composite type debug description. This is not only to cache, but also /// used for resolving forward references. +#if LDC_LLVM_VER >= 307 + llvm::MDType* diCompositeType = nullptr; +#else llvm::DIType diCompositeType; +#endif /// true, if the LLVM struct type for the aggregate is declared as packed bool packed; diff --git a/ir/irvar.h b/ir/irvar.h index 9e6583c3b59..2e2e1f5691f 100644 --- a/ir/irvar.h +++ b/ir/irvar.h @@ -43,8 +43,13 @@ struct IrVar llvm::Value* value; // debug description +#if LDC_LLVM_VER >= 307 + llvm::MDLocalVariable* debugVariable = nullptr; + llvm::MDSubprogram* debugFunc = nullptr; +#else llvm::DIVariable debugVariable; llvm::DISubprogram debugFunc; +#endif }; // represents a global variable From 867b34103032520d55454fb80cd7084d9376228e Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Sat, 25 Apr 2015 17:18:44 +0200 Subject: [PATCH 034/101] Fix a bug where the mutable version of a Type is not properly resolved if it contains alias identifiers. This results in a bug later during compilation where stripModifiers() will return a not-fully-resolved type. --- dmd2/declaration.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dmd2/declaration.c b/dmd2/declaration.c index b063d6ce4d5..fef48c17b30 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -557,7 +557,7 @@ void AliasDeclaration::semantic(Scope *sc) if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember())) goto L2; // it's a symbolic alias - type = type->addStorageClass(storage_class); + type = type->addSTC(storage_class); if (storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCdisable)) { // For 'ref' to be attached to function types, and picked @@ -569,6 +569,7 @@ void AliasDeclaration::semantic(Scope *sc) } else type->resolve(loc, sc, &e, &t, &s); + if (s) { goto L2; From 4db0123bb75b45f85786fbfccf1f2af24454c1ea Mon Sep 17 00:00:00 2001 From: kai Date: Wed, 22 Apr 2015 07:51:18 +0200 Subject: [PATCH 035/101] Implement FlagParser using llvm::cl::generic_parser_base. This approach is easier and requires less code. With some template foo the BoolOrDefaultAdapter is not required. This solutions applies to previous LLVM versions, too. --- driver/cl_options.cpp | 18 ++--- gen/cl_helpers.cpp | 33 --------- gen/cl_helpers.h | 164 +++++++++++++++++++++++++++++------------ gen/optimizer.cpp | 2 +- runtime/CMakeLists.txt | 6 +- 5 files changed, 127 insertions(+), 96 deletions(-) diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index ab7a023e3f6..6cd995086d6 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -347,7 +347,7 @@ cl::opt disableFpElim("disable-fp-elim", cl::desc("Disable frame pointer elimination optimization"), cl::init(false)); -static cl::opt asserts("asserts", +static cl::opt > asserts("asserts", cl::desc("(*) Enable assertions"), cl::value_desc("bool"), cl::location(global.params.useAssert), @@ -362,13 +362,11 @@ class BoundsChecksAdapter { } }; -#if LDC_LLVM_VER < 307 -cl::opt boundsChecksOld("boundscheck", +cl::opt > boundsChecksOld("boundscheck", cl::desc("(*) Enable array bounds check (deprecated, use -boundscheck=on|off)")); -#endif cl::opt boundsChecksNew("boundscheck", - cl::desc("(*) Enable array bounds check"), + cl::desc("Enable array bounds check"), cl::location(boundsCheck), cl::values( clEnumValN(BC_Off, "off", "no array bounds checks"), @@ -376,17 +374,17 @@ cl::opt boundsChecksNew("boundscheck", clEnumValN(BC_On, "on", "array bounds checks for all functions"), clEnumValEnd)); -static cl::opt invariants("invariants", +static cl::opt > invariants("invariants", cl::desc("(*) Enable invariants"), cl::location(global.params.useInvariants), cl::init(true)); -static cl::opt preconditions("preconditions", +static cl::opt > preconditions("preconditions", cl::desc("(*) Enable function preconditions"), cl::location(global.params.useIn), cl::init(true)); -static cl::opt postconditions("postconditions", +static cl::opt > postconditions("postconditions", cl::desc("(*) Enable function postconditions"), cl::location(global.params.useOut), cl::init(true)); @@ -394,7 +392,7 @@ static cl::opt postconditions("postconditions", static MultiSetter ContractsSetter(false, &global.params.useIn, &global.params.useOut, NULL); -static cl::opt contracts("contracts", +static cl::opt > contracts("contracts", cl::desc("(*) Enable function pre- and post-conditions"), cl::location(ContractsSetter)); @@ -436,7 +434,7 @@ cl::opt vgc("vgc", cl::desc("list all gc allocations including hidden ones"), cl::location(global.params.vgc)); -cl::opt color("color", +cl::opt > color("color", cl::desc("Force colored console output"), cl::location(global.params.color)); diff --git a/gen/cl_helpers.cpp b/gen/cl_helpers.cpp index 0c1a3630396..af1414effad 100644 --- a/gen/cl_helpers.cpp +++ b/gen/cl_helpers.cpp @@ -18,39 +18,6 @@ namespace opts { -#if LDC_LLVM_VER < 307 -bool FlagParser::parse(cl::Option &O, llvm::StringRef ArgName, llvm::StringRef Arg, bool &Val) { - // Make a std::string out of it to make comparisons easier - // (and avoid repeated conversion) - llvm::StringRef argname = ArgName; - - typedef std::vector >::iterator It; - for (It I = switches.begin(), E = switches.end(); I != E; ++I) { - llvm::StringRef name = I->first; - if (name == argname - || (name.size() < argname.size() - && argname.substr(0, name.size()) == name - && argname[name.size()] == '=')) { - - if (!cl::parser::parse(O, ArgName, Arg, Val)) { - Val = (Val == I->second); - return false; - } - // Invalid option value - break; - } - } - return true; -} - -void FlagParser::getExtraOptionNames(llvm::SmallVectorImpl &Names) { - typedef std::vector >::iterator It; - for (It I = switches.begin() + 1, E = switches.end(); I != E; ++I) { - Names.push_back(I->first.data()); - } -} -#endif - MultiSetter::MultiSetter(bool invert, bool* p, ...) { this->invert = invert; if (p) { diff --git a/gen/cl_helpers.h b/gen/cl_helpers.h index c1ed6d651f4..44de302feab 100644 --- a/gen/cl_helpers.h +++ b/gen/cl_helpers.h @@ -17,6 +17,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" +#include "gen/llvmcompat.h" #if LDC_LLVM_VER < 306 #define LLVM_END_WITH_NULL END_WITH_NULL @@ -28,46 +29,132 @@ typedef Array Strings; namespace opts { namespace cl = llvm::cl; + /// Helper class to determine values + template + struct FlagParserDataType {}; + + template<> + struct FlagParserDataType{ + static bool true_val() { return true; } + static bool false_val() { return false; } + }; + + template<> + struct FlagParserDataType { + static cl::boolOrDefault true_val() { return cl::BOU_TRUE; } + static cl::boolOrDefault false_val() { return cl::BOU_FALSE; } + }; + + template + class FlagParser : public cl::generic_parser_base { + protected: + llvm::SmallVector, 2> switches; #if LDC_LLVM_VER >= 307 -typedef cl::parser FlagParser; + cl::Option& owner() const { return Owner; } #else - /// Helper class for fancier options - class FlagParser : public cl::parser { -#if LDC_LLVM_VER >= 307 - cl::Option &Opt; + cl::Option* Owner; + cl::Option& owner() const { return *Owner; } #endif - std::vector > switches; + public: #if LDC_LLVM_VER >= 307 - FlagParser(cl::Option &O) : parser(O), Opt(O) { } - - void initialize() { - std::string Name(Opt.ArgStr); - switches.push_back(make_pair("enable-" + Name, true)); - switches.push_back(make_pair("disable-" + Name, false)); - // Replace with -enable- and register -disable- - // A literal option can only registered if the argstr is empty - - // just do this first. - Opt.setArgStr(""); - AddLiteralOption(Opt, strdup(switches[1].first.data())); - Opt.setArgStr(switches[0].first.data()); - } + FlagParser(cl::Option& O) : generic_parser_base(O) {} #else - template - void initialize(Opt &O) { - std::string Name = O.ArgStr; - switches.push_back(make_pair("enable-" + Name, true)); - switches.push_back(make_pair("disable-" + Name, false)); - // Replace with -enable- - O.ArgStr = switches[0].first.data(); - } + FlagParser() : generic_parser_base(), Owner(0) {} #endif + typedef DataType parser_data_type; + +#if LDC_LLVM_VER >= 307 + void initialize() { +#else + void initialize(cl::Option& O) { + Owner = &O; +#endif + std::string Name(owner().ArgStr); + switches.push_back(make_pair("enable-" + Name, FlagParserDataType::true_val())); + switches.push_back(make_pair("disable-" + Name, FlagParserDataType::false_val())); + // Replace with -enable- and register -disable- +#if LDC_LLVM_VER >= 307 + // A literal option can only registered if the argstr is empty - + // just do this first. + owner().setArgStr(""); + AddLiteralOption(Owner, strdup(switches[1].first.data())); +#endif + owner().setArgStr(switches[0].first.data()); + } + + enum cl::ValueExpected getValueExpectedFlagDefault() const { + return cl::ValueOptional; + } + + // Implement virtual functions needed by generic_parser_base + unsigned getNumOptions() const LLVM_OVERRIDE { return 1; } + const char* getOption(unsigned N) const LLVM_OVERRIDE { + assert(N == 0); + return owner().ArgStr; + } - bool parse(cl::Option &O, llvm::StringRef ArgName, llvm::StringRef ArgValue, bool &Val); + const char* getDescription(unsigned N) const LLVM_OVERRIDE { + assert(N == 0); + return owner().HelpStr; + } + + private: + struct OptionValue : cl::OptionValueBase < DataType, false > { + OptionValue() { }; + }; + const OptionValue EmptyOptionValue; + + public: + // getOptionValue - Return the value of option name N. + const cl::GenericOptionValue &getOptionValue(unsigned N) const LLVM_OVERRIDE { + return EmptyOptionValue; + } - void getExtraOptionNames(llvm::SmallVectorImpl &Names); + // parse - Return true on error. + bool parse(cl::Option& O, llvm::StringRef ArgName, llvm::StringRef Arg, DataType& Val) { + typedef typename llvm::SmallVector, 2>::iterator It; + for (It I = switches.begin(), E = switches.end(); I != E; ++I) { + llvm::StringRef name = I->first; + if (name == ArgName + || (name.size() < ArgName.size() + && ArgName.substr(0, name.size()) == name + && ArgName[name.size()] == '=')) { + if (!parse(owner(), Arg, Val)) + { + Val = (Val == I->second) ? FlagParserDataType::true_val() : FlagParserDataType::false_val(); + return false; + } + // Invalid option value + break; + } + } + return true; + } + + void getExtraOptionNames(llvm::SmallVectorImpl& Names) { + typedef typename llvm::SmallVector, 2>::iterator It; + for (It I = switches.begin() + 1, E = switches.end(); I != E; ++I) { + Names.push_back(I->first.data()); + } + } + + private: + static bool parse(cl::Option &O, llvm::StringRef Arg, DataType &Val) { + if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || + Arg == "1") { + Val = FlagParserDataType::true_val(); + return false; + } + + if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { + Val = FlagParserDataType::false_val(); + return false; + } + return O.error("'" + Arg + + "' is invalid value for boolean argument! Try 0 or 1"); + } }; -#endif /// Helper class for options that set multiple flags class MultiSetter { @@ -99,23 +186,6 @@ typedef cl::parser FlagParser; push_back(str.c_str()); } }; - - /// Helper class to allow use of a parser with BoolOrDefault - class BoolOrDefaultAdapter { - cl::boolOrDefault value; - public: - operator cl::boolOrDefault() { - return value; - } - - void operator=(cl::boolOrDefault val) { - value = val; - } - - void operator=(bool val) { - *this = (val ? cl::BOU_TRUE : cl::BOU_FALSE); - } - }; } #endif diff --git a/gen/optimizer.cpp b/gen/optimizer.cpp index 2da04a5e155..1069042a4d8 100644 --- a/gen/optimizer.cpp +++ b/gen/optimizer.cpp @@ -111,7 +111,7 @@ disableGCToStack("disable-gc2stack", cl::desc("Disable promotion of GC allocations to stack memory"), cl::ZeroOrMore); -static cl::opt +static cl::opt > enableInlining("inlining", cl::desc("Enable function inlining (default in -O2 and higher)"), cl::ZeroOrMore); diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 815c9f217c9..92386f605b3 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -322,11 +322,7 @@ macro(compile_druntime d_flags lib_suffix path_suffix outlist_o outlist_bc) # Always disable invariants for debug builds of core.* and gc.* (there # are/were some broken invariants around; druntime is always built in # release mode in upstream builds). - if(${LDC_LLVM_VER} LESS 307) - set(rt_flags "${d_flags};-disable-invariants") - else () - set(rt_flags "${d_flags};-invariants=false") - endif() + set(rt_flags "${d_flags};-disable-invariants") if(BUILD_SHARED_LIBS) set(shared ";-d-version=Shared") From 6e5d33a2698d6685b35eabeef9d23f827ae7c6c5 Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Sun, 26 Apr 2015 15:44:36 +0200 Subject: [PATCH 036/101] MSVC: Fix LLVM::APFloat assert crash upon float NaN/infinity roundtrip --- dmd2/hdrgen.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dmd2/hdrgen.c b/dmd2/hdrgen.c index 64b9f68902b..cb092583577 100644 --- a/dmd2/hdrgen.c +++ b/dmd2/hdrgen.c @@ -1145,9 +1145,15 @@ class PrettyPrintVisitor : public Visitor ld_sprint(buffer, 'g', value); assert(strlen(buffer) < BUFFER_LEN); - real_t r = Port::strtold(buffer, NULL); - if (r != value) // if exact duplication - ld_sprint(buffer, 'a', value); + #if _MSC_VER + // MSVC: LLVM's APFloat is used for strtold, which asserts for certain special float inputs + if (!Port::isNan(value) && !Port::isInfinity(value)) + #endif + { + real_t r = Port::strtold(buffer, NULL); + if (r != value) // if exact duplication + ld_sprint(buffer, 'a', value); + } buf->writestring(buffer); if (type) From 28407c6906904764b4ed4da4fd5d5769d0af0bb9 Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 26 Apr 2015 19:09:56 +0200 Subject: [PATCH 037/101] Fix a problem with debug info for nested local variables. Debug info for nested local variables must be created for each function (with different address expression). The resulting debug info was not stored per function which resulted in the use of the last created debug info even if it was wrong. This commit fixes the bug and the current assertion with LLVM 3.7. --- gen/dibuilder.cpp | 28 ++++++++++++++++++++-------- ir/irvar.h | 27 ++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 39797cc56bb..93c86e77f08 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -20,6 +20,7 @@ #include "enum.h" #include "module.h" #include "mtype.h" +#include //////////////////////////////////////////////////////////////////////////////// @@ -825,7 +826,11 @@ void ldc::DIBuilder::EmitStopPoint(unsigned ln) void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) { - llvm::DIVariable debugVariable = getIrVar(vd)->debugVariable; + IrVar::DebugMap::iterator sub = getIrVar(vd)->debug.find(IR->func()->diSubprogram); + if (sub == getIrVar(vd)->debug.end()) + return; + + llvm::DIVariable debugVariable = sub->second; if (!global.params.symdebug || !debugVariable) return; @@ -855,8 +860,9 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, LOG_SCOPE; IrVar *irVar = getIrVar(vd); - if (IR->func()->diSubprogram == irVar->debugFunc) // ensure that the debug variable is created only once - return; + IrVar::DebugMap::iterator sub = irVar->debug.find(IR->func()->diSubprogram); + if (sub != irVar->debug.end()) + return; // ensure that the debug variable is created only once // get type description llvm::DIType TD = CreateTypeDescription(vd->type, true); @@ -872,10 +878,16 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, else tag = llvm::dwarf::DW_TAG_auto_variable; +#if LDC_LLVM_VER >= 307 + llvm::MDLocalVariable* debugVariable; +#else + llvm::DIVariable debugVariable; +#endif + #if LDC_LLVM_VER < 306 if (addr.empty()) { #endif - irVar->debugVariable = DBuilder.createLocalVariable( + debugVariable = DBuilder.createLocalVariable( tag, // tag GetCurrentScope(), // scope vd->toChars(), // name @@ -887,7 +899,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, #if LDC_LLVM_VER < 306 } else { - irVar->debugVariable = DBuilder.createComplexVariable( + debugVariable = DBuilder.createComplexVariable( tag, // tag GetCurrentScope(), // scope vd->toChars(), // name @@ -897,14 +909,14 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, addr ); } - irVar->debugFunc = IR->func()->diSubprogram; #endif + irVar->debug[IR->func()->diSubprogram] = debugVariable; // declare #if LDC_LLVM_VER >= 306 - Declare(ll, irVar->debugVariable, addr.empty() ? DBuilder.createExpression() : DBuilder.createExpression(addr)); + Declare(ll, debugVariable, addr.empty() ? DBuilder.createExpression() : DBuilder.createExpression(addr)); #else - Declare(ll, irVar->debugVariable); + Declare(ll, debugVariable); #endif } diff --git a/ir/irvar.h b/ir/irvar.h index 2e2e1f5691f..1ed535ed97f 100644 --- a/ir/irvar.h +++ b/ir/irvar.h @@ -29,6 +29,8 @@ #include "llvm/Analysis/DebugInfo.h" #endif +#include + struct IrFuncTyArg; class VarDeclaration; @@ -42,14 +44,29 @@ struct IrVar VarDeclaration* V; llvm::Value* value; - // debug description + // Debug description of variable. + // A variable can be accessed from nested functions. + // Each function has a debug description for the variable but with + // different address expression. #if LDC_LLVM_VER >= 307 - llvm::MDLocalVariable* debugVariable = nullptr; - llvm::MDSubprogram* debugFunc = nullptr; + struct MDSubprogramLess : public std::binary_function { + bool operator()(const llvm::MDSubprogram* a, const llvm::MDSubprogram* b) const + { + return a->getLinkageName() < b->getLinkageName(); + } + }; + + typedef std::map DebugMap; #else - llvm::DIVariable debugVariable; - llvm::DISubprogram debugFunc; + struct DISubprogramLess : public std::binary_function { + bool operator()(const llvm::DISubprogram& a, const llvm::DISubprogram& b) const + { + return a.getLinkageName() < b.getLinkageName(); + } +}; + typedef std::map DebugMap; #endif + DebugMap debug; }; // represents a global variable From 6cba633e8fa59c8a3c2dda95d8b9fd1a0dce69b5 Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 26 Apr 2015 21:02:40 +0200 Subject: [PATCH 038/101] Add -k to dmd-testsuite execution. This should run all tests but still set the error exit code. --- tests/d2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/CMakeLists.txt b/tests/d2/CMakeLists.txt index d3ed7c8c3ca..c7f1c5449df 100644 --- a/tests/d2/CMakeLists.txt +++ b/tests/d2/CMakeLists.txt @@ -23,7 +23,7 @@ function(add_testsuite config_name dflags model) # testsuite build system provides no way to run the test cases with a # given set of flags without trying all combinations of them. add_test(NAME ${name} - COMMAND make -C ${PROJECT_SOURCE_DIR}/tests/d2/dmd-testsuite RESULTS_DIR=${outdir} DMD=$ DFLAGS=${dflags} MODEL=${model} quick + COMMAND make -k -C ${PROJECT_SOURCE_DIR}/tests/d2/dmd-testsuite RESULTS_DIR=${outdir} DMD=$ DFLAGS=${dflags} MODEL=${model} quick ) set_tests_properties(${name} PROPERTIES DEPENDS clean-${name}) endfunction() From 8395d19a5d85faafd935bb30042c5f1edbd01a55 Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 26 Apr 2015 21:09:29 +0200 Subject: [PATCH 039/101] Fix error message in DMD frontend. This is already upstream. --- dmd2/interpret.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd2/interpret.c b/dmd2/interpret.c index b7823483e74..b3c52d638f0 100644 --- a/dmd2/interpret.c +++ b/dmd2/interpret.c @@ -4520,7 +4520,7 @@ class Interpreter : public Visitor firstIndex = lowerbound + ofs; if (firstIndex < 0 || hi > dim) { - originalExp->error("slice [lld..%lld] exceeds memory block bounds [0..%lld]", + originalExp->error("slice [%lld..%lld] exceeds memory block bounds [0..%lld]", firstIndex, hi, dim); return EXP_CANT_INTERPRET; } From fc59f0392fea9b911f3390b4a2078a11f0f21935 Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 26 Apr 2015 21:10:54 +0200 Subject: [PATCH 040/101] Fix a printf warning. --- gen/module.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/module.cpp b/gen/module.cpp index 516f3ed206c..77977e8f8f5 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -586,7 +586,7 @@ static void addCoverageAnalysis(Module* m) // For safety, make the array large enough such that the slice passed to _d_cover_register2 is completely valid. array_size = m->numlines; - IF_LOG Logger::println("Build private variable: size_t[%d] _d_cover_valid", array_size); + IF_LOG Logger::println("Build private variable: size_t[%llu] _d_cover_valid", (ulonglong) array_size); llvm::ArrayType* type = llvm::ArrayType::get(DtoSize_t(), array_size); llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type); From 2f3b31909b4372e8c9e270834679b4662f97ed9f Mon Sep 17 00:00:00 2001 From: kai Date: Tue, 28 Apr 2015 00:13:43 +0200 Subject: [PATCH 041/101] LLVM 3.7: Fix GEP instructions in coverage code. --- gen/coverage.cpp | 2 +- gen/module.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gen/coverage.cpp b/gen/coverage.cpp index e2acc2117d6..0a7af5a504f 100644 --- a/gen/coverage.cpp +++ b/gen/coverage.cpp @@ -29,7 +29,7 @@ void emitCoverageLinecountInc(Loc &loc) { LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(line) }; LLValue* ptr = llvm::ConstantExpr::getGetElementPtr( #if LDC_LLVM_VER >= 307 - LLType::getInt32Ty(gIR->context()), + LLArrayType::get(LLType::getInt32Ty(gIR->context()), gIR->dmodule->numlines), #endif gIR->dmodule->d_cover_data, idxs, true); diff --git a/gen/module.cpp b/gen/module.cpp index 77977e8f8f5..390f40a739f 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -595,7 +595,7 @@ static void addCoverageAnalysis(Module* m) d_cover_valid_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), llvm::ConstantExpr::getGetElementPtr( #if LDC_LLVM_VER >= 307 - DtoSize_t(), + type, #endif m->d_cover_valid, idxs, true) ); @@ -616,7 +616,7 @@ static void addCoverageAnalysis(Module* m) d_cover_data_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), llvm::ConstantExpr::getGetElementPtr( #if LDC_LLVM_VER >= 307 - LLType::getInt32Ty(gIR->context()), + type, #endif m->d_cover_data, idxs, true) ); } From 17214d2175b34539fc5cc55f503907d64ca79ef3 Mon Sep 17 00:00:00 2001 From: kai Date: Mon, 27 Apr 2015 23:23:22 +0200 Subject: [PATCH 042/101] Refactoring the debug info for nested local variables. - the debug info is now stored in the IrFunction object -> saves the lookup from VarDeclaration to IrVar - uses a llvm::DenseMap instead of std::map -> no comparison method required -> hashing should be faster then a tree lookup --- gen/dibuilder.cpp | 13 ++++++------- ir/irfunction.h | 6 ++++++ ir/irvar.h | 26 -------------------------- 3 files changed, 12 insertions(+), 33 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 93c86e77f08..7bcd1ed2612 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -20,7 +20,6 @@ #include "enum.h" #include "module.h" #include "mtype.h" -#include //////////////////////////////////////////////////////////////////////////////// @@ -826,8 +825,8 @@ void ldc::DIBuilder::EmitStopPoint(unsigned ln) void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) { - IrVar::DebugMap::iterator sub = getIrVar(vd)->debug.find(IR->func()->diSubprogram); - if (sub == getIrVar(vd)->debug.end()) + IrFunction::VariableMap::iterator sub = IR->func()->variableMap.find(vd); + if (sub == IR->func()->variableMap.end()) return; llvm::DIVariable debugVariable = sub->second; @@ -859,9 +858,9 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Logger::println("D to dwarf local variable"); LOG_SCOPE; - IrVar *irVar = getIrVar(vd); - IrVar::DebugMap::iterator sub = irVar->debug.find(IR->func()->diSubprogram); - if (sub != irVar->debug.end()) + IrFunction::VariableMap& variableMap = IR->func()->variableMap; + IrFunction::VariableMap::iterator sub = variableMap.find(vd); + if (sub != variableMap.end()) return; // ensure that the debug variable is created only once // get type description @@ -910,7 +909,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, ); } #endif - irVar->debug[IR->func()->diSubprogram] = debugVariable; + variableMap[vd] = debugVariable; // declare #if LDC_LLVM_VER >= 306 diff --git a/ir/irfunction.h b/ir/irfunction.h index d45737d9b6b..ec4fef325f8 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -16,6 +16,8 @@ #ifndef LDC_IR_IRFUNCTION_H #define LDC_IR_IRFUNCTION_H +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" #include "gen/llvm.h" #include "ir/irlandingpad.h" #include "ir/irfuncty.h" @@ -125,10 +127,14 @@ struct IrFunction #if LDC_LLVM_VER >= 307 llvm::MDSubprogram* diSubprogram = nullptr; std::stack diLexicalBlocks; + typedef llvm::DenseMap VariableMap; #else llvm::DISubprogram diSubprogram; std::stack diLexicalBlocks; + typedef llvm::DenseMap VariableMap; #endif + // Debug info for all variables + VariableMap variableMap; IrFuncTy irFty; }; diff --git a/ir/irvar.h b/ir/irvar.h index 1ed535ed97f..1969847fa36 100644 --- a/ir/irvar.h +++ b/ir/irvar.h @@ -29,8 +29,6 @@ #include "llvm/Analysis/DebugInfo.h" #endif -#include - struct IrFuncTyArg; class VarDeclaration; @@ -43,30 +41,6 @@ struct IrVar VarDeclaration* V; llvm::Value* value; - - // Debug description of variable. - // A variable can be accessed from nested functions. - // Each function has a debug description for the variable but with - // different address expression. -#if LDC_LLVM_VER >= 307 - struct MDSubprogramLess : public std::binary_function { - bool operator()(const llvm::MDSubprogram* a, const llvm::MDSubprogram* b) const - { - return a->getLinkageName() < b->getLinkageName(); - } - }; - - typedef std::map DebugMap; -#else - struct DISubprogramLess : public std::binary_function { - bool operator()(const llvm::DISubprogram& a, const llvm::DISubprogram& b) const - { - return a.getLinkageName() < b.getLinkageName(); - } -}; - typedef std::map DebugMap; -#endif - DebugMap debug; }; // represents a global variable From 6ab801361a817fff272aa95e45b552310c9748bf Mon Sep 17 00:00:00 2001 From: kai Date: Thu, 30 Apr 2015 21:53:54 +0200 Subject: [PATCH 043/101] LLVM 3.7: Debug info classes changed again. The solution is to use a typedef to hide the differences in most cases. --- driver/toobj.cpp | 16 ++++-- gen/dibuilder.cpp | 144 +++++++++++++++++++++++++--------------------- gen/dibuilder.h | 120 +++++++++++++++++++------------------- ir/irfunction.h | 6 +- ir/irtypeaggr.h | 2 +- 5 files changed, 152 insertions(+), 136 deletions(-) diff --git a/driver/toobj.cpp b/driver/toobj.cpp index 420f6eb6bd1..6c7a8e86b73 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -159,7 +159,7 @@ namespace { os << debugLoc.getLine() << ":" << debugLoc.getCol(); #if LDC_LLVM_VER >= 307 - if (MDLocation *IDL = debugLoc.getInlinedAt()) + if (DILocation *IDL = debugLoc.getInlinedAt()) { os << "@"; printDebugLoc(IDL, os); @@ -181,13 +181,13 @@ namespace { // Find the MDNode which corresponds to the DISubprogram data that described F. #if LDC_LLVM_VER >= 307 - static MDSubprogram* FindSubprogram(const Function *F, DebugInfoFinder &Finder) + static DISubprogram* FindSubprogram(const Function *F, DebugInfoFinder &Finder) #else static MDNode* FindSubprogram(const Function *F, DebugInfoFinder &Finder) #endif { #if LDC_LLVM_VER >= 307 - for (MDSubprogram* Subprogram : Finder.subprograms()) + for (DISubprogram* Subprogram : Finder.subprograms()) if (Subprogram->describes(F)) return Subprogram; return nullptr; #elif LDC_LLVM_VER >= 305 @@ -214,7 +214,7 @@ namespace Finder.processModule(const_cast(*F->getParent())); #endif #if LDC_LLVM_VER >= 307 - if (MDSubprogram* N = FindSubprogram(F, Finder)) + if (DISubprogram* N = FindSubprogram(F, Finder)) #else if (MDNode* N = FindSubprogram(F, Finder)) #endif @@ -275,7 +275,11 @@ namespace } if (const DbgDeclareInst* DDI = dyn_cast(instr)) { +#if LDC_LLVM_VER >= 307 + DILocalVariable* Var(DDI->getVariable()); +#else DIVariable Var(DDI->getVariable()); +#endif if (!padding) { os.PadToColumn(50); @@ -289,7 +293,11 @@ namespace } else if (const DbgValueInst* DVI = dyn_cast(instr)) { +#if LDC_LLVM_VER >= 307 + DILocalVariable* Var(DVI->getVariable()); +#else DIVariable Var(DVI->getVariable()); +#endif if (!padding) { os.PadToColumn(50); diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 7bcd1ed2612..018fffe4cac 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////////////// #if LDC_LLVM_VER >= 307 -typedef llvm::DebugNode Access; +typedef llvm::DINode Access; #else typedef llvm::DIDescriptor Access; #endif @@ -61,11 +61,7 @@ llvm::LLVMContext &ldc::DIBuilder::getContext() return IR->context(); } -#if LDC_LLVM_VER >= 307 -llvm::MDScope* ldc::DIBuilder::GetCurrentScope() -#else -llvm::DIDescriptor ldc::DIBuilder::GetCurrentScope() -#endif +ldc::DIScope ldc::DIBuilder::GetCurrentScope() { IrFunction *fn = IR->func(); if (fn->diLexicalBlocks.empty()) @@ -76,9 +72,9 @@ llvm::DIDescriptor ldc::DIBuilder::GetCurrentScope() return fn->diLexicalBlocks.top(); } -void ldc::DIBuilder::Declare(llvm::Value *var, llvm::DIVariable divar +void ldc::DIBuilder::Declare(llvm::Value *var, ldc::DILocalVariable divar #if LDC_LLVM_VER >= 306 - , llvm::DIExpression diexpr + , ldc::DIExpression diexpr #endif ) { @@ -93,7 +89,7 @@ void ldc::DIBuilder::Declare(llvm::Value *var, llvm::DIVariable divar instr->setDebugLoc(IR->ir->getCurrentDebugLocation()); } -llvm::DIFile ldc::DIBuilder::CreateFile(Loc& loc) +ldc::DIFile ldc::DIBuilder::CreateFile(Loc& loc) { llvm::SmallString<128> path(loc.filename ? loc.filename : ""); llvm::sys::fs::make_absolute(path); @@ -104,7 +100,7 @@ llvm::DIFile ldc::DIBuilder::CreateFile(Loc& loc) ); } -llvm::DIType ldc::DIBuilder::CreateBasicType(Type *type) +ldc::DIType ldc::DIBuilder::CreateBasicType(Type *type) { using namespace llvm::dwarf; @@ -165,7 +161,7 @@ llvm::DIType ldc::DIBuilder::CreateBasicType(Type *type) ); } -llvm::DIType ldc::DIBuilder::CreateEnumType(Type *type) +ldc::DIType ldc::DIBuilder::CreateEnumType(Type *type) { llvm::Type *T = DtoType(type); @@ -193,10 +189,10 @@ llvm::DIType ldc::DIBuilder::CreateEnumType(Type *type) llvm::StringRef Name = te->toChars(); unsigned LineNumber = te->sym->loc.linnum; - llvm::DIFile File = CreateFile(te->sym->loc); + ldc::DIFile File(CreateFile(te->sym->loc)); return DBuilder.createEnumerationType( - llvm::DICompileUnit(GetCU()), + GetCU(), Name, File, LineNumber, @@ -209,7 +205,7 @@ llvm::DIType ldc::DIBuilder::CreateEnumType(Type *type) ); } -llvm::DIType ldc::DIBuilder::CreatePointerType(Type *type) +ldc::DIType ldc::DIBuilder::CreatePointerType(Type *type) { llvm::Type *T = DtoType(type); Type *t = type->toBasetype(); @@ -218,7 +214,7 @@ llvm::DIType ldc::DIBuilder::CreatePointerType(Type *type) // find base type Type *nt = t->nextOf(); - llvm::DIType basetype = CreateTypeDescription(nt, false); + ldc::DIType basetype(CreateTypeDescription(nt, false)); return DBuilder.createPointerType( basetype, @@ -228,7 +224,7 @@ llvm::DIType ldc::DIBuilder::CreatePointerType(Type *type) ); } -llvm::DIType ldc::DIBuilder::CreateVectorType(Type *type) +ldc::DIType ldc::DIBuilder::CreateVectorType(Type *type) { LLType* T = DtoType(type); Type* t = type->toBasetype(); @@ -245,7 +241,7 @@ llvm::DIType ldc::DIBuilder::CreateVectorType(Type *type) { DBuilder.getOrCreateSubrange(0, Dim) }; - llvm::DIType basetype = CreateTypeDescription(te, false); + ldc::DIType basetype(CreateTypeDescription(te, false)); return DBuilder.createVectorType( getTypeBitSize(T), // size (bits) @@ -255,17 +251,17 @@ llvm::DIType ldc::DIBuilder::CreateVectorType(Type *type) ); } -llvm::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type, - llvm::DIFile file, - const char* c_name, - unsigned offset, - PROT prot) +ldc::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type, + ldc::DIFile file, + const char* c_name, + unsigned offset, + PROT prot) { llvm::Type *T = DtoType(type); Type *t = type->toBasetype(); // find base type - llvm::DIType basetype = CreateTypeDescription(t, true); + ldc::DIType basetype(CreateTypeDescription(t, true)); unsigned Flags = 0; switch (prot) { @@ -285,7 +281,7 @@ llvm::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type, } return DBuilder.createMemberType( - llvm::DICompileUnit(GetCU()), + GetCU(), c_name, // name file, // file linnum, // line number @@ -297,7 +293,7 @@ llvm::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type, ); } -void ldc::DIBuilder::AddBaseFields(ClassDeclaration *sd, llvm::DIFile file, +void ldc::DIBuilder::AddBaseFields(ClassDeclaration *sd, ldc::DIFile file, #if LDC_LLVM_VER >= 306 std::vector &elems #else @@ -321,7 +317,7 @@ void ldc::DIBuilder::AddBaseFields(ClassDeclaration *sd, llvm::DIFile file, } } -llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) +ldc::DIType ldc::DIBuilder::CreateCompositeType(Type *type) { Type* t = type->toBasetype(); assert((t->ty == Tstruct || t->ty == Tclass) && @@ -367,10 +363,14 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) // defaults llvm::StringRef name = sd->toChars(); unsigned linnum = sd->loc.linnum; - llvm::DICompileUnit CU(GetCU()); + ldc::DICompileUnit CU(GetCU()); assert(CU && "Compilation unit missing or corrupted"); - llvm::DIFile file = CreateFile(sd->loc); - llvm::DIType derivedFrom; + ldc::DIFile file(CreateFile(sd->loc)); +#if LDC_LLVM_VER >= 307 + ldc::DIType derivedFrom = nullptr; +#else + ldc::DIType derivedFrom; +#endif // set diCompositeType to handle recursive types properly unsigned tag = (t->ty == Tstruct) ? llvm::dwarf::DW_TAG_structure_type @@ -398,7 +398,7 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) I != E; ++I) { VarDeclaration* vd = *I; - llvm::DIType dt = CreateMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset, vd->prot()); + ldc::DIType dt = CreateMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset, vd->prot()); elems.push_back(dt); } } @@ -412,12 +412,12 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) } #if LDC_LLVM_VER >= 307 - llvm::DebugNodeArray elemsArray = DBuilder.getOrCreateArray(elems); + llvm::DINodeArray elemsArray = DBuilder.getOrCreateArray(elems); #else llvm::DIArray elemsArray = DBuilder.getOrCreateArray(elems); #endif - llvm::DIType ret; + ldc::DIType ret; if (t->ty == Tclass) { ret = DBuilder.createClassType( CU, // compile unit where defined @@ -448,7 +448,7 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) } #if LDC_LLVM_VER >= 307 - ir->diCompositeType = DBuilder.replaceTemporary(llvm::TempMDType(ir->diCompositeType), static_cast(ret)); + ir->diCompositeType = DBuilder.replaceTemporary(llvm::TempDINode(ir->diCompositeType), static_cast(ret)); #else ir->diCompositeType.replaceAllUsesWith(ret); #endif @@ -457,7 +457,7 @@ llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) return ret; } -llvm::DIType ldc::DIBuilder::CreateArrayType(Type *type) +ldc::DIType ldc::DIBuilder::CreateArrayType(Type *type) { llvm::Type *T = DtoType(type); Type *t = type->toBasetype(); @@ -465,7 +465,7 @@ llvm::DIType ldc::DIBuilder::CreateArrayType(Type *type) assert(t->ty == Tarray && "Only arrays allowed for debug info in DIBuilder::CreateArrayType"); Loc loc(IR->dmodule, 0, 0); - llvm::DIFile file = CreateFile(loc); + ldc::DIFile file(CreateFile(loc)); #if LDC_LLVM_VER >= 306 llvm::Metadata *elems[] = @@ -480,21 +480,23 @@ llvm::DIType ldc::DIBuilder::CreateArrayType(Type *type) return DBuilder.createStructType ( - llvm::DICompileUnit(GetCU()), + GetCU(), llvm::StringRef(), // Name TODO: Really no name for arrays? t->toChars()? file, // File 0, // LineNo getTypeBitSize(T), // size in bits getABITypeAlign(T)*8, // alignment in bits 0, // What here? -#if LDC_LLVM_VER >= 303 +#if LDC_LLVM_VER >= 307 + nullptr, // DerivedFrom +#elif LDC_LLVM_VER >= 303 llvm::DIType(), // DerivedFrom #endif DBuilder.getOrCreateArray(elems) ); } -llvm::DIType ldc::DIBuilder::CreateSArrayType(Type *type) +ldc::DIType ldc::DIBuilder::CreateSArrayType(Type *type) { llvm::Type *T = DtoType(type); Type *t = type->toBasetype(); @@ -517,7 +519,7 @@ llvm::DIType ldc::DIBuilder::CreateSArrayType(Type *type) subscripts.push_back(subscript); t = t->nextOf(); } - llvm::DIType basetype = CreateTypeDescription(t, false); + ldc::DIType basetype(CreateTypeDescription(t, false)); return DBuilder.createArrayType( getTypeBitSize(T), // size (bits) @@ -527,7 +529,7 @@ llvm::DIType ldc::DIBuilder::CreateSArrayType(Type *type) ); } -llvm::DIType ldc::DIBuilder::CreateAArrayType(Type *type) +ldc::DIType ldc::DIBuilder::CreateAArrayType(Type *type) { // FIXME: Implement #if LDC_LLVM_VER >= 304 @@ -539,13 +541,13 @@ llvm::DIType ldc::DIBuilder::CreateAArrayType(Type *type) //////////////////////////////////////////////////////////////////////////////// -ldc::DIFunctionType ldc::DIBuilder::CreateFunctionType(Type *type) +ldc::DISubroutineType ldc::DIBuilder::CreateFunctionType(Type *type) { TypeFunction *t = static_cast(type); Type *retType = t->next; Loc loc(IR->dmodule, 0, 0); - llvm::DIFile file = CreateFile(loc); + ldc::DIFile file(CreateFile(loc)); // Create "dummy" subroutine type for the return type #if LDC_LLVM_VER >= 306 @@ -555,7 +557,7 @@ ldc::DIFunctionType ldc::DIBuilder::CreateFunctionType(Type *type) #endif Elts.push_back(CreateTypeDescription(retType, true)); #if LDC_LLVM_VER >= 307 - llvm::MDTypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); + llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); #elif LDC_LLVM_VER >= 306 llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); #else @@ -564,13 +566,13 @@ ldc::DIFunctionType ldc::DIBuilder::CreateFunctionType(Type *type) return DBuilder.createSubroutineType(file, EltTypeArray); } -ldc::DIFunctionType ldc::DIBuilder::CreateDelegateType(Type *type) +ldc::DISubroutineType ldc::DIBuilder::CreateDelegateType(Type *type) { // FIXME: Implement TypeDelegate *t = static_cast(type); Loc loc(IR->dmodule, 0, 0); - llvm::DIFile file = CreateFile(loc); + ldc::DIFile file(CreateFile(loc)); // Create "dummy" subroutine type for the return type #if LDC_LLVM_VER >= 306 @@ -586,7 +588,7 @@ ldc::DIFunctionType ldc::DIBuilder::CreateDelegateType(Type *type) #endif ); #if LDC_LLVM_VER >= 307 - llvm::MDTypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); + llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); #elif LDC_LLVM_VER >= 306 llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); #else @@ -597,7 +599,7 @@ ldc::DIFunctionType ldc::DIBuilder::CreateDelegateType(Type *type) //////////////////////////////////////////////////////////////////////////////// -llvm::DIType ldc::DIBuilder::CreateTypeDescription(Type* type, +ldc::DIType ldc::DIBuilder::CreateTypeDescription(Type* type, bool derefclass) { Type *t = type->toBasetype(); @@ -675,21 +677,25 @@ void ldc::DIBuilder::EmitCompileUnit(Module *m) #endif } -llvm::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) +ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) { if (!global.params.symdebug) +#if LDC_LLVM_VER >= 307 + return nullptr; +#else return llvm::DISubprogram(); +#endif Logger::println("D to dwarf subprogram"); LOG_SCOPE; - llvm::DICompileUnit CU(GetCU()); + ldc::DICompileUnit CU(GetCU()); assert(CU && "Compilation unit missing or corrupted in DIBuilder::EmitSubProgram"); - llvm::DIFile file = CreateFile(fd->loc); + ldc::DIFile file(CreateFile(fd->loc)); // Create subroutine type - ldc::DIFunctionType DIFnType = CreateFunctionType(static_cast(fd->type)); + ldc::DISubroutineType DIFnType = CreateFunctionType(static_cast(fd->type)); // FIXME: duplicates ? return DBuilder.createFunction( @@ -708,20 +714,24 @@ llvm::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) ); } -llvm::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function* Fn, - llvm::StringRef prettyname) +ldc::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function* Fn, + llvm::StringRef prettyname) { if (!global.params.symdebug) +#if LDC_LLVM_VER >= 307 + return nullptr; +#else return llvm::DISubprogram(); +#endif Logger::println("D to dwarf subprogram"); LOG_SCOPE; - llvm::DICompileUnit CU(GetCU()); + ldc::DICompileUnit CU(GetCU()); assert(CU && "Compilation unit missing or corrupted in DIBuilder::EmitSubProgram"); Loc loc(IR->dmodule, 0, 0); - llvm::DIFile file(CreateFile(loc)); + ldc::DIFile file(CreateFile(loc)); // Create "dummy" subroutine type for the return type #if LDC_LLVM_VER >= 306 @@ -731,13 +741,13 @@ llvm::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function* Fn, #endif Elts.push_back(CreateTypeDescription(Type::tvoid, true)); #if LDC_LLVM_VER >= 307 - llvm::MDTypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); + llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); #elif LDC_LLVM_VER >= 306 llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); #else llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); #endif - ldc::DIFunctionType DIFnType = DBuilder.createSubroutineType(file, EltTypeArray); + ldc::DISubroutineType DIFnType = DBuilder.createSubroutineType(file, EltTypeArray); // FIXME: duplicates ? return DBuilder.createFunction( @@ -786,7 +796,7 @@ void ldc::DIBuilder::EmitBlockStart(Loc& loc) Logger::println("D to dwarf block start"); LOG_SCOPE; - llvm::DILexicalBlock block = DBuilder.createLexicalBlock( + ldc::DILexicalBlock block = DBuilder.createLexicalBlock( GetCurrentScope(), // scope CreateFile(loc), // file loc.linnum, // line @@ -829,7 +839,7 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) if (sub == IR->func()->variableMap.end()) return; - llvm::DIVariable debugVariable = sub->second; + ldc::DILocalVariable debugVariable = sub->second; if (!global.params.symdebug || !debugVariable) return; @@ -864,7 +874,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, return; // ensure that the debug variable is created only once // get type description - llvm::DIType TD = CreateTypeDescription(vd->type, true); + ldc::DIType TD = CreateTypeDescription(vd->type, true); if (static_cast(TD) == 0) return; // unsupported @@ -877,11 +887,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, else tag = llvm::dwarf::DW_TAG_auto_variable; -#if LDC_LLVM_VER >= 307 - llvm::MDLocalVariable* debugVariable; -#else - llvm::DIVariable debugVariable; -#endif + ldc::DILocalVariable debugVariable; #if LDC_LLVM_VER < 306 if (addr.empty()) { @@ -919,10 +925,14 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, #endif } -llvm::DIGlobalVariable ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd) +ldc::DIGlobalVariable ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd) { if (!global.params.symdebug) +#if LDC_LLVM_VER >= 307 + return nullptr; +#else return llvm::DIGlobalVariable(); +#endif Logger::println("D to dwarf global_variable"); LOG_SCOPE; @@ -931,7 +941,7 @@ llvm::DIGlobalVariable ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable * return DBuilder.createGlobalVariable( #if LDC_LLVM_VER >= 306 - llvm::DICompileUnit(GetCU()), // context + GetCU(), // context #endif vd->toChars(), // name #if LDC_LLVM_VER >= 303 diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 48c62974389..40e26ab2b47 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -67,40 +67,43 @@ extern const llvm::DataLayout* gDataLayout; extern const llvm::TargetData* gDataLayout; #endif -// LLVM 3.7: no more DIFoo wrappers for MDFoo* pointers -// Let's define primitive wrappers for backward compatibility, -// primarily for proper initialization with null. -#if LDC_LLVM_VER >= 307 -namespace llvm { - template - class DIWrapper - { - T* ptr; - public: - DIWrapper(T* ptr = nullptr) : ptr(ptr) {} - operator T*() { return ptr; } - T* operator ->() { return ptr; } - }; - - using DICompileUnit = DIWrapper; - using DIExpression = DIWrapper; - using DIFile = DIWrapper; - using DIGlobalVariable = DIWrapper; - using DILexicalBlock = DIWrapper; - using DISubprogram = DIWrapper; - using DIType = DIWrapper; - using DIVariable = DIWrapper; -} -#endif - namespace ldc { +// Define some basic types #if LDC_LLVM_VER >= 307 -typedef llvm::MDSubroutineType* DIFunctionType; +typedef llvm::DIType* DIType; +typedef llvm::DIFile* DIFile; +typedef llvm::DIGlobalVariable* DIGlobalVariable; +typedef llvm::DILocalVariable* DILocalVariable; +typedef llvm::DIExpression* DIExpression; +typedef llvm::DILexicalBlock* DILexicalBlock; +typedef llvm::DIScope* DIScope; +typedef llvm::DISubroutineType* DISubroutineType; +typedef llvm::DISubprogram* DISubprogram; +typedef llvm::DICompileUnit* DICompileUnit; #elif LDC_LLVM_VER >= 304 -typedef llvm::DICompositeType DIFunctionType; +typedef llvm::DIType DIType; +typedef llvm::DIFile DIFile; +typedef llvm::DIGlobalVariable DIGlobalVariable; +typedef llvm::DIVariable DILocalVariable; +typedef llvm::DILexicalBlock DILexicalBlock; +typedef llvm::DIDescriptor DIScope; +typedef llvm::DICompositeType DISubroutineType; +typedef llvm::DISubprogram DISubprogram; +typedef llvm::DICompileUnit DICompileUnit; #else -typedef llvm::DIType DIFunctionType; +typedef llvm::DIType DIType; +typedef llvm::DIFile DIFile; +typedef llvm::DIGlobalVariable DIGlobalVariable; +typedef llvm::DIVariable DILocalVariable; +typedef llvm::DILexicalBlock DILexicalBlock; +typedef llvm::DIDescriptor DIScope; +typedef llvm::DISubprogram DISubprogram; +typedef llvm::DIType DISubroutineType; +typedef llvm::DICompileUnit DICompileUnit; +#endif +#if LDC_LLVM_VER == 306 +typedef llvm::DIExpression DIExpression; #endif class DIBuilder @@ -109,20 +112,19 @@ class DIBuilder llvm::DIBuilder DBuilder; #if LDC_LLVM_VER >= 307 - llvm::MDCompileUnit *CUNode; - - llvm::MDCompileUnit *GetCU() - { - return CUNode; - } + DICompileUnit CUNode; #else const llvm::MDNode *CUNode; +#endif - const llvm::MDNode *GetCU() + DICompileUnit GetCU() { +#if LDC_LLVM_VER >= 307 return CUNode; - } +#else + return llvm::DICompileUnit(CUNode); #endif + } public: DIBuilder(IRState *const IR, llvm::Module &M); @@ -134,7 +136,7 @@ class DIBuilder /// \brief Emit the Dwarf subprogram global for a function declaration fd. /// \param fd Function declaration to emit as subprogram. /// \returns the Dwarf subprogram global. - llvm::DISubprogram EmitSubProgram(FuncDeclaration *fd); // FIXME + DISubprogram EmitSubProgram(FuncDeclaration *fd); // FIXME /// \brief Emit the Dwarf subprogram global for a module ctor. /// This is used for generated functions like moduleinfoctors, @@ -142,7 +144,7 @@ class DIBuilder /// \param Fn llvm::Function pointer. /// \param prettyname The name as seen in the source. /// \returns the Dwarf subprogram global. - llvm::DISubprogram EmitModuleCTor(llvm::Function* Fn, llvm::StringRef prettyname); // FIXME + DISubprogram EmitModuleCTor(llvm::Function* Fn, llvm::StringRef prettyname); // FIXME /// \brief Emits debug info for function start void EmitFuncStart(FuncDeclaration *fd); @@ -175,43 +177,39 @@ class DIBuilder /// \brief Emits all things necessary for making debug info for a global variable vd. /// \param ll LLVM global variable /// \param vd Variable declaration to emit debug info for. - llvm::DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd); // FIXME + DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd); // FIXME void EmitModuleEnd(); private: llvm::LLVMContext &getContext(); Module *getDefinedModule(Dsymbol *s); -#if LDC_LLVM_VER >= 307 - llvm::MDScope* GetCurrentScope(); -#else - llvm::DIDescriptor GetCurrentScope(); -#endif - void Declare(llvm::Value *var, llvm::DIVariable divar + DIScope GetCurrentScope(); + void Declare(llvm::Value *var, ldc::DILocalVariable divar #if LDC_LLVM_VER >= 306 - , llvm::DIExpression diexpr + , ldc::DIExpression diexpr #endif ); - void AddBaseFields(ClassDeclaration *sd, llvm::DIFile file, + void AddBaseFields(ClassDeclaration *sd, ldc::DIFile file, #if LDC_LLVM_VER >= 306 std::vector &elems #else std::vector &elems #endif ); - llvm::DIFile CreateFile(Loc& loc); - llvm::DIType CreateBasicType(Type *type); - llvm::DIType CreateEnumType(Type *type); - llvm::DIType CreatePointerType(Type *type); - llvm::DIType CreateVectorType(Type *type); - llvm::DIType CreateMemberType(unsigned linnum, Type *type, llvm::DIFile file, const char* c_name, unsigned offset, PROT); - llvm::DIType CreateCompositeType(Type *type); - llvm::DIType CreateArrayType(Type *type); - llvm::DIType CreateSArrayType(Type *type); - llvm::DIType CreateAArrayType(Type *type); - DIFunctionType CreateFunctionType(Type *type); - DIFunctionType CreateDelegateType(Type *type); - llvm::DIType CreateTypeDescription(Type* type, bool derefclass = false); + DIFile CreateFile(Loc& loc); + DIType CreateBasicType(Type *type); + DIType CreateEnumType(Type *type); + DIType CreatePointerType(Type *type); + DIType CreateVectorType(Type *type); + DIType CreateMemberType(unsigned linnum, Type *type, DIFile file, const char* c_name, unsigned offset, PROT); + DIType CreateCompositeType(Type *type); + DIType CreateArrayType(Type *type); + DIType CreateSArrayType(Type *type); + DIType CreateAArrayType(Type *type); + DISubroutineType CreateFunctionType(Type *type); + DISubroutineType CreateDelegateType(Type *type); + DIType CreateTypeDescription(Type* type, bool derefclass = false); public: template diff --git a/ir/irfunction.h b/ir/irfunction.h index ec4fef325f8..a36e6bea382 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -125,9 +125,9 @@ struct IrFunction llvm::Value* _argptr; #if LDC_LLVM_VER >= 307 - llvm::MDSubprogram* diSubprogram = nullptr; - std::stack diLexicalBlocks; - typedef llvm::DenseMap VariableMap; + llvm::DISubprogram* diSubprogram = nullptr; + std::stack diLexicalBlocks; + typedef llvm::DenseMap VariableMap; #else llvm::DISubprogram diSubprogram; std::stack diLexicalBlocks; diff --git a/ir/irtypeaggr.h b/ir/irtypeaggr.h index 4b042473af0..4b0a76bd0a5 100644 --- a/ir/irtypeaggr.h +++ b/ir/irtypeaggr.h @@ -67,7 +67,7 @@ class IrTypeAggr : public IrType /// Composite type debug description. This is not only to cache, but also /// used for resolving forward references. #if LDC_LLVM_VER >= 307 - llvm::MDType* diCompositeType = nullptr; + llvm::DIType* diCompositeType = nullptr; #else llvm::DIType diCompositeType; #endif From cc9a810a697ae31574445b7948e568137995f727 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Tue, 12 May 2015 17:51:48 +0200 Subject: [PATCH 044/101] LLVM: TargetRegistry: iterator was replaced by iterator_range. --- driver/targetmachine.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp index 5a21293b1c3..f7e160b25e7 100644 --- a/driver/targetmachine.cpp +++ b/driver/targetmachine.cpp @@ -256,12 +256,18 @@ const llvm::Target *lookupTarget(const std::string &arch, llvm::Triple &triple, const llvm::Target *target = 0; if (!arch.empty()) { +#if LDC_LLVM_VER >= 307 + for (const llvm::Target &T : llvm::TargetRegistry::targets()) + { +#else for (llvm::TargetRegistry::iterator it = llvm::TargetRegistry::begin(), ie = llvm::TargetRegistry::end(); it != ie; ++it) { - if (arch == it->getName()) + const llvm::Target& T = *it; +#endif + if (arch == T.getName()) { - target = &*it; + target = &T; break; } } From 82a76cf3f84c70edca6554d7cfa237b612694279 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Tue, 12 May 2015 18:11:30 +0200 Subject: [PATCH 045/101] LLVM 3.7: TargetOptions.UseSoftFloat is gone. A function attribute use-soft-float with values true or false is used instead. This commi only ensures that LDC compiles with LLVM 3.7. The possible semantic change needs to be evaluated. --- driver/main.cpp | 5 +++++ driver/targetmachine.cpp | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/driver/main.cpp b/driver/main.cpp index a4c9e54a669..15b6bd62b57 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -560,7 +560,12 @@ static void registerMipsABI() static void registerPredefinedFloatABI(const char *soft, const char *hard, const char *softfp=NULL) { // Use target floating point unit instead of s/w float routines +#if LDC_LLVM_VER >= 307 + // FIXME: This is a semantic change! + bool useFPU = gTargetMachine->Options.FloatABIType = llvm::FloatABI::Hard; +#else bool useFPU = !gTargetMachine->Options.UseSoftFloat; +#endif VersionCondition::addPredefinedGlobalIdent(useFPU ? "D_HardFloat" : "D_SoftFloat"); if (gTargetMachine->Options.FloatABIType == llvm::FloatABI::Soft) diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp index f7e160b25e7..81b0f654e93 100644 --- a/driver/targetmachine.cpp +++ b/driver/targetmachine.cpp @@ -425,15 +425,21 @@ llvm::TargetMachine* createTargetMachine( { default: llvm_unreachable("Floating point ABI type unknown."); case FloatABI::Soft: +#if LDC_LLVM_VER < 307 targetOptions.UseSoftFloat = true; +#endif targetOptions.FloatABIType = llvm::FloatABI::Soft; break; case FloatABI::SoftFP: +#if LDC_LLVM_VER < 307 targetOptions.UseSoftFloat = false; +#endif targetOptions.FloatABIType = llvm::FloatABI::Soft; break; case FloatABI::Hard: +#if LDC_LLVM_VER < 307 targetOptions.UseSoftFloat = false; +#endif targetOptions.FloatABIType = llvm::FloatABI::Hard; break; } From b2c569404baa6ff068bc81bc444efe7c066ec1fa Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 16 May 2015 02:49:14 +0200 Subject: [PATCH 046/101] Fix a warning about sprintf type --- gen/pragma.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/pragma.cpp b/gen/pragma.cpp index 33760a1e4d9..1150481d4a5 100644 --- a/gen/pragma.cpp +++ b/gen/pragma.cpp @@ -116,7 +116,7 @@ Pragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, std::string &arg1str) else priority = 65535; char buf[8]; - sprintf(buf, "%lu", priority); + sprintf(buf, "%llu", static_cast(priority)); arg1str = std::string(buf); return ident == Id::LDC_global_crt_ctor ? LLVMglobal_crt_ctor : LLVMglobal_crt_dtor; } From 76f543d0a7c7f074651cabdbaf5a0c6c3a3c47f3 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 16 May 2015 18:56:38 +0200 Subject: [PATCH 047/101] Fix another sprintf warning --- gen/asmstmt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index 9deaf2017b1..5d0d8b0b854 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -458,7 +458,7 @@ static void remap_outargs(std::string& insnt, size_t nargs, size_t idx) needle = prefix + digits[i] + suffix; size_t pos = insnt.find(needle); if(std::string::npos != pos) - sprintf(buf, "%lu", idx++); + sprintf(buf, "%llu", static_cast(idx++)); while(std::string::npos != (pos = insnt.find(needle))) insnt.replace(pos, needle.size(), buf); } @@ -483,7 +483,7 @@ static void remap_inargs(std::string& insnt, size_t nargs, size_t idx) needle = prefix + digits[i] + suffix; size_t pos = insnt.find(needle); if(std::string::npos != pos) - sprintf(buf, "%lu", idx++); + sprintf(buf, "%llu", static_cast(idx++)); while(std::string::npos != (pos = insnt.find(needle))) insnt.replace(pos, needle.size(), buf); } From afe6051ead12a620f532267bde8043b37b7a91d2 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 16 May 2015 18:56:59 +0200 Subject: [PATCH 048/101] LLVM 3.7: Fix MIPS ABI definition. Detection of EABI is still missing. --- driver/main.cpp | 11 +++++++++++ driver/targetmachine.cpp | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/driver/main.cpp b/driver/main.cpp index 15b6bd62b57..7b0539ae7af 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -544,6 +544,16 @@ static void initializePasses() { /// Register the MIPS ABI. static void registerMipsABI() { +#if LDC_LLVM_VER >= 307 + // FIXME: EABI? + auto dl = gTargetMachine->getDataLayout(); + if (dl->getPointerSizeInBits() == 64) + VersionCondition::addPredefinedGlobalIdent("MIPS_N64"); + else if (dl->getStackAlignment() <= 64) + VersionCondition::addPredefinedGlobalIdent("MIPS_O32"); + else + VersionCondition::addPredefinedGlobalIdent("MIPS_N32"); +#else llvm::StringRef features = gTargetMachine->getTargetFeatureString(); if (features.find("+o32") != std::string::npos) VersionCondition::addPredefinedGlobalIdent("MIPS_O32"); @@ -553,6 +563,7 @@ static void registerMipsABI() VersionCondition::addPredefinedGlobalIdent("MIPS_N64"); if (features.find("+eabi") != std::string::npos) VersionCondition::addPredefinedGlobalIdent("MIPS_EABI"); +#endif } /// Register the float ABI. diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp index 81b0f654e93..d12bbc32d59 100644 --- a/driver/targetmachine.cpp +++ b/driver/targetmachine.cpp @@ -199,6 +199,7 @@ static FloatABI::Type getARMFloatABI(const llvm::Triple &triple, } } +#if LDC_LLVM_VER < 307 /// Sanitizes the MIPS ABI in the feature string. static void addMipsABI(const llvm::Triple &triple, std::vector &attrs) { @@ -238,6 +239,7 @@ static void addMipsABI(const llvm::Triple &triple, std::vector &att if (bits != defaultABI) attrs.push_back(is64Bit ? "-n64" : "-o32"); } +#endif /// Looks up a target based on an arch name and a target triple. /// @@ -362,11 +364,13 @@ llvm::TargetMachine* createTargetMachine( #endif } } +#if LDC_LLVM_VER < 307 if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel || triple.getArch() == llvm::Triple::mips64 || triple.getArch() == llvm::Triple::mips64el) addMipsABI(triple, attrs); +#endif for (unsigned i = 0; i < attrs.size(); ++i) features.AddFeature(attrs[i]); From 0e9307225963096cadefe4fd6b3e769cda9421e5 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 16 May 2015 23:27:54 +0200 Subject: [PATCH 049/101] MIPS64: Use DataLayout.getLargestLegalIntTypeSize() to check for N32. This is more natural: if pointers are not 64bit but the largest int type is 64bit then the ABI is N32; otherwise it is O32. --- driver/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/driver/main.cpp b/driver/main.cpp index 7b0539ae7af..51d8c5d1f68 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -549,10 +549,10 @@ static void registerMipsABI() auto dl = gTargetMachine->getDataLayout(); if (dl->getPointerSizeInBits() == 64) VersionCondition::addPredefinedGlobalIdent("MIPS_N64"); - else if (dl->getStackAlignment() <= 64) - VersionCondition::addPredefinedGlobalIdent("MIPS_O32"); - else + else if (dl->getLargestLegalIntTypeSize() == 64) VersionCondition::addPredefinedGlobalIdent("MIPS_N32"); + else + VersionCondition::addPredefinedGlobalIdent("MIPS_O32"); #else llvm::StringRef features = gTargetMachine->getTargetFeatureString(); if (features.find("+o32") != std::string::npos) From b92e377d49ddfc682bd19dc116a54850746d7fd5 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 17 May 2015 12:29:23 +0200 Subject: [PATCH 050/101] Fix definition of D_LP64. LP64 defines a C environment with 64bit pointers and char/short/int/long are 8/16/32/64bit. char/short/int/long have defined sizes in D. We need to look only at the pointer size. There are now 64bit environments with 32bit pointers. Examples are x32 in Intel and N32 on MIPS64. For these environments D_LP64 should not defined but the global.param.is64bit is still true. The definition of size_t is also affected. If only 32bit are addressable then size_t should also be a 32bit type. (This is not required by C standard but common practize.) The net result is that not only the definition of D_LP64 must be changed but also DtoSize_t(). --- driver/main.cpp | 25 ++++++++++++------------- gen/tollvm.cpp | 2 +- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/driver/main.cpp b/driver/main.cpp index 51d8c5d1f68..286df9e76eb 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -698,7 +698,7 @@ static void registerPredefinedTargetVersions() { } // a generic 64bit version - if (global.params.is64bit) { + if (global.params.isLP64) { VersionCondition::addPredefinedGlobalIdent("D_LP64"); } @@ -1028,6 +1028,16 @@ int main(int argc, char **argv) bitness, mFloatABI, mRelocModel, mCodeModel, codeGenOptLevel(), global.params.symdebug || disableFpElim, disableLinkerStripDead); +#if LDC_LLVM_VER >= 307 + gDataLayout = gTargetMachine->getDataLayout(); +#elif LDC_LLVM_VER >= 306 + gDataLayout = gTargetMachine->getSubtargetImpl()->getDataLayout(); +#elif LDC_LLVM_VER >= 302 + gDataLayout = gTargetMachine->getDataLayout(); +#else + gDataLayout = gTargetMachine->getTargetData(); +#endif + { llvm::Triple triple = llvm::Triple(gTargetMachine->getTargetTriple()); global.params.targetTriple = triple; @@ -1037,21 +1047,10 @@ int main(int argc, char **argv) global.params.isFreeBSD = triple.getOS() == llvm::Triple::FreeBSD; global.params.isOpenBSD = triple.getOS() == llvm::Triple::OpenBSD; global.params.isSolaris = triple.getOS() == llvm::Triple::Solaris; - // FIXME: Correctly handle the x32 ABI (AMD64 ILP32) here. - global.params.isLP64 = triple.isArch64Bit(); + global.params.isLP64 = gDataLayout->getPointerSizeInBits() == 64; global.params.is64bit = triple.isArch64Bit(); } -#if LDC_LLVM_VER >= 307 - gDataLayout = gTargetMachine->getDataLayout(); -#elif LDC_LLVM_VER >= 306 - gDataLayout = gTargetMachine->getSubtargetImpl()->getDataLayout(); -#elif LDC_LLVM_VER >= 302 - gDataLayout = gTargetMachine->getDataLayout(); -#else - gDataLayout = gTargetMachine->getTargetData(); -#endif - // allocate the target abi gABI = TargetABI::getTarget(); diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index f20739ec2dc..41ec5f8a017 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -299,7 +299,7 @@ LLIntegerType* DtoSize_t() // the type of size_t does not change once set static LLIntegerType* t = NULL; if (t == NULL) - t = (global.params.is64bit) ? LLType::getInt64Ty(gIR->context()) : LLType::getInt32Ty(gIR->context()); + t = (global.params.isLP64) ? LLType::getInt64Ty(gIR->context()) : LLType::getInt32Ty(gIR->context()); return t; } From 0cadfa055c54a6e3f294a70833a33bdbf236eab5 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 17 May 2015 13:01:15 +0200 Subject: [PATCH 051/101] LLVM 3.7: Use comparison instead of assignment. Bug spotted by Temtaime. --- driver/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/main.cpp b/driver/main.cpp index 286df9e76eb..74ba896488b 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -573,7 +573,7 @@ static void registerPredefinedFloatABI(const char *soft, const char *hard, const // Use target floating point unit instead of s/w float routines #if LDC_LLVM_VER >= 307 // FIXME: This is a semantic change! - bool useFPU = gTargetMachine->Options.FloatABIType = llvm::FloatABI::Hard; + bool useFPU = gTargetMachine->Options.FloatABIType == llvm::FloatABI::Hard; #else bool useFPU = !gTargetMachine->Options.UseSoftFloat; #endif From 4cc724ed08390fb1c63475a17e0f62f894300a85 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 17 May 2015 14:31:46 +0200 Subject: [PATCH 052/101] New Phobos fixes --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index 92d5870574b..cee2386f0dd 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 92d5870574b661ee1ce5a0ba7950df818b39372f +Subproject commit cee2386f0dd0c213542f476154e334e5eca53e7e From 8ec4918ec8af3c861efae26d76fdd3a19b57ef94 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 17 May 2015 15:50:05 +0200 Subject: [PATCH 053/101] More std.math changes. - Fixed MIPS inline assembly - Added missing EXPBIAS for 128bit float --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index cee2386f0dd..8dc621165a7 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit cee2386f0dd0c213542f476154e334e5eca53e7e +Subproject commit 8dc621165a7fa53782b6adff38338ea4ded9341e From b5cb838ec461a3db334dfb85a50900147535f926 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 17 May 2015 18:11:09 +0200 Subject: [PATCH 054/101] MIPS: Some more MIPS fixes for std.math --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index 8dc621165a7..91c43e0af80 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 8dc621165a7fa53782b6adff38338ea4ded9341e +Subproject commit 91c43e0af80e7b89e7e320a8492648dbc82a0aa4 From 9e824c38ec010c77c45f271dac4a9de4850122f0 Mon Sep 17 00:00:00 2001 From: kai Date: Mon, 18 May 2015 06:47:36 +0200 Subject: [PATCH 055/101] vararg fix for MIPS64 and PPC/PPC64. --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 8bc16bf28d9..5220555dc4c 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 8bc16bf28d9ce46ee7407c342378d47de40aea01 +Subproject commit 5220555dc4ce0ebd51d26ae783f9cd54f792335f From ca3915edcb0a8dd742b0af2487b4a2573398c681 Mon Sep 17 00:00:00 2001 From: kai Date: Mon, 18 May 2015 06:53:58 +0200 Subject: [PATCH 056/101] Add minimal ABI class for MIPS. Without this ABI class it is not possible to compile vararg funtions. --- gen/abi-mips64.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++++++ gen/abi-mips64.h | 21 +++++++++++ gen/abi.cpp | 6 +++ 3 files changed, 121 insertions(+) create mode 100644 gen/abi-mips64.cpp create mode 100644 gen/abi-mips64.h diff --git a/gen/abi-mips64.cpp b/gen/abi-mips64.cpp new file mode 100644 index 00000000000..df19b0c807c --- /dev/null +++ b/gen/abi-mips64.cpp @@ -0,0 +1,94 @@ +//===-- gen/abi-mips64.cpp - MIPS64 ABI description ------------*- C++ -*-===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// +// +// The MIPS64 N32 and N64 ABI can be found here: +// http://techpubs.sgi.com/library/dynaweb_docs/0640/SGI_Developer/books/Mpro_n32_ABI/sgi_html/index.html +// +//===----------------------------------------------------------------------===// + +#include "gen/abi.h" +#include "gen/abi-generic.h" +#include "gen/abi-mips64.h" +#include "gen/dvalue.h" +#include "gen/irstate.h" +#include "gen/llvmhelpers.h" +#include "gen/tollvm.h" + +struct MIPS64TargetABI : TargetABI { + ExplicitByvalRewrite byvalRewrite; + IntegerRewrite integerRewrite; + const bool Is64Bit; + + MIPS64TargetABI(const bool Is64Bit) : Is64Bit(Is64Bit) + { } + + llvm::CallingConv::ID callingConv(LINK l) + { + switch (l) + { + case LINKc: + case LINKcpp: + case LINKpascal: + case LINKwindows: + case LINKd: + case LINKdefault: + return llvm::CallingConv::C; + default: + llvm_unreachable("Unhandled D linkage type."); + } + } + + bool returnInArg(TypeFunction* tf) + { + if (tf->isref) + return false; + + // Return structs and static arrays on the stack. The latter is needed + // because otherwise LLVM tries to actually return the array in a number + // of physical registers, which leads, depending on the target, to + // either horrendous codegen or backend crashes. + Type* rt = tf->next->toBasetype(); + return (rt->ty == Tstruct || rt->ty == Tsarray); + } + + bool passByVal(Type* t) + { + TY ty = t->toBasetype()->ty; + return ty == Tstruct || ty == Tsarray; + } + + void rewriteFunctionType(TypeFunction* tf, IrFuncTy &fty) + { + for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) + { + IrFuncTyArg& arg = **I; + + if (!arg.byref) + rewriteArgument(fty, arg); + } + } + + void rewriteArgument(IrFuncTy& fty, IrFuncTyArg& arg) + { + // FIXME + } + + // Returns true if the D type can be bit-cast to an integer of the same size. + bool canRewriteAsInt(Type* t) + { + const unsigned size = t->size(); + return size == 1 || size == 2 || size == 4 || (Is64Bit && size == 8); + } +}; + +// The public getter for abi.cpp +TargetABI* getMIPS64TargetABI(bool Is64Bit) +{ + return new MIPS64TargetABI(Is64Bit); +} diff --git a/gen/abi-mips64.h b/gen/abi-mips64.h new file mode 100644 index 00000000000..43bffb7e504 --- /dev/null +++ b/gen/abi-mips64.h @@ -0,0 +1,21 @@ +//===-- gen/abi-mips64.h - MIPS64 ABI description --------------*- C++ -*-===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// +// +// The ABI implementation used for 64 bit MIPS targets. +// +//===----------------------------------------------------------------------===// + +#ifndef LDC_GEN_ABI_MIPS64_H +#define LDC_GEN_ABI_MIPS64_H + +struct TargetABI; + +TargetABI* getMIPS64TargetABI(bool Is64Bit); + +#endif diff --git a/gen/abi.cpp b/gen/abi.cpp index 2a854f9ef7b..395e96fabc3 100644 --- a/gen/abi.cpp +++ b/gen/abi.cpp @@ -10,6 +10,7 @@ #include "gen/abi.h" #include "mars.h" #include "gen/abi-generic.h" +#include "gen/abi-mips64.h" #include "gen/abi-ppc64.h" #include "gen/abi-win64.h" #include "gen/abi-x86-64.h" @@ -196,6 +197,11 @@ TargetABI * TargetABI::getTarget() return getWin64TargetABI(); else return getX86_64TargetABI(); + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + return getMIPS64TargetABI(global.params.is64bit); case llvm::Triple::ppc64: #if LDC_LLVM_VER >= 305 case llvm::Triple::ppc64le: From 8d0fada2c2b4e7778f3eb53c26df7ed13258433e Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 22 May 2015 21:25:14 +0200 Subject: [PATCH 057/101] LLVM 3.7: The signature of CreateCall() has changed. The method now takes an array with the argument values. --- gen/functions.cpp | 4 ++++ gen/module.cpp | 6 +++++- gen/toir.cpp | 4 ++++ gen/tollvm.cpp | 4 ++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/gen/functions.cpp b/gen/functions.cpp index 2451a9cd2cd..88cd8d15848 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -926,7 +926,11 @@ void DtoDefineFunction(FuncDeclaration* fd) { // emit a call to llvm_eh_unwind_init LLFunction* hack = GET_INTRINSIC_DECL(eh_unwind_init); +#if LDC_LLVM_VER >= 307 + gIR->ir->CreateCall(hack, {}); +#else gIR->ir->CreateCall(hack, ""); +#endif } // give the 'this' argument storage and debug info diff --git a/gen/module.cpp b/gen/module.cpp index 390f40a739f..286ed4d3eb9 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -209,7 +209,11 @@ static llvm::Function* build_module_function(const std::string &name, const std: typedef std::list::const_iterator FuncIterator; for (FuncIterator itr = funcs.begin(), end = funcs.end(); itr != end; ++itr) { llvm::Function* f = getIrFunc(*itr)->func; - llvm::CallInst* call = builder.CreateCall(f,""); +#if LDC_LLVM_VER >= 307 + llvm::CallInst* call = builder.CreateCall(f, {}); +#else + llvm::CallInst* call = builder.CreateCall(f, ""); +#endif call->setCallingConv(gABI->callingConv(LINKd)); } diff --git a/gen/toir.cpp b/gen/toir.cpp index a90b54c8ae8..4fc678f70e0 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2262,7 +2262,11 @@ class ToElemVisitor : public Visitor IF_LOG Logger::print("HaltExp::toElem: %s\n", e->toChars()); LOG_SCOPE; +#if LDC_LLVM_VER >= 307 + p->ir->CreateCall(GET_INTRINSIC_DECL(trap), {}); +#else p->ir->CreateCall(GET_INTRINSIC_DECL(trap), ""); +#endif p->ir->CreateUnreachable(); // this terminated the basicblock, start a new one diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 41ec5f8a017..75d4ddc4d42 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -420,7 +420,11 @@ LLValue* DtoMemCmp(LLValue* lhs, LLValue* rhs, LLValue* nbytes) lhs = DtoBitCast(lhs, VoidPtrTy); rhs = DtoBitCast(rhs, VoidPtrTy); +#if LDC_LLVM_VER >= 307 + return gIR->ir->CreateCall(fn, { lhs, rhs, nbytes }); +#else return gIR->ir->CreateCall3(fn, lhs, rhs, nbytes); +#endif } ////////////////////////////////////////////////////////////////////////////////////////// From f1c3c3a81febdaaea82728d0f0602aeb638ed6b4 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 22 May 2015 21:42:41 +0200 Subject: [PATCH 058/101] LLVM 3.7: Add new component mir --- CMakeLists.txt | 2 +- cmake/Modules/FindLLVM.cmake | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7444f5bc2e..65228dd2358 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ include(CheckCXXCompilerFlag) # find_package(LLVM 3.1 REQUIRED - all-targets analysis asmparser asmprinter bitreader bitwriter codegen core debuginfodwarf instcombine ipa ipo instrumentation linker lto mc mcdisassembler mcparser objcarcopts object option profiledata scalaropts selectiondag support tablegen target transformutils vectorize ${EXTRA_LLVM_MODULES}) + all-targets analysis asmparser asmprinter bitreader bitwriter codegen core debuginfodwarf instcombine ipa ipo instrumentation linker lto mc mcdisassembler mcparser mir objcarcopts object option profiledata scalaropts selectiondag support tablegen target transformutils vectorize ${EXTRA_LLVM_MODULES}) math(EXPR LDC_LLVM_VER ${LLVM_VERSION_MAJOR}*100+${LLVM_VERSION_MINOR}) # diff --git a/cmake/Modules/FindLLVM.cmake b/cmake/Modules/FindLLVM.cmake index 2ad80fe87ff..22adcad9448 100644 --- a/cmake/Modules/FindLLVM.cmake +++ b/cmake/Modules/FindLLVM.cmake @@ -78,9 +78,10 @@ if ((WIN32 AND NOT(MINGW OR CYGWIN)) OR NOT LLVM_CONFIG) list(REMOVE_ITEM LLVM_FIND_COMPONENTS "profiledata" index) endif() if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-6][\\.0-9A-Za-z]*") - # Versions below 3.7 do not support components debuginfodwarf + # Versions below 3.7 do not support components debuginfodwarf, mir # Only debuginfo is available list(REMOVE_ITEM LLVM_FIND_COMPONENTS "debuginfodwarf" index) + list(REMOVE_ITEM LLVM_FIND_COMPONENTS "mir" index) list(APPEND LLVM_FIND_COMPONENTS "debuginfo") endif() @@ -158,9 +159,10 @@ else() list(REMOVE_ITEM LLVM_FIND_COMPONENTS "profiledata" index) endif() if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-6][\\.0-9A-Za-z]*") - # Versions below 3.7 do not support components debuginfodwarf + # Versions below 3.7 do not support components debuginfodwarf, mir # Only debuginfo is available list(REMOVE_ITEM LLVM_FIND_COMPONENTS "debuginfodwarf" index) + list(REMOVE_ITEM LLVM_FIND_COMPONENTS "mir" index) list(APPEND LLVM_FIND_COMPONENTS "debuginfo") endif() From f104af446278589af55ad7c8a6ac6f972cd81e55 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 23 May 2015 02:10:15 +0200 Subject: [PATCH 059/101] Revert "LLVM 3.7: Add new component mir" This reverts commit f1c3c3a81febdaaea82728d0f0602aeb638ed6b4. The LLVM commit was reverted. --- CMakeLists.txt | 2 +- cmake/Modules/FindLLVM.cmake | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65228dd2358..f7444f5bc2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ include(CheckCXXCompilerFlag) # find_package(LLVM 3.1 REQUIRED - all-targets analysis asmparser asmprinter bitreader bitwriter codegen core debuginfodwarf instcombine ipa ipo instrumentation linker lto mc mcdisassembler mcparser mir objcarcopts object option profiledata scalaropts selectiondag support tablegen target transformutils vectorize ${EXTRA_LLVM_MODULES}) + all-targets analysis asmparser asmprinter bitreader bitwriter codegen core debuginfodwarf instcombine ipa ipo instrumentation linker lto mc mcdisassembler mcparser objcarcopts object option profiledata scalaropts selectiondag support tablegen target transformutils vectorize ${EXTRA_LLVM_MODULES}) math(EXPR LDC_LLVM_VER ${LLVM_VERSION_MAJOR}*100+${LLVM_VERSION_MINOR}) # diff --git a/cmake/Modules/FindLLVM.cmake b/cmake/Modules/FindLLVM.cmake index 22adcad9448..2ad80fe87ff 100644 --- a/cmake/Modules/FindLLVM.cmake +++ b/cmake/Modules/FindLLVM.cmake @@ -78,10 +78,9 @@ if ((WIN32 AND NOT(MINGW OR CYGWIN)) OR NOT LLVM_CONFIG) list(REMOVE_ITEM LLVM_FIND_COMPONENTS "profiledata" index) endif() if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-6][\\.0-9A-Za-z]*") - # Versions below 3.7 do not support components debuginfodwarf, mir + # Versions below 3.7 do not support components debuginfodwarf # Only debuginfo is available list(REMOVE_ITEM LLVM_FIND_COMPONENTS "debuginfodwarf" index) - list(REMOVE_ITEM LLVM_FIND_COMPONENTS "mir" index) list(APPEND LLVM_FIND_COMPONENTS "debuginfo") endif() @@ -159,10 +158,9 @@ else() list(REMOVE_ITEM LLVM_FIND_COMPONENTS "profiledata" index) endif() if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-6][\\.0-9A-Za-z]*") - # Versions below 3.7 do not support components debuginfodwarf, mir + # Versions below 3.7 do not support components debuginfodwarf # Only debuginfo is available list(REMOVE_ITEM LLVM_FIND_COMPONENTS "debuginfodwarf" index) - list(REMOVE_ITEM LLVM_FIND_COMPONENTS "mir" index) list(APPEND LLVM_FIND_COMPONENTS "debuginfo") endif() From f1c4cf92ff4d35648e825037edb1282b9ea27368 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 23 May 2015 22:12:10 +0200 Subject: [PATCH 060/101] Possible fix for issue #938. The functions for all arrayops are compiler-generated but the functions which are also defined in druntime are never emitted. This prevents inlining of the function body and causes issue #938. The fix is to emit the arrayops if inlining is enabled and otherwise use the druntime provided implementations. An alternative approach could be to always emit the arrayops and never use the druntime version. --- gen/dibuilder.cpp | 3 ++- gen/functions.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 018fffe4cac..1693e4a02ee 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -13,6 +13,7 @@ #include "gen/llvmhelpers.h" #include "gen/logger.h" #include "gen/tollvm.h" +#include "gen/optimizer.h" #include "ir/irtypeaggr.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/FileSystem.h" @@ -42,7 +43,7 @@ Module *ldc::DIBuilder::getDefinedModule(Dsymbol *s) // array operations as well else if (FuncDeclaration* fd = s->isFuncDeclaration()) { - if (fd->isArrayOp && !isDruntimeArrayOp(fd)) + if (fd->isArrayOp && (willInline() || !isDruntimeArrayOp(fd))) return IR->dmodule; } // otherwise use the symbol's module diff --git a/gen/functions.cpp b/gen/functions.cpp index 88cd8d15848..0f70d8b29ea 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -733,7 +733,7 @@ static llvm::GlobalValue::LinkageTypes lowerFuncLinkage(FuncDeclaration* fdecl) // Generated array op functions behave like templates in that they might be // emitted into many different modules. - if (fdecl->isArrayOp && !isDruntimeArrayOp(fdecl)) + if (fdecl->isArrayOp && (willInline() || !isDruntimeArrayOp(fdecl))) return templateLinkage; // A body-less declaration always needs to be marked as external in LLVM @@ -782,7 +782,7 @@ void DtoDefineFunction(FuncDeclaration* fd) } // Skip array ops implemented in druntime - if (fd->isArrayOp && isDruntimeArrayOp(fd)) + if (fd->isArrayOp && !willInline() && isDruntimeArrayOp(fd)) { IF_LOG Logger::println("No code generation for array op %s implemented in druntime", fd->toChars()); fd->ir.setDefined(); From ca8e4bfe573aaf96cc6ee51e2ddc8e0fc1eec55b Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 23 May 2015 23:50:50 +0200 Subject: [PATCH 061/101] Druntime: Remove FIXMEs in rt.arrayint --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 5220555dc4c..e70d02f0d97 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 5220555dc4ce0ebd51d26ae783f9cd54f792335f +Subproject commit e70d02f0d9790b60ecfd8e458ee7052ad2aed6d2 From 3291535bcf515957c04b954a9ddf02690f43c58e Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 24 May 2015 14:31:36 +0200 Subject: [PATCH 062/101] Druntime: Use LLVM intrinsics in rt.lifetime. --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index e70d02f0d97..04a8dccf5d7 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit e70d02f0d9790b60ecfd8e458ee7052ad2aed6d2 +Subproject commit 04a8dccf5d7ff4439867ad4b8dedda02acb95a0e From 23318896699d6f86317621a2a49bc39131dad1a7 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 24 May 2015 18:03:45 +0200 Subject: [PATCH 063/101] MIPS: Implement ABI handling. Adds a new command line option -mabi= and uses the value to compute the ABI to use. Adds the ABI to linker and assembler invocation, too. Allows consistent invocation of the whole tool chain. --- driver/cl_options.cpp | 7 ++++ driver/cl_options.h | 3 ++ driver/linker.cpp | 38 +++++++++++++++--- driver/main.cpp | 37 ++++++++---------- driver/targetmachine.cpp | 84 ++++++++++++++++++++++++++++++++++++++++ driver/targetmachine.h | 19 +++++++++ driver/toobj.cpp | 43 +++++++++++++++++--- 7 files changed, 200 insertions(+), 31 deletions(-) diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index 6cd995086d6..6e1f0e9badc 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -308,6 +308,13 @@ cl::list mAttrs("mattr", cl::opt mTargetTriple("mtriple", cl::desc("Override target triple")); +#if LDC_LLVM_VER >= 307 +cl::opt mABI("mabi", + cl::desc("The name of the ABI to be targeted from the backend"), + cl::Hidden, + cl::init("")); +#endif + cl::opt mRelocModel("relocation-model", cl::desc("Relocation model"), cl::init(llvm::Reloc::Default), diff --git a/driver/cl_options.h b/driver/cl_options.h index 6b0c4434c1d..80fc46d33ed 100644 --- a/driver/cl_options.h +++ b/driver/cl_options.h @@ -66,6 +66,9 @@ namespace opts { extern cl::opt mCPU; extern cl::list mAttrs; extern cl::opt mTargetTriple; +#if LDC_LLVM_VER >= 307 + extern cl::opt mABI; +#endif extern cl::opt mRelocModel; extern cl::opt mCodeModel; extern cl::opt disableFpElim; diff --git a/driver/linker.cpp b/driver/linker.cpp index 71752406288..31ef93283ee 100644 --- a/driver/linker.cpp +++ b/driver/linker.cpp @@ -226,13 +226,39 @@ static int linkObjToBinaryGcc(bool sharedLib) // Only specify -m32/-m64 for architectures where the two variants actually // exist (as e.g. the GCC ARM toolchain doesn't recognize the switches). + // MIPS does not have -m32/-m64 but requires -mabi=. if (global.params.targetTriple.get64BitArchVariant().getArch() != - llvm::Triple::UnknownArch - ) { - if (global.params.is64bit) - args.push_back("-m64"); - else - args.push_back("-m32"); + llvm::Triple::UnknownArch && + global.params.targetTriple.get32BitArchVariant().getArch() != + llvm::Triple::UnknownArch) { + if (global.params.targetTriple.get64BitArchVariant().getArch() == + llvm::Triple::mips64 || + global.params.targetTriple.get64BitArchVariant().getArch() == + llvm::Triple::mips64el) { + switch (getMipsABI()) + { + case MipsABI::EABI: + args.push_back("-mabi=eabi"); + break; + case MipsABI::O32: + args.push_back("-mabi=32"); + break; + case MipsABI::N32: + args.push_back("-mabi=n32"); + break; + case MipsABI::N64: + args.push_back("-mabi=64"); + break; + case MipsABI::Unknown: + break; + } + } + else { + if (global.params.is64bit) + args.push_back("-m64"); + else + args.push_back("-m32"); + } } if (opts::createSharedLib && addSoname) { diff --git a/driver/main.cpp b/driver/main.cpp index 74ba896488b..b926af1d944 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -544,26 +544,23 @@ static void initializePasses() { /// Register the MIPS ABI. static void registerMipsABI() { -#if LDC_LLVM_VER >= 307 - // FIXME: EABI? - auto dl = gTargetMachine->getDataLayout(); - if (dl->getPointerSizeInBits() == 64) - VersionCondition::addPredefinedGlobalIdent("MIPS_N64"); - else if (dl->getLargestLegalIntTypeSize() == 64) - VersionCondition::addPredefinedGlobalIdent("MIPS_N32"); - else - VersionCondition::addPredefinedGlobalIdent("MIPS_O32"); -#else - llvm::StringRef features = gTargetMachine->getTargetFeatureString(); - if (features.find("+o32") != std::string::npos) - VersionCondition::addPredefinedGlobalIdent("MIPS_O32"); - if (features.find("+n32") != std::string::npos) - VersionCondition::addPredefinedGlobalIdent("MIPS_N32"); - if (features.find("+n64") != std::string::npos) - VersionCondition::addPredefinedGlobalIdent("MIPS_N64"); - if (features.find("+eabi") != std::string::npos) - VersionCondition::addPredefinedGlobalIdent("MIPS_EABI"); -#endif + switch (getMipsABI()) + { + case MipsABI::EABI: + VersionCondition::addPredefinedGlobalIdent("MIPS_EABI"); + break; + case MipsABI::O32: + VersionCondition::addPredefinedGlobalIdent("MIPS_O32"); + break; + case MipsABI::N32: + VersionCondition::addPredefinedGlobalIdent("MIPS_N32"); + break; + case MipsABI::N64: + VersionCondition::addPredefinedGlobalIdent("MIPS_N64"); + break; + case MipsABI::Unknown: + break; + } } /// Register the float ABI. diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp index d12bbc32d59..cf0732e11ee 100644 --- a/driver/targetmachine.cpp +++ b/driver/targetmachine.cpp @@ -26,6 +26,87 @@ #include "mars.h" #include "gen/logger.h" +#if LDC_LLVM_VER >= 307 +#include "driver/cl_options.h" + +static const llvm::StringRef getABI(const llvm::Triple &triple) +{ + llvm::StringRef ABIName(opts::mABI); + if (ABIName != "") + { + switch (triple.getArch()) + { + case llvm::Triple::arm: + case llvm::Triple::armeb: + if (ABIName.startswith("aapcs")) return "aapcs"; + if (ABIName.startswith("eabi")) return "apcs"; + break; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + if (ABIName.startswith("o32")) return "o32"; + if (ABIName.startswith("n32")) return "n32"; + if (ABIName.startswith("n64")) return "n64"; + if (ABIName.startswith("eabi")) return "eabi"; + break; + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + if (ABIName.startswith("elfv1")) return "elfv1"; + if (ABIName.startswith("elfv2")) return "elfv2"; + break; + default: + break; + } + warning(Loc(), "Unknown ABI %s - using default ABI instead", ABIName.str().c_str()); + } + + switch (triple.getArch()) + { + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + return "n32"; + case llvm::Triple::ppc64: + return "elfv1"; + case llvm::Triple::ppc64le: + return "elfv2"; + default: + return 0; + } +} +#endif + +extern llvm::TargetMachine* gTargetMachine; + +MipsABI::Type getMipsABI() +{ +#if LDC_LLVM_VER >= 307 + // eabi can only be set on the commandline + if (strncmp(opts::mABI.c_str(), "eabi", 4) == 0) + return MipsABI::EABI; + else + { + auto dl = gTargetMachine->getDataLayout(); + if (dl->getPointerSizeInBits() == 64) + return MipsABI::N64; + else if (dl->getLargestLegalIntTypeSize() == 64) + return MipsABI::N32; + else + return MipsABI::O32; + } +#else + llvm::StringRef features = gTargetMachine->getTargetFeatureString(); + if (features.find("+o32") != std::string::npos) + return MipsABI::O32; + if (features.find("+n32") != std::string::npos) + return MipsABI::N32; + if (features.find("+n64") != std::string::npos) + return MipsABI::N32; + if (features.find("+eabi") != std::string::npos) + return MipsABI::EABI; + return MipsABI::Unknown; +#endif +} static std::string getX86TargetCPU(const llvm::Triple &triple) { @@ -424,6 +505,9 @@ llvm::TargetMachine* createTargetMachine( llvm::TargetOptions targetOptions; targetOptions.NoFramePointerElim = noFramePointerElim; +#if LDC_LLVM_VER >= 307 + targetOptions.MCOptions.ABIName = getABI(triple); +#endif switch (floatABI) { diff --git a/driver/targetmachine.h b/driver/targetmachine.h index a49469aace9..d33deb1116f 100644 --- a/driver/targetmachine.h +++ b/driver/targetmachine.h @@ -36,6 +36,16 @@ namespace FloatABI { }; } +namespace MipsABI { + enum Type { + Unknown, + O32, + N32, + N64, + EABI + }; +} + namespace llvm { class TargetMachine; } /** @@ -58,4 +68,13 @@ llvm::TargetMachine* createTargetMachine( bool noLinkerStripDead ); +/** + * Returns the Mips ABI which is used for code generation. + * + * Function may only be called after the target machine is created. + * Returns MipsABI::Unknown in case the ABI is not known (e.g. not compiling + * for Mips). + */ +MipsABI::Type getMipsABI(); + #endif // LDC_DRIVER_TARGET_H diff --git a/driver/toobj.cpp b/driver/toobj.cpp index 6c7a8e86b73..e66e75fb391 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "driver/toobj.h" +#include "driver/targetmachine.h" #include "driver/tool.h" #include "gen/irstate.h" #include "gen/logger.h" @@ -130,15 +131,47 @@ static void assemble(const std::string &asmpath, const std::string &objpath) std::vector args; args.push_back("-O3"); args.push_back("-c"); - args.push_back("-xassembler"); + args.push_back("-x assembler"); args.push_back(asmpath); args.push_back("-o"); args.push_back(objpath); - if (global.params.is64bit) - args.push_back("-m64"); - else - args.push_back("-m32"); + // Only specify -m32/-m64 for architectures where the two variants actually + // exist (as e.g. the GCC ARM toolchain doesn't recognize the switches). + // MIPS does not have -m32/-m64 but requires -mabi=. + if (global.params.targetTriple.get64BitArchVariant().getArch() != + llvm::Triple::UnknownArch && + global.params.targetTriple.get32BitArchVariant().getArch() != + llvm::Triple::UnknownArch) { + if (global.params.targetTriple.get64BitArchVariant().getArch() == + llvm::Triple::mips64 || + global.params.targetTriple.get64BitArchVariant().getArch() == + llvm::Triple::mips64el) { + switch (getMipsABI()) + { + case MipsABI::EABI: + args.push_back("-mabi=eabi"); + break; + case MipsABI::O32: + args.push_back("-mabi=32"); + break; + case MipsABI::N32: + args.push_back("-mabi=n32"); + break; + case MipsABI::N64: + args.push_back("-mabi=64"); + break; + case MipsABI::Unknown: + break; + } + } + else { + if (global.params.is64bit) + args.push_back("-m64"); + else + args.push_back("-m32"); + } + } // Run the compiler to assembly the program. std::string gcc(getGcc()); From 90f7debeb2349fb4a5d1cd89d9796156e4a82a9d Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 24 May 2015 19:42:59 +0200 Subject: [PATCH 064/101] Remove a wrong space in argument. --- driver/toobj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/toobj.cpp b/driver/toobj.cpp index e66e75fb391..f0550a60908 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -131,7 +131,7 @@ static void assemble(const std::string &asmpath, const std::string &objpath) std::vector args; args.push_back("-O3"); args.push_back("-c"); - args.push_back("-x assembler"); + args.push_back("-xassembler"); args.push_back(asmpath); args.push_back("-o"); args.push_back(objpath); From 2d9e66de66eea832234a72bed18b539a3728ba43 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Mon, 25 May 2015 16:20:48 +0200 Subject: [PATCH 065/101] Fix assertion in getABI(). --- driver/targetmachine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp index cf0732e11ee..144c2d8a212 100644 --- a/driver/targetmachine.cpp +++ b/driver/targetmachine.cpp @@ -29,7 +29,7 @@ #if LDC_LLVM_VER >= 307 #include "driver/cl_options.h" -static const llvm::StringRef getABI(const llvm::Triple &triple) +static const char* getABI(const llvm::Triple &triple) { llvm::StringRef ABIName(opts::mABI); if (ABIName != "") @@ -71,7 +71,7 @@ static const llvm::StringRef getABI(const llvm::Triple &triple) case llvm::Triple::ppc64le: return "elfv2"; default: - return 0; + return ""; } } #endif From bb32dcd6decabc31cb4319ea35734026ec192f97 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Mon, 25 May 2015 22:54:56 +0200 Subject: [PATCH 066/101] Add new hidden option -no-integrated-as. This is useful if the integrated assembler causes problems. Also adds an architecture to the assembler command line in case of compiling for MIPS. --- driver/toobj.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/driver/toobj.cpp b/driver/toobj.cpp index f0550a60908..e83d9317707 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -67,6 +67,10 @@ enum OpenFlags { } #endif +static llvm::cl::opt +NoIntegratedAssembler("no-integrated-as", llvm::cl::Hidden, + llvm::cl::desc("Disable integrated assembler")); + // based on llc code, University of Illinois Open Source License static void codegenModule(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out, llvm::TargetMachine::CodeGenFileType fileType) @@ -151,15 +155,19 @@ static void assemble(const std::string &asmpath, const std::string &objpath) { case MipsABI::EABI: args.push_back("-mabi=eabi"); + args.push_back("-march=mips32r2"); break; case MipsABI::O32: args.push_back("-mabi=32"); + args.push_back("-march=mips32r2"); break; case MipsABI::N32: args.push_back("-mabi=n32"); + args.push_back("-march=mips64r2"); break; case MipsABI::N64: args.push_back("-mabi=64"); + args.push_back("-march=mips64r2"); break; case MipsABI::Unknown: break; @@ -389,13 +397,15 @@ void writeModule(llvm::Module* m, std::string filename) // There is no integrated assembler on AIX because XCOFF is not supported. // Starting with LLVM 3.5 the integrated assembler can be used with MinGW. bool const assembleExternally = global.params.output_o && - global.params.targetTriple.getOS() == llvm::Triple::AIX; + (NoIntegratedAssembler || + global.params.targetTriple.getOS() == llvm::Triple::AIX); #else // (We require LLVM 3.5 with AIX.) // We don't use the integrated assembler with MinGW as it does not support // emitting DW2 exception handling tables. bool const assembleExternally = global.params.output_o && - global.params.targetTriple.getOS() == llvm::Triple::MinGW32; + (NoIntegratedAssembler || + global.params.targetTriple.getOS() == llvm::Triple::MinGW32); #endif // eventually do our own path stuff, dmd's is a bit strange. From 084ae9da5b76994182f773a5360cbff51d8c0747 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 29 May 2015 00:53:58 +0200 Subject: [PATCH 067/101] Remove extra load on assignment generated only for debug info This leads to serious problems for values we really should not be loading from, such as 100k element static arrays. It was hard to figure out exactly why we need to emit DWARF info here, so the easiest solution is to just have a look at assignments during the next big debug info push. --- gen/llvmhelpers.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index c536d64fd49..0334b7dec4c 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -460,11 +460,6 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op, bool canSkipPostblit) } gIR->ir->CreateStore(r, l); } - - DVarValue *var = lhs->isVar(); - VarDeclaration *vd = var ? var->var : 0; - if (vd) - gIR->DBuilder.EmitValue(DtoLoad(var->getLVal()), vd); } /****************************************************************************************/ From c65faeabafb8f8e8da9ed34bc75e917c6b75edb4 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 29 May 2015 00:22:21 +0200 Subject: [PATCH 068/101] Fix struct alignment padding type selection GitHub: Fixes #944. --- ir/irtypeaggr.cpp | 2 +- tests/d2/dmd-testsuite | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ir/irtypeaggr.cpp b/ir/irtypeaggr.cpp index f8d0ca0d0b5..2c5f0f1fd09 100644 --- a/ir/irtypeaggr.cpp +++ b/ir/irtypeaggr.cpp @@ -27,7 +27,7 @@ static bool isAligned(llvm::Type* type, size_t offset) { - return gDataLayout->getABITypeAlignment(type) % offset == 0; + return (offset % gDataLayout->getABITypeAlignment(type)) == 0; } size_t add_zeros(std::vector& defaultTypes, diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 627b3a7aba4..6e19a33c1eb 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 627b3a7aba4b7511e800f3384ed2f75b20c2ec4c +Subproject commit 6e19a33c1eba44443c175faa55f9750c32768e20 From 3abe023e3e2048bb698431bfe3784eea454c151a Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 29 May 2015 17:55:37 +0200 Subject: [PATCH 069/101] Fold in llvm_expect constraint update --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 04a8dccf5d7..7acf1cf415d 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 04a8dccf5d7ff4439867ad4b8dedda02acb95a0e +Subproject commit 7acf1cf415dd99b53949f696e1f390df8d10ff57 From 568bf3723bc30d2ed12cf26265cd2bc524760085 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 29 May 2015 21:49:22 +0200 Subject: [PATCH 070/101] DtoSymbolAddress: Remove support for unused ClassInfoDeclaration It will be gone in 2.068. --- dmd2/declaration.h | 1 - dmd2/dsymbol.h | 2 -- gen/llvmhelpers.cpp | 7 ------- 3 files changed, 10 deletions(-) diff --git a/dmd2/declaration.h b/dmd2/declaration.h index 4ad24f62971..3c4f81aad0f 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -361,7 +361,6 @@ class ClassInfoDeclaration : public VarDeclaration Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); - ClassInfoDeclaration* isClassInfoDeclaration() { return this; } void accept(Visitor *v) { v->visit(this); } }; diff --git a/dmd2/dsymbol.h b/dmd2/dsymbol.h index 24b04252201..47ef120ead8 100644 --- a/dmd2/dsymbol.h +++ b/dmd2/dsymbol.h @@ -304,8 +304,6 @@ class Dsymbol : public RootObject virtual OverloadSet *isOverloadSet() { return NULL; } virtual void accept(Visitor *v) { v->visit(this); } #if IN_LLVM - virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; } - // llvm stuff int llvmInternal; diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 0334b7dec4c..dd88ee60a33 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1713,13 +1713,6 @@ DValue* DtoSymbolAddress(Loc& loc, Type* type, Declaration* decl) val = DtoArrayLen(gIR->arrays.back()); return new DImValue(type, val); } - // classinfo - else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration()) - { - Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars()); - DtoResolveClass(cid->cd); - return new DVarValue(type, vd, getIrAggr(cid->cd)->getClassInfoSymbol()); - } // typeinfo else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) { From 0a8dd808503e1f64ddef7964685a009f4167e0e1 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 31 May 2015 17:51:52 +0200 Subject: [PATCH 071/101] Do not search for destructors inside assert expression if assertions are turned off. Otherwise there is the possibility that temporaries are found and we try to call the destructor on them. This fixes issue #953. --- gen/toir.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 4fc678f70e0..4e8573d9ab4 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2067,7 +2067,7 @@ class ToElemVisitor : public Visitor // call assert runtime functions p->scope() = IRScope(assertbb, endbb); - /* DMD Bugzilla 8360: If the condition is evalated to true, + /* DMD Bugzilla 8360: If the condition is evaluated to true, * msg is not evaluated at all. So should use toElemDtor() * instead of toElem(). */ @@ -3198,7 +3198,12 @@ class SearchVarsWithDestructors : public Visitor virtual void visit(AssertExp *e) { - applyTo(e->e1); + // If assertions are turned off e.g. in release mode then + // the expression is ignored. Only search for destructors + // inside the assert expression if assertions are turned on. + // See GitHub issue #953. + if (global.params.useAssert) + applyTo(e->e1); // same as above // applyTo(e->msg); } From c5ec63c3ff62453ffd3a0246f920a6eb100f5eae Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 31 May 2015 20:32:20 +0200 Subject: [PATCH 072/101] Add testcase for issue #821. --- tests/d2/dmd-testsuite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 6e19a33c1eb..6840ecd43bc 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 6e19a33c1eba44443c175faa55f9750c32768e20 +Subproject commit 6840ecd43bc50afdcfcd4a2b2b7ce8686a70fb7a From 9d3dd1f609e08f001aeec2cacb1c55707f37884b Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 31 May 2015 21:32:12 +0200 Subject: [PATCH 073/101] Add true value of "isOptimized" to Dwarf debug info. --- gen/dibuilder.cpp | 6 +++--- gen/optimizer.cpp | 4 ++++ gen/optimizer.h | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 1693e4a02ee..d360583f578 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -669,7 +669,7 @@ void ldc::DIBuilder::EmitCompileUnit(Module *m) llvm::sys::path::filename(srcpath), llvm::sys::path::parent_path(srcpath), "LDC (http://wiki.dlang.org/LDC)", - false, // isOptimized TODO + isOptimizationEnabled(), // isOptimized llvm::StringRef(), // Flags TODO 1 // Runtime Version TODO ); @@ -710,7 +710,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) IR->dmodule == getDefinedModule(fd), // isdefinition fd->loc.linnum, // FIXME: scope line 0, // Flags - false, // isOptimized + isOptimizationEnabled(), // isOptimized getIrFunc(fd)->func ); } @@ -761,7 +761,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function* Fn, true, // is local to unit true, // isdefinition 0, // FIXME: scope line - false, // FIXME: isOptimized + isOptimizationEnabled(), // isOptimized Fn ); } diff --git a/gen/optimizer.cpp b/gen/optimizer.cpp index 1069042a4d8..ef2ea637166 100644 --- a/gen/optimizer.cpp +++ b/gen/optimizer.cpp @@ -167,6 +167,10 @@ bool willInline() { (enableInlining == cl::BOU_UNSET && optLevel() > 1); } +bool isOptimizationEnabled() { + return optimizeLevel != 0; +} + llvm::CodeGenOpt::Level codeGenOptLevel() { const int opt = optLevel(); // Use same appoach as clang (see lib/CodeGen/BackendUtil.cpp) diff --git a/gen/optimizer.h b/gen/optimizer.h index 784aaa5469f..dacefca1dfc 100644 --- a/gen/optimizer.h +++ b/gen/optimizer.h @@ -36,7 +36,7 @@ bool ldc_optimize_module(llvm::Module* m); // Returns whether the normal, full inlining pass will be run. bool willInline(); -bool optimize(); +bool isOptimizationEnabled(); llvm::CodeGenOpt::Level codeGenOptLevel(); From 34e6acaaf808539f696f54309d798eeeeecabb3b Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Wed, 3 Jun 2015 23:01:02 +0200 Subject: [PATCH 074/101] ARM: Fix FPSCR bits and resetIeeeFlags() handling. --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index 91c43e0af80..a2d4c542330 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 91c43e0af80e7b89e7e320a8492648dbc82a0aa4 +Subproject commit a2d4c542330e281bf03c70f5a6c34abadb594cfd From 67dd76faf7995c0e0cefb79211c39d383b2490df Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 14:04:50 +0200 Subject: [PATCH 075/101] LLVM 3.7: ListInit.getSize() was renamed to ListInit.size(). This is in TableGen only and affects the gen_gccbuiltins utility. --- utils/gen_gccbuiltins.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/utils/gen_gccbuiltins.cpp b/utils/gen_gccbuiltins.cpp index 36e29bdeb30..0491df96e69 100644 --- a/utils/gen_gccbuiltins.cpp +++ b/utils/gen_gccbuiltins.cpp @@ -85,8 +85,13 @@ string dtype(Record* rec) string attributes(ListInit* propertyList) { - string prop = propertyList->getSize() ? - propertyList->getElementAsRecord(0)->getName() : ""; + string prop = +#if LDC_LLVM_VER >= 307 + propertyList->size() +#else + propertyList->getSize() +#endif + ? propertyList->getElementAsRecord(0)->getName() : ""; return prop == "IntrNoMem" ? "nothrow pure @safe" : @@ -111,7 +116,13 @@ void processRecord(raw_ostream& os, Record& rec, string arch) ListInit* paramsList = rec.getValueAsListInit("ParamTypes"); vector params; - for(unsigned int i = 0; i < paramsList->getSize(); i++) + for(unsigned int i = 0; i < +#if LDC_LLVM_VER >= 307 + paramsList->size(); +#else + paramsList->getSize(); +#endif + i++) { string t = dtype(paramsList->getElementAsRecord(i)); if(t == "") @@ -122,9 +133,14 @@ void processRecord(raw_ostream& os, Record& rec, string arch) ListInit* retList = rec.getValueAsListInit("RetTypes"); string ret; - if(retList->getSize() == 0) +#if LDC_LLVM_VER >= 307 + size_t sz = retList->size(); +#else + size_t sz = retList->getSize(); +#endif + if(sz == 0) ret = "void"; - else if(retList->getSize() == 1) + else if(sz == 1) { ret = dtype(retList->getElementAsRecord(0)); if(ret == "") From f67186592a39f47dcdb63138f84ea1afc684cce8 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 15:07:02 +0200 Subject: [PATCH 076/101] LLVM 3.7: NoFramePointerElim is now an attribute. Temporary workaround to enable Travis-CI. --- driver/targetmachine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp index 144c2d8a212..28f618ba957 100644 --- a/driver/targetmachine.cpp +++ b/driver/targetmachine.cpp @@ -504,7 +504,9 @@ llvm::TargetMachine* createTargetMachine( #endif llvm::TargetOptions targetOptions; +#if LDC_LLVM_VER < 307 targetOptions.NoFramePointerElim = noFramePointerElim; +#endif #if LDC_LLVM_VER >= 307 targetOptions.MCOptions.ABIName = getABI(triple); #endif From 15b1ee1576f5dd9198c39a5e6139dbe4aaa3e263 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 15:09:29 +0200 Subject: [PATCH 077/101] DebugInfo: Output the underlying delegate for lazy parameters. This fixes issue #959. --- gen/dibuilder.cpp | 10 ++++++---- gen/dibuilder.h | 4 ++++ gen/functions.cpp | 7 ++++--- gen/nested.cpp | 4 ++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index d360583f578..ab67b8328a1 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -856,10 +856,11 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) } void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, + Type *type, bool isArtificial, #if LDC_LLVM_VER >= 306 - llvm::ArrayRef addr + llvm::ArrayRef addr #else - llvm::ArrayRef addr + llvm::ArrayRef addr #endif ) { @@ -875,7 +876,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, return; // ensure that the debug variable is created only once // get type description - ldc::DIType TD = CreateTypeDescription(vd->type, true); + ldc::DIType TD = CreateTypeDescription(type ? type : vd->type, true); if (static_cast(TD) == 0) return; // unsupported @@ -900,7 +901,8 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, CreateFile(vd->loc), // file vd->loc.linnum, // line num TD, // type - true // preserve + true, // preserve + isArtificial ? llvm::dwarf::DW_AT_artificial : 0 ); #if LDC_LLVM_VER < 306 } diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 40e26ab2b47..428766c5256 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -165,8 +165,12 @@ class DIBuilder /// \brief 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. + /// \param type Type of parameter if diferent from vd->type + /// \param isArtificial Parameter is artificial, e.g. this /// \param addr An array of complex address operations. void EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, + Type *type = 0, + bool isArtificial = false, #if LDC_LLVM_VER >= 306 llvm::ArrayRef addr = llvm::ArrayRef() #else diff --git a/gen/functions.cpp b/gen/functions.cpp index 0f70d8b29ea..44dd32ef25e 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -950,7 +950,7 @@ void DtoDefineFunction(FuncDeclaration* fd) assert(getIrParameter(fd->vthis)->value == thisvar); getIrParameter(fd->vthis)->value = thismem; - gIR->DBuilder.EmitLocalVariable(thismem, fd->vthis); + gIR->DBuilder.EmitLocalVariable(thismem, fd->vthis, 0, true); } // give the 'nestArg' storage @@ -979,7 +979,8 @@ void DtoDefineFunction(FuncDeclaration* fd) bool refout = vd->storage_class & (STCref | STCout); bool lazy = vd->storage_class & STClazy; - if (!refout && (!irparam->arg->byref || lazy)) + bool firstClassVal = !refout && (!irparam->arg->byref || lazy); + if (firstClassVal) { // alloca a stack slot for this first class value arg LLValue* mem = DtoAlloca(irparam->arg->type, vd->ident->toChars()); @@ -993,7 +994,7 @@ void DtoDefineFunction(FuncDeclaration* fd) } if (global.params.symdebug && !(isaArgument(irparam->value) && isaArgument(irparam->value)->hasByValAttr()) && !refout) - gIR->DBuilder.EmitLocalVariable(irparam->value, vd); + gIR->DBuilder.EmitLocalVariable(irparam->value, vd, firstClassVal ? irparam->arg->type : 0); } } diff --git a/gen/nested.cpp b/gen/nested.cpp index df93e2d89c1..b1e2db7acae 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -169,7 +169,7 @@ DValue* DtoNestedVariable(Loc& loc, Type* astype, VarDeclaration* vd, bool byref } if (dwarfValue && global.params.symdebug) - gIR->DBuilder.EmitLocalVariable(dwarfValue, vd, dwarfAddr); + gIR->DBuilder.EmitLocalVariable(dwarfValue, vd, 0, false, dwarfAddr); return new DVarValue(astype, vd, val); } @@ -507,7 +507,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { LLSmallVector addr; #endif gIR->DBuilder.OpOffset(addr, frameType, irLocal->nestedIndex); - gIR->DBuilder.EmitLocalVariable(frame, vd, addr); + gIR->DBuilder.EmitLocalVariable(frame, vd, 0, false, addr); } } } From 816ecf5502323444efd4e433dd076cee88921415 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 16:23:22 +0200 Subject: [PATCH 078/101] DebugInfo: At a stop point at end of function. --- gen/dibuilder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index ab67b8328a1..a0b1ffbe333 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -787,6 +787,7 @@ void ldc::DIBuilder::EmitFuncEnd(FuncDeclaration *fd) LOG_SCOPE; assert(static_cast(getIrFunc(fd)->diSubprogram) != 0); + EmitStopPoint(fd->endloc.linnum); } void ldc::DIBuilder::EmitBlockStart(Loc& loc) From 3b363a1b086b9c8794d51e6d6022bf773374b869 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 18:00:24 +0200 Subject: [PATCH 079/101] DebugInfo: Add more flags and other refinements. In D all functions are prototyped. Mark the hidden this pointer with flag ObjectPointer. Also add a column for a lexical block start. --- gen/dibuilder.cpp | 32 +++++++++++++++++++++----------- gen/dibuilder.h | 4 ++-- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index a0b1ffbe333..8bde90b9619 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -25,9 +25,9 @@ //////////////////////////////////////////////////////////////////////////////// #if LDC_LLVM_VER >= 307 -typedef llvm::DINode Access; +typedef llvm::DINode DIFlags; #else -typedef llvm::DIDescriptor Access; +typedef llvm::DIDescriptor DIFlags; #endif //////////////////////////////////////////////////////////////////////////////// @@ -267,14 +267,14 @@ ldc::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type, unsigned Flags = 0; switch (prot) { case PROTprivate: - Flags = Access::FlagPrivate; + Flags = DIFlags::FlagPrivate; break; case PROTprotected: - Flags = Access::FlagProtected; + Flags = DIFlags::FlagProtected; break; #if LDC_LLVM_VER >= 306 case PROTpublic: - Flags = Access::FlagPublic; + Flags = DIFlags::FlagPublic; break; #endif default: @@ -428,7 +428,7 @@ ldc::DIType ldc::DIBuilder::CreateCompositeType(Type *type) getTypeBitSize(T), // size in bits getABITypeAlign(T)*8, // alignment in bits 0, // offset in bits, - Access::FlagFwdDecl, // flags + DIFlags::FlagFwdDecl, // flags derivedFrom, // DerivedFrom elemsArray ); @@ -440,7 +440,7 @@ ldc::DIType ldc::DIBuilder::CreateCompositeType(Type *type) linnum, // line number where defined getTypeBitSize(T), // size in bits getABITypeAlign(T)*8, // alignment in bits - Access::FlagFwdDecl, // flags + DIFlags::FlagFwdDecl, // flags #if LDC_LLVM_VER >= 303 derivedFrom, // DerivedFrom #endif @@ -709,7 +709,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) fd->protection == PROTprivate, // is local to unit IR->dmodule == getDefinedModule(fd), // isdefinition fd->loc.linnum, // FIXME: scope line - 0, // Flags + DIFlags::FlagPrototyped, // Flags isOptimizationEnabled(), // isOptimized getIrFunc(fd)->func ); @@ -761,6 +761,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function* Fn, true, // is local to unit true, // isdefinition 0, // FIXME: scope line + DIFlags::FlagPrototyped | DIFlags::FlagArtificial, isOptimizationEnabled(), // isOptimized Fn ); @@ -802,7 +803,7 @@ void ldc::DIBuilder::EmitBlockStart(Loc& loc) GetCurrentScope(), // scope CreateFile(loc), // file loc.linnum, // line - 0 // column + loc.charnum // column #if LDC_LLVM_VER == 305 , 0 // DWARF path discriminator value #endif @@ -857,7 +858,7 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) } void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, - Type *type, bool isArtificial, + Type *type, bool isThisPtr, #if LDC_LLVM_VER >= 306 llvm::ArrayRef addr #else @@ -891,6 +892,15 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, tag = llvm::dwarf::DW_TAG_auto_variable; ldc::DILocalVariable debugVariable; + unsigned Flags = 0; + if (isThisPtr) + { +#if LDC_LLVM_VER >= 302 + Flags |= DIFlags::FlagArtificial | DIFlags::FlagObjectPointer; +#else + Flags |= DIFlags::FlagArtificial; +#endif + } #if LDC_LLVM_VER < 306 if (addr.empty()) { @@ -903,7 +913,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, vd->loc.linnum, // line num TD, // type true, // preserve - isArtificial ? llvm::dwarf::DW_AT_artificial : 0 + Flags // flags ); #if LDC_LLVM_VER < 306 } diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 428766c5256..f365bb28bca 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -166,11 +166,11 @@ class DIBuilder /// \param ll LLVM Value of the variable. /// \param vd Variable declaration to emit debug info for. /// \param type Type of parameter if diferent from vd->type - /// \param isArtificial Parameter is artificial, e.g. this + /// \param isThisPtr Parameter is hidden this pointer /// \param addr An array of complex address operations. void EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Type *type = 0, - bool isArtificial = false, + bool isThisPtr = false, #if LDC_LLVM_VER >= 306 llvm::ArrayRef addr = llvm::ArrayRef() #else From c2691280dbc38126eb2eed69a7569fa834ede51c Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 18:25:14 +0200 Subject: [PATCH 080/101] LLVM 3.7: Fix inline IR test. --- tests/d2/dmd-testsuite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 6840ecd43bc..ea3d890be17 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 6840ecd43bc50afdcfcd4a2b2b7ce8686a70fb7a +Subproject commit ea3d890be17aa2e957cb86ca03d6167ade111093 From 0f86de548cba9be342bf42f97609a8e4eec9ff62 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 19:04:23 +0200 Subject: [PATCH 081/101] DebugInfo: EmitStopPoint() now has a Loc parameter. --- gen/asmstmt.cpp | 2 +- gen/dibuilder.cpp | 13 ++++++------- gen/dibuilder.h | 2 +- gen/statements.cpp | 22 +++++++++++----------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index 5d0d8b0b854..dfbffe59a69 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -187,7 +187,7 @@ void AsmStatement_toIR(AsmStatement *stmt, IRState * irs) assert(asmblock); // debug info - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); if (!stmt->asmcode) return; diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 8bde90b9619..0cc17e2f97c 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -776,7 +776,7 @@ void ldc::DIBuilder::EmitFuncStart(FuncDeclaration *fd) LOG_SCOPE; assert(static_cast(getIrFunc(fd)->diSubprogram) != 0); - EmitStopPoint(fd->loc.linnum); + EmitStopPoint(fd->loc); } void ldc::DIBuilder::EmitFuncEnd(FuncDeclaration *fd) @@ -788,7 +788,7 @@ void ldc::DIBuilder::EmitFuncEnd(FuncDeclaration *fd) LOG_SCOPE; assert(static_cast(getIrFunc(fd)->diSubprogram) != 0); - EmitStopPoint(fd->endloc.linnum); + EmitStopPoint(fd->endloc); } void ldc::DIBuilder::EmitBlockStart(Loc& loc) @@ -809,7 +809,7 @@ void ldc::DIBuilder::EmitBlockStart(Loc& loc) #endif ); IR->func()->diLexicalBlocks.push(block); - EmitStopPoint(loc.linnum); + EmitStopPoint(loc); } void ldc::DIBuilder::EmitBlockEnd() @@ -825,15 +825,14 @@ void ldc::DIBuilder::EmitBlockEnd() fn->diLexicalBlocks.pop(); } -void ldc::DIBuilder::EmitStopPoint(unsigned ln) +void ldc::DIBuilder::EmitStopPoint(Loc& loc) { if (!global.params.symdebug) return; - Logger::println("D to dwarf stoppoint at line %u", ln); + Logger::println("D to dwarf stoppoint at line %u, column %u", loc.linnum, loc.charnum); LOG_SCOPE; - llvm::DebugLoc loc = llvm::DebugLoc::get(ln, 0, GetCurrentScope()); - IR->ir->SetCurrentDebugLocation(loc); + IR->ir->SetCurrentDebugLocation(llvm::DebugLoc::get(loc.linnum, loc.charnum, GetCurrentScope())); } void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) diff --git a/gen/dibuilder.h b/gen/dibuilder.h index f365bb28bca..3d65fe8fc98 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -158,7 +158,7 @@ class DIBuilder /// \brief Emits debug info for block end void EmitBlockEnd(); - void EmitStopPoint(unsigned ln); + void EmitStopPoint(Loc& loc); void EmitValue(llvm::Value *val, VarDeclaration* vd); diff --git a/gen/statements.cpp b/gen/statements.cpp index ccc8215693b..e125ea8c93f 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -372,7 +372,7 @@ class ToIRVisitor : public Visitor { LOG_SCOPE; // emit dwarf stop point - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); emitCoverageLinecountInc(stmt->loc); @@ -493,7 +493,7 @@ class ToIRVisitor : public Visitor { LOG_SCOPE; // emit dwarf stop point - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); emitCoverageLinecountInc(stmt->loc); @@ -810,7 +810,7 @@ class ToIRVisitor : public Visitor { return; // emit dwarf stop point - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); emitCoverageLinecountInc(stmt->loc); @@ -873,7 +873,7 @@ class ToIRVisitor : public Visitor { LOG_SCOPE; // emit dwarf stop point - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); emitCoverageLinecountInc(stmt->loc); @@ -941,7 +941,7 @@ class ToIRVisitor : public Visitor { LOG_SCOPE; // emit dwarf stop point - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); // if there's no finalbody or no body, things are simple if (!stmt->finalbody) { @@ -1033,7 +1033,7 @@ class ToIRVisitor : public Visitor { LOG_SCOPE; // emit dwarf stop point - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); // create basic blocks llvm::BasicBlock* oldend = irs->scopeend(); @@ -1090,7 +1090,7 @@ class ToIRVisitor : public Visitor { LOG_SCOPE; // emit dwarf stop point - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); emitCoverageLinecountInc(stmt->loc); @@ -1119,7 +1119,7 @@ class ToIRVisitor : public Visitor { LOG_SCOPE; // emit dwarf stop point - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); emitCoverageLinecountInc(stmt->loc); @@ -1691,7 +1691,7 @@ class ToIRVisitor : public Visitor { IF_LOG Logger::println("GotoStatement::toIR(): %s", stmt->loc.toChars()); LOG_SCOPE; - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); emitCoverageLinecountInc(stmt->loc); @@ -1709,7 +1709,7 @@ class ToIRVisitor : public Visitor { IF_LOG Logger::println("GotoDefaultStatement::toIR(): %s", stmt->loc.toChars()); LOG_SCOPE; - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); emitCoverageLinecountInc(stmt->loc); @@ -1731,7 +1731,7 @@ class ToIRVisitor : public Visitor { IF_LOG Logger::println("GotoCaseStatement::toIR(): %s", stmt->loc.toChars()); LOG_SCOPE; - gIR->DBuilder.EmitStopPoint(stmt->loc.linnum); + gIR->DBuilder.EmitStopPoint(stmt->loc); emitCoverageLinecountInc(stmt->loc); From 482711a6010607246d867f255b3bf78df67d7d3d Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 20:19:18 +0200 Subject: [PATCH 082/101] DebugInfo: Do not emit line info if line number is zero. --- gen/dibuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 0cc17e2f97c..dcc6642a3e3 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -827,7 +827,7 @@ void ldc::DIBuilder::EmitBlockEnd() void ldc::DIBuilder::EmitStopPoint(Loc& loc) { - if (!global.params.symdebug) + if (!global.params.symdebug || !loc.linnum) return; Logger::println("D to dwarf stoppoint at line %u, column %u", loc.linnum, loc.charnum); From 104e7c991f389c396c66881a117dd28c5c2e51ef Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 20:19:54 +0200 Subject: [PATCH 083/101] DebugInfo: Remove most calls to EmitFuncEnd() Debug information is based on static lexical blocks. Most calls to EmitFuncEnd() are done if control flow reaches the end of the function which is quite different. --- gen/functions.cpp | 3 ++- gen/llvmhelpers.cpp | 3 --- gen/statements.cpp | 7 ------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/gen/functions.cpp b/gen/functions.cpp index 44dd32ef25e..ca2815cfc59 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -1043,7 +1043,7 @@ void DtoDefineFunction(FuncDeclaration* fd) // in automatically, so we do it here. // pass the previous block into this block - gIR->DBuilder.EmitFuncEnd(fd); + gIR->DBuilder.EmitStopPoint(fd->endloc); if (func->getReturnType() == LLType::getVoidTy(gIR->context())) { llvm::ReturnInst::Create(gIR->context(), gIR->scopebb()); } @@ -1060,6 +1060,7 @@ void DtoDefineFunction(FuncDeclaration* fd) else llvm::ReturnInst::Create(gIR->context(), LLConstant::getNullValue(func->getReturnType()), bb); } + gIR->DBuilder.EmitFuncEnd(fd); // erase alloca point if (allocaPoint->getParent()) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index dd88ee60a33..0bbbdee4960 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -197,9 +197,6 @@ void DtoAssert(Module* M, Loc& loc, DValue* msg) // call gIR->CreateCallOrInvoke(fn, args); - // end debug info - gIR->DBuilder.EmitFuncEnd(gIR->func()->decl); - // after assert is always unreachable gIR->ir->CreateUnreachable(); } diff --git a/gen/statements.cpp b/gen/statements.cpp index e125ea8c93f..5061fbe36c4 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -403,9 +403,6 @@ class ToIRVisitor : public Visitor { // emit scopes DtoEnclosingHandlers(stmt->loc, NULL); - // emit dbg end function - gIR->DBuilder.EmitFuncEnd(f->decl); - // emit ret llvm::ReturnInst::Create(gIR->context(), irs->scopebb()); } @@ -467,7 +464,6 @@ class ToIRVisitor : public Visitor { // emit scopes DtoEnclosingHandlers(stmt->loc, NULL); - gIR->DBuilder.EmitFuncEnd(irs->func()->decl); llvm::ReturnInst::Create(gIR->context(), v, irs->scopebb()); } } @@ -476,7 +472,6 @@ class ToIRVisitor : public Visitor { { assert(irs->topfunc()->getReturnType() == LLType::getVoidTy(gIR->context())); DtoEnclosingHandlers(stmt->loc, NULL); - gIR->DBuilder.EmitFuncEnd(irs->func()->decl); llvm::ReturnInst::Create(gIR->context(), irs->scopebb()); } @@ -1097,8 +1092,6 @@ class ToIRVisitor : public Visitor { assert(stmt->exp); DValue* e = toElemDtor(stmt->exp); - gIR->DBuilder.EmitFuncEnd(gIR->func()->decl); - llvm::Function* fn = LLVM_D_GetRuntimeFunction(stmt->loc, gIR->module, "_d_throw_exception"); //Logger::cout() << "calling: " << *fn << '\n'; LLValue* arg = DtoBitCast(e->getRVal(), fn->getFunctionType()->getParamType(0)); From b301407f9cf7a8072f521e25a50d4e175cbfe790 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 21:22:38 +0200 Subject: [PATCH 084/101] DebugInfo: Use the IRBuilder to create a ret instruction. This ensures that a previous set debug location will be set on the return instruction. --- gen/functions.cpp | 8 ++++---- gen/statements.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gen/functions.cpp b/gen/functions.cpp index ca2815cfc59..12641f3cb4d 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -1045,20 +1045,20 @@ void DtoDefineFunction(FuncDeclaration* fd) // pass the previous block into this block gIR->DBuilder.EmitStopPoint(fd->endloc); if (func->getReturnType() == LLType::getVoidTy(gIR->context())) { - llvm::ReturnInst::Create(gIR->context(), gIR->scopebb()); + gIR->ir->CreateRetVoid(); } else if (!fd->isMain()) { AsmBlockStatement* asmb = fd->fbody->endsWithAsm(); if (asmb) { assert(asmb->abiret); - llvm::ReturnInst::Create(gIR->context(), asmb->abiret, bb); + gIR->ir->CreateRet(asmb->abiret); } else { - llvm::ReturnInst::Create(gIR->context(), llvm::UndefValue::get(func->getReturnType()), bb); + gIR->ir->CreateRet(llvm::UndefValue::get(func->getReturnType())); } } else - llvm::ReturnInst::Create(gIR->context(), LLConstant::getNullValue(func->getReturnType()), bb); + gIR->ir->CreateRet(LLConstant::getNullValue(func->getReturnType())); } gIR->DBuilder.EmitFuncEnd(fd); diff --git a/gen/statements.cpp b/gen/statements.cpp index 5061fbe36c4..7142b64e00a 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -404,7 +404,7 @@ class ToIRVisitor : public Visitor { DtoEnclosingHandlers(stmt->loc, NULL); // emit ret - llvm::ReturnInst::Create(gIR->context(), irs->scopebb()); + gIR->ir->CreateRetVoid(); } // the return type is not void, so this is a normal "register" return else @@ -464,7 +464,7 @@ class ToIRVisitor : public Visitor { // emit scopes DtoEnclosingHandlers(stmt->loc, NULL); - llvm::ReturnInst::Create(gIR->context(), v, irs->scopebb()); + gIR->ir->CreateRet(v); } } // no return value expression means it's a void function @@ -472,7 +472,7 @@ class ToIRVisitor : public Visitor { { assert(irs->topfunc()->getReturnType() == LLType::getVoidTy(gIR->context())); DtoEnclosingHandlers(stmt->loc, NULL); - llvm::ReturnInst::Create(gIR->context(), irs->scopebb()); + gIR->ir->CreateRetVoid(); } // the return terminated this basicblock, start a new one From 3bab8306aace28eb253e5c5dc0194cfbfc3bc2c9 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 21:58:43 +0200 Subject: [PATCH 085/101] DebugInfo: Use DebugLoc::get() for declaration of variable. --- gen/dibuilder.cpp | 12 +++++++----- gen/dibuilder.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index dcc6642a3e3..05593044788 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -73,7 +73,7 @@ ldc::DIScope ldc::DIBuilder::GetCurrentScope() return fn->diLexicalBlocks.top(); } -void ldc::DIBuilder::Declare(llvm::Value *var, ldc::DILocalVariable divar +void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar #if LDC_LLVM_VER >= 306 , ldc::DIExpression diexpr #endif @@ -84,10 +84,12 @@ void ldc::DIBuilder::Declare(llvm::Value *var, ldc::DILocalVariable divar diexpr, #endif #if LDC_LLVM_VER >= 307 - IR->ir->getCurrentDebugLocation(), + llvm::DebugLoc::get(loc.linnum, loc.charnum, GetCurrentScope()), #endif IR->scopebb()); - instr->setDebugLoc(IR->ir->getCurrentDebugLocation()); +#if LDC_LLVM_VER < 307 + instr->setDebugLoc(llvm::DebugLoc::get(loc.linnum, loc.charnum, GetCurrentScope())); +#endif } ldc::DIFile ldc::DIBuilder::CreateFile(Loc& loc) @@ -932,9 +934,9 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, // declare #if LDC_LLVM_VER >= 306 - Declare(ll, debugVariable, addr.empty() ? DBuilder.createExpression() : DBuilder.createExpression(addr)); + Declare(vd->loc, ll, debugVariable, addr.empty() ? DBuilder.createExpression() : DBuilder.createExpression(addr)); #else - Declare(ll, debugVariable); + Declare(vd->loc, ll, debugVariable); #endif } diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 3d65fe8fc98..1b58ae3a45a 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -189,7 +189,7 @@ class DIBuilder llvm::LLVMContext &getContext(); Module *getDefinedModule(Dsymbol *s); DIScope GetCurrentScope(); - void Declare(llvm::Value *var, ldc::DILocalVariable divar + void Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar #if LDC_LLVM_VER >= 306 , ldc::DIExpression diexpr #endif From 31d6031c9e7082dffb753c96f70b5f1f3ffb3f99 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 4 Jun 2015 22:45:23 +0200 Subject: [PATCH 086/101] DebugInfo: Better location for automatically appended return. If function main() has return type void then a return 0; is automatically appended to the statements. Set the end of the function as the location of this statement. This helps with the debug information in LDC. --- dmd2/func.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dmd2/func.c b/dmd2/func.c index 0fa1a75beb3..a2fcc55ffb4 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -2203,7 +2203,12 @@ void FuncDeclaration::semantic3(Scope *sc) if (isMain() && type->nextOf()->ty == Tvoid) { // Add a return 0; statement +#if IN_LLVM + // The return statement is put at the end. Give it the end location. + Statement *s = new ReturnStatement(endloc, new IntegerExp(0)); +#else Statement *s = new ReturnStatement(Loc(), new IntegerExp(0)); +#endif a->push(s); } From 7e82631b94fd3dd11ab4cafdbde3977f8a0f3c53 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 5 Jun 2015 00:16:48 +0200 Subject: [PATCH 087/101] Revert "DebugInfo: Use DebugLoc::get() for declaration of variable." This reverts commit 3bab8306aace28eb253e5c5dc0194cfbfc3bc2c9. --- gen/dibuilder.cpp | 12 +++++------- gen/dibuilder.h | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 05593044788..dcc6642a3e3 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -73,7 +73,7 @@ ldc::DIScope ldc::DIBuilder::GetCurrentScope() return fn->diLexicalBlocks.top(); } -void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar +void ldc::DIBuilder::Declare(llvm::Value *var, ldc::DILocalVariable divar #if LDC_LLVM_VER >= 306 , ldc::DIExpression diexpr #endif @@ -84,12 +84,10 @@ void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVaria diexpr, #endif #if LDC_LLVM_VER >= 307 - llvm::DebugLoc::get(loc.linnum, loc.charnum, GetCurrentScope()), + IR->ir->getCurrentDebugLocation(), #endif IR->scopebb()); -#if LDC_LLVM_VER < 307 - instr->setDebugLoc(llvm::DebugLoc::get(loc.linnum, loc.charnum, GetCurrentScope())); -#endif + instr->setDebugLoc(IR->ir->getCurrentDebugLocation()); } ldc::DIFile ldc::DIBuilder::CreateFile(Loc& loc) @@ -934,9 +932,9 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, // declare #if LDC_LLVM_VER >= 306 - Declare(vd->loc, ll, debugVariable, addr.empty() ? DBuilder.createExpression() : DBuilder.createExpression(addr)); + Declare(ll, debugVariable, addr.empty() ? DBuilder.createExpression() : DBuilder.createExpression(addr)); #else - Declare(vd->loc, ll, debugVariable); + Declare(ll, debugVariable); #endif } diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 1b58ae3a45a..3d65fe8fc98 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -189,7 +189,7 @@ class DIBuilder llvm::LLVMContext &getContext(); Module *getDefinedModule(Dsymbol *s); DIScope GetCurrentScope(); - void Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar + void Declare(llvm::Value *var, ldc::DILocalVariable divar #if LDC_LLVM_VER >= 306 , ldc::DIExpression diexpr #endif From 227f16bcce930fabfe223b434baee6ce2cd8521d Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 5 Jun 2015 02:52:13 +0200 Subject: [PATCH 088/101] DebugInfo: Better location for automatically appended return. If function main() has return type void then a 'return 0;' is automatically appended to the statements. Set the end of the function as the location of this statement. This helps with the debug information in LDC. Don't do it at a more global level because disturbs the coverage code. --- gen/statements.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gen/statements.cpp b/gen/statements.cpp index 7142b64e00a..7e4d83a8a23 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -464,6 +464,12 @@ class ToIRVisitor : public Visitor { // emit scopes DtoEnclosingHandlers(stmt->loc, NULL); + // Hack: the frontend generates 'return 0;' as last statement of + // 'void main()'. But the debug location is missing. Use the end + // of function as debug location. + if (f->decl->isMain() && !stmt->loc.linnum) + gIR->DBuilder.EmitStopPoint(f->decl->endloc); + gIR->ir->CreateRet(v); } } From 95c897ab3e541bdca294c19a966568c57c6c14d1 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 5 Jun 2015 13:04:30 +0200 Subject: [PATCH 089/101] DebugInfo: Use location of variable declaration instead of current stop point. There might be no valid stop point but the variable should always have a location. This fixes an ICE compiling core.demangle. --- gen/dibuilder.cpp | 12 +++++++----- gen/dibuilder.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index dcc6642a3e3..05593044788 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -73,7 +73,7 @@ ldc::DIScope ldc::DIBuilder::GetCurrentScope() return fn->diLexicalBlocks.top(); } -void ldc::DIBuilder::Declare(llvm::Value *var, ldc::DILocalVariable divar +void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar #if LDC_LLVM_VER >= 306 , ldc::DIExpression diexpr #endif @@ -84,10 +84,12 @@ void ldc::DIBuilder::Declare(llvm::Value *var, ldc::DILocalVariable divar diexpr, #endif #if LDC_LLVM_VER >= 307 - IR->ir->getCurrentDebugLocation(), + llvm::DebugLoc::get(loc.linnum, loc.charnum, GetCurrentScope()), #endif IR->scopebb()); - instr->setDebugLoc(IR->ir->getCurrentDebugLocation()); +#if LDC_LLVM_VER < 307 + instr->setDebugLoc(llvm::DebugLoc::get(loc.linnum, loc.charnum, GetCurrentScope())); +#endif } ldc::DIFile ldc::DIBuilder::CreateFile(Loc& loc) @@ -932,9 +934,9 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, // declare #if LDC_LLVM_VER >= 306 - Declare(ll, debugVariable, addr.empty() ? DBuilder.createExpression() : DBuilder.createExpression(addr)); + Declare(vd->loc, ll, debugVariable, addr.empty() ? DBuilder.createExpression() : DBuilder.createExpression(addr)); #else - Declare(ll, debugVariable); + Declare(vd->loc, ll, debugVariable); #endif } diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 3d65fe8fc98..1b58ae3a45a 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -189,7 +189,7 @@ class DIBuilder llvm::LLVMContext &getContext(); Module *getDefinedModule(Dsymbol *s); DIScope GetCurrentScope(); - void Declare(llvm::Value *var, ldc::DILocalVariable divar + void Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar #if LDC_LLVM_VER >= 306 , ldc::DIExpression diexpr #endif From 34d95511242053e7b1e16c915f8bbc44eb8ee630 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 5 Jun 2015 13:44:49 +0200 Subject: [PATCH 090/101] Revert "DebugInfo: Better location for automatically appended return." This reverts commit 31d6031c9e7082dffb753c96f70b5f1f3ffb3f99. --- dmd2/func.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dmd2/func.c b/dmd2/func.c index a2fcc55ffb4..0fa1a75beb3 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -2203,12 +2203,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (isMain() && type->nextOf()->ty == Tvoid) { // Add a return 0; statement -#if IN_LLVM - // The return statement is put at the end. Give it the end location. - Statement *s = new ReturnStatement(endloc, new IntegerExp(0)); -#else Statement *s = new ReturnStatement(Loc(), new IntegerExp(0)); -#endif a->push(s); } From 6370ebf2d1892652ae98f8aabe4d96dfba60f36c Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 24 Mar 2015 00:30:11 +0100 Subject: [PATCH 091/101] Don't care about mismatching types in conditional expressions. Ignore LL type mismatches between the overall expression and its 2 nested true/false expressions. --- gen/toir.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 4e8573d9ab4..85d158f6dd1 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2443,7 +2443,7 @@ class ToElemVisitor : public Visitor LOG_SCOPE; Type* dtype = e->type->toBasetype(); - LLValue *retPtr = 0; + LLValue* retPtr = 0; if (dtype->ty != Tvoid) { // allocate a temporary for pointer to the final result. retPtr = DtoAlloca(dtype->pointerTo(), "condtmp"); @@ -2456,22 +2456,26 @@ class ToElemVisitor : public Visitor DValue* c = toElem(e->econd); LLValue* cond_val = DtoCast(e->loc, c, Type::tbool)->getRVal(); - llvm::BranchInst::Create(condtrue,condfalse,cond_val,p->scopebb()); + llvm::BranchInst::Create(condtrue, condfalse, cond_val, p->scopebb()); p->scope() = IRScope(condtrue, condfalse); DValue* u = toElemDtor(e->e1); - if (dtype->ty != Tvoid) - DtoStore(makeLValue(e->loc, u), retPtr); + if (retPtr) { + LLValue* lval = makeLValue(e->loc, u); + DtoStore(lval, DtoBitCast(retPtr, lval->getType()->getPointerTo())); + } llvm::BranchInst::Create(condend, p->scopebb()); p->scope() = IRScope(condfalse, condend); DValue* v = toElemDtor(e->e2); - if (dtype->ty != Tvoid) - DtoStore(makeLValue(e->loc, v), retPtr); + if (retPtr) { + LLValue* lval = makeLValue(e->loc, v); + DtoStore(lval, DtoBitCast(retPtr, lval->getType()->getPointerTo())); + } llvm::BranchInst::Create(condend, p->scopebb()); p->scope() = IRScope(condend, oldend); - if (dtype->ty != Tvoid) + if (retPtr) result = new DVarValue(e->type, DtoLoad(retPtr)); else result = new DConstValue(e->type, getNullValue(voidToI8(DtoType(dtype)))); From 638ff17f894829313f40cea3b71733310e9bd06c Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 7 Jun 2015 00:33:28 +0200 Subject: [PATCH 092/101] Add test case for issue #965. The bug was already fixed in the merge-2.067 branch. --- tests/d2/dmd-testsuite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index ea3d890be17..296e3747580 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit ea3d890be17aa2e957cb86ca03d6167ade111093 +Subproject commit 296e3747580450f153f822386fdf84b4221c0278 From e5838342dfeac0db1979109a63c5b76a3d994fb8 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 14 Jun 2015 02:48:38 +0200 Subject: [PATCH 093/101] We always define functions for which we emit DWARF subprograms This fixes a crash with debug info for lambdas, where DMD appends the lambda function declaration to the wrong module. But the comparison is supposed to be tautological anyway, as we only ever call it from DtoDefineFunction. Furthermore, it seems as passing false can never work unless you manually (without going through llvm::DIBuilder) resolve the Vars node later. Clang does not try to do this either. --- gen/dibuilder.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 05593044788..53dffe2c335 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "gen/dibuilder.h" + #include "gen/functions.h" #include "gen/irstate.h" #include "gen/llvmhelpers.h" @@ -709,7 +710,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) fd->loc.linnum, // line no DIFnType, // type fd->protection == PROTprivate, // is local to unit - IR->dmodule == getDefinedModule(fd), // isdefinition + true, // isdefinition fd->loc.linnum, // FIXME: scope line DIFlags::FlagPrototyped, // Flags isOptimizationEnabled(), // isOptimized From ebfa7523fe0b3d2074827ac1cef01cd809f2b644 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 14 Jun 2015 21:41:13 +0200 Subject: [PATCH 094/101] Always link libcurl when Phobos is linked This is the only sensible solution until e.g. D-Programming-Language/phobos#3009 is merged, which makes Phobos load libcurl dynamically. The issue with the current situation is is that the user cannot even manually link libcurl if linker errors occur, because it will appear before libphobos2-ldc in the linker command line. GitHub: Fixes #906. --- ldc2_install.conf.in | 4 ++-- ldc2_phobos.conf.in | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ldc2_install.conf.in b/ldc2_install.conf.in index 33b67f880e7..bb9b6c64e49 100644 --- a/ldc2_install.conf.in +++ b/ldc2_install.conf.in @@ -10,7 +10,7 @@ default: "-I@INCLUDE_INSTALL_DIR@/ldc", "-I@INCLUDE_INSTALL_DIR@", "-L-L@CMAKE_INSTALL_LIBDIR@", @MULTILIB_ADDITIONAL_INSTALL_PATH@ - "-defaultlib=phobos2-ldc,druntime-ldc", - "-debuglib=phobos2-ldc-debug,druntime-ldc-debug" + "-defaultlib=phobos2-ldc,curl,druntime-ldc", + "-debuglib=phobos2-ldc-debug,curl,druntime-ldc-debug" ]; }; diff --git a/ldc2_phobos.conf.in b/ldc2_phobos.conf.in index e3f8a80b4ca..01e09b0715d 100644 --- a/ldc2_phobos.conf.in +++ b/ldc2_phobos.conf.in @@ -14,7 +14,7 @@ default: "-L-L@PROJECT_BINARY_DIR@/../lib@LIB_SUFFIX@/Debug", "-L-L@PROJECT_BINARY_DIR@/../lib@LIB_SUFFIX@/Release", "-L-L@PROJECT_BINARY_DIR@/../lib@LIB_SUFFIX@/RelWithDebInfo", - "-defaultlib=phobos2-ldc,druntime-ldc", - "-debuglib=phobos2-ldc-debug,druntime-ldc-debug" + "-defaultlib=phobos2-ldc,curl,druntime-ldc", + "-debuglib=phobos2-ldc-debug,curl,druntime-ldc-debug" ]; }; From a72efcf80cb576d25c7056a428f5b78f05e87afb Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 21 Jun 2015 17:32:48 +0200 Subject: [PATCH 095/101] LLVM 3.7: set personality function on a per-function basis. Instead of on a per-landing-pad basis. See LLVM commit cc714e2. --- ir/irlandingpad.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/ir/irlandingpad.cpp b/ir/irlandingpad.cpp index 6bff24a81e1..23d4e3b12a9 100644 --- a/ir/irlandingpad.cpp +++ b/ir/irlandingpad.cpp @@ -19,11 +19,20 @@ // creates new landing pad static llvm::LandingPadInst *createLandingPadInst() { - llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(Loc(), gIR->module, "_d_eh_personality"); - LLType *retType = LLStructType::get(LLType::getInt8PtrTy(gIR->context()), + LLType* retType = LLStructType::get(LLType::getInt8PtrTy(gIR->context()), LLType::getInt32Ty(gIR->context()), NULL); - return gIR->ir->CreateLandingPad(retType, personality_fn, 0, "landing_pad"); +#if LDC_LLVM_VER >= 307 + LLFunction* currentFunction = gIR->func()->func; + if (!currentFunction->hasPersonalityFn()) { + LLFunction* personalityFn = LLVM_D_GetRuntimeFunction(Loc(), gIR->module, "_d_eh_personality"); + currentFunction->setPersonalityFn(personalityFn); + } + return gIR->ir->CreateLandingPad(retType, 0, "landing_pad"); +#else + LLFunction* personalityFn = LLVM_D_GetRuntimeFunction(Loc(), gIR->module, "_d_eh_personality"); + return gIR->ir->CreateLandingPad(retType, personalityFn, 0, "landing_pad"); +#endif } IRLandingPadCatchInfo::IRLandingPadCatchInfo(Catch* catchstmt_, llvm::BasicBlock* end_) : From 49c3acd50f7dd905f9c7f5501fe91c30b29e0c9e Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 21 Jun 2015 17:28:36 +0200 Subject: [PATCH 096/101] Don't suppress all warnings when building LDC with MSVC. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7444f5bc2e..372977c43d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -325,7 +325,7 @@ if(MSVC) string(REGEX REPLACE "(^| ) */GR-? *( |$)" "\\1 \\2" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") add_definitions(-D_HAS_EXCEPTIONS=0) - set(EXTRA_CXXFLAGS "/W0 /wd4996 /GF /GR- /EHs-c- /MP") + set(EXTRA_CXXFLAGS "/GF /GR- /EHs-c- /MP") else() set(EXTRA_CXXFLAGS "") endif() From 3b73307ede4fc5644d3d8246cf57d2f30f95b2cd Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 21 Jun 2015 17:31:21 +0200 Subject: [PATCH 097/101] Revise MSVC compiler switches for druntime and phobos. --- runtime/CMakeLists.txt | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 92386f605b3..973130b696b 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -221,17 +221,14 @@ add_custom_command( ) # Always build zlib and other C parts of the runtime in release mode, regardless -# of what the user chose for LDC itself. We can't easily do this on MSVC builds -# due to incompatible switches. -if(NOT MSVC) - set(cfiles "${CORE_C};${DCRT_C}") - if(PHOBOS2_DIR) - list(APPEND cfiles "${ZLIB_C}") - endif() - set_source_files_properties(${cfiles} PROPERTIES - COMPILE_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}" - ) +# of what the user chose for LDC itself. +set(cfiles "${CORE_C};${DCRT_C}") +if(PHOBOS2_DIR) + list(APPEND cfiles "${ZLIB_C}") endif() +set_source_files_properties(${cfiles} PROPERTIES + COMPILE_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}" +) # Compiles the given D module into an object file, and if enabled, a bitcode # file. The ouput is written to a path based on output_dir. The paths of the @@ -488,10 +485,11 @@ endmacro() # if(MSVC) + # /wd4996: suppress deprecation warnings about zlib using POSIX names if (LINK_WITH_MSVCRT) - set(RT_CFLAGS "/MDd") + set(RT_CFLAGS "/wd4996 /MD") else() - set(RT_CFLAGS "/MTd") + set(RT_CFLAGS "/wd4996 /MT") endif() else() set(RT_CFLAGS "") From d7347a5829f376adb6023967c763b024f6d58a5b Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 25 Jun 2015 21:49:42 +0200 Subject: [PATCH 098/101] Do not imply ` -singleObj` if creating lib. If a target file name is given (`-of`) and a library is created then `-singleObj` is implied. This results in behaviour not compatible with dmd. This commit checks for this situation and does not set `-singleObj`. This fixes issue #978. --- dmd2/module.h | 2 +- driver/main.cpp | 8 ++------ gen/module.cpp | 11 ++++++----- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/dmd2/module.h b/dmd2/module.h index ac9900e499f..f717846f753 100644 --- a/dmd2/module.h +++ b/dmd2/module.h @@ -209,7 +209,7 @@ class Module : public Package #if IN_LLVM // LDC llvm::Module* genLLVMModule(llvm::LLVMContext& context); - void buildTargetFiles(bool singleObj); + void buildTargetFiles(bool singleObj, bool library); File* buildFilePath(const char* forcename, const char* path, const char* ext); llvm::GlobalVariable* moduleInfoSymbol(); diff --git a/driver/main.cpp b/driver/main.cpp index b926af1d944..267ad55bb94 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -496,11 +496,7 @@ static void parseCommandLine(int argc, char **argv, Strings &sourceFiles, bool & error(Loc(), "flags conflict with -run"); } else if (global.params.objname && sourceFiles.dim > 1) { - if (createStaticLib || createSharedLib) - { - singleObj = true; - } - if (!singleObj) + if (!(createStaticLib || createSharedLib) && !singleObj) { error(Loc(), "multiple source files, but only one .obj name"); } @@ -1246,7 +1242,7 @@ int main(int argc, char **argv) } m->parse(global.params.doDocComments); - m->buildTargetFiles(singleObj); + m->buildTargetFiles(singleObj, createSharedLib || createStaticLib); m->deleteObjFile(); if (m->isDocFile) { diff --git a/gen/module.cpp b/gen/module.cpp index 286ed4d3eb9..e987aed9331 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -86,7 +86,7 @@ static void check_and_add_output_file(Module* NewMod, const std::string& str) files.insert(std::make_pair(str, NewMod)); } -void Module::buildTargetFiles(bool singleObj) +void Module::buildTargetFiles(bool singleObj, bool library) { if (objfile && (!doDocComment || docfile) && @@ -94,15 +94,16 @@ void Module::buildTargetFiles(bool singleObj) return; if (!objfile) { + const char *objname = library ? 0 : global.params.objname; if (global.params.output_o) - objfile = Module::buildFilePath(global.params.objname, global.params.objdir, + objfile = Module::buildFilePath(objname, global.params.objdir, global.params.targetTriple.isOSWindows() ? global.obj_ext_alt : global.obj_ext); else if (global.params.output_bc) - objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.bc_ext); + objfile = Module::buildFilePath(objname, global.params.objdir, global.bc_ext); else if (global.params.output_ll) - objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.ll_ext); + objfile = Module::buildFilePath(objname, global.params.objdir, global.ll_ext); else if (global.params.output_s) - objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.s_ext); + objfile = Module::buildFilePath(objname, global.params.objdir, global.s_ext); } if (doDocComment && !docfile) docfile = Module::buildFilePath(global.params.docname, global.params.docdir, global.doc_ext); From d1e764cec1788f4c3f3d09045b8adb8dc9c0d857 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sat, 27 Jun 2015 14:21:33 +0200 Subject: [PATCH 099/101] Backport of "Avoid using llvm::Linker" to master. See pull request #974 for the original code. --- .travis.yml | 8 +- CMakeLists.txt | 2 + dmd2/dsymbol.h | 12 -- dmd2/module.c | 1 - dmd2/module.h | 2 - driver/codegenerator.cpp | 221 ++++++++++++++++++++++++ driver/codegenerator.h | 46 +++++ driver/linker.cpp | 5 - driver/main.cpp | 310 +++++++--------------------------- gen/arrays.cpp | 4 +- gen/classes.cpp | 2 +- gen/coverage.cpp | 67 ++++---- gen/declarations.cpp | 2 +- gen/dibuilder.cpp | 11 +- gen/dibuilder.h | 4 +- gen/functions.cpp | 143 ++-------------- gen/inlineir.cpp | 107 ++++++++++++ gen/inlineir.h | 24 +++ gen/irstate.cpp | 12 +- gen/irstate.h | 30 +--- gen/llvm.h | 2 +- gen/llvmhelpers.cpp | 19 +-- gen/logger.cpp | 4 +- gen/module.cpp | 352 +++++++++++++++------------------------ gen/naked.cpp | 2 +- gen/rttibuilder.cpp | 4 +- gen/runtime.cpp | 12 +- gen/runtime.h | 4 +- gen/statements.cpp | 4 +- gen/tocall.cpp | 4 +- gen/toconstelem.cpp | 12 +- gen/toir.cpp | 8 +- gen/tollvm.cpp | 33 +--- gen/tollvm.h | 1 - gen/typinf.cpp | 8 +- ir/iraggr.cpp | 2 +- ir/irclass.cpp | 12 +- ir/irmodule.cpp | 34 ++-- ir/irmodule.h | 31 ++-- 39 files changed, 751 insertions(+), 810 deletions(-) create mode 100644 driver/codegenerator.cpp create mode 100644 driver/codegenerator.h create mode 100644 gen/inlineir.cpp create mode 100644 gen/inlineir.h diff --git a/.travis.yml b/.travis.yml index 0c409a51def..da28a05047b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,15 +55,13 @@ env: - LLVM_PACKAGE="llvm-3.5 llvm-3.5-dev libedit2 libedit-dev" - LLVM_PACKAGE="llvm-3.5 llvm-3.5-dev libedit2 libedit-dev" OPTS="-DTEST_COVERAGE=ON" - LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" TEST_DEBUG=1 - - LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" + - LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" OPTS="-DMULTILIB=ON" TEST_BITNESS=32 + - LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" OPTS="-DMULTILIB=ON" TEST_BITNESS=64 - LLVM_PACKAGE="llvm-3.7 llvm-3.7-dev libedit2 libedit-dev" TEST_DEBUG=1 - LLVM_PACKAGE="llvm-3.7 llvm-3.7-dev libedit2 libedit-dev" matrix: allow_failures: - - env: LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" OPTS="-DMULTILIB=ON" TEST_BITNESS=32 - - env: LLVM_PACKAGE="llvm-3.4 llvm-3.4-dev" OPTS="-DMULTILIB=ON" TEST_BITNESS=64 - - env: LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" TEST_DEBUG=1 - - env: LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" + - env: LLVM_PACKAGE="llvm-3.6 llvm-3.6-dev libedit2 libedit-dev" OPTS="-DMULTILIB=ON" TEST_BITNESS=32 - env: LLVM_PACKAGE="llvm-3.7 llvm-3.7-dev libedit2 libedit-dev" TEST_DEBUG=1 - env: LLVM_PACKAGE="llvm-3.7 llvm-3.7-dev libedit2 libedit-dev" script: diff --git a/CMakeLists.txt b/CMakeLists.txt index f7444f5bc2e..c418bed76e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,6 +228,7 @@ file(GLOB IR_SRC ir/*.cpp) file(GLOB IR_HDR ir/*.h) set(DRV_SRC driver/cl_options.cpp + driver/codegenerator.cpp driver/configfile.cpp driver/targetmachine.cpp driver/toobj.cpp @@ -239,6 +240,7 @@ set(DRV_SRC set(DRV_HDR driver/linker.h driver/cl_options.h + driver/codegenerator.h driver/configfile.h driver/ldc-version.h driver/targetmachine.h diff --git a/dmd2/dsymbol.h b/dmd2/dsymbol.h index 47ef120ead8..26982615aa4 100644 --- a/dmd2/dsymbol.h +++ b/dmd2/dsymbol.h @@ -86,24 +86,12 @@ class DeleteDeclaration; struct HdrGenState; class OverloadSet; struct AA; -#if IN_LLVM -class TypeInfoDeclaration; -class ClassInfoDeclaration; -#endif #ifdef IN_GCC typedef union tree_node TYPE; #else struct TYPE; #endif -#if IN_LLVM -struct IRState; -namespace llvm -{ - class Value; -} -#endif - struct Ungag { unsigned oldgag; diff --git a/dmd2/module.c b/dmd2/module.c index a6de5e3bd73..dd4688f8f03 100644 --- a/dmd2/module.c +++ b/dmd2/module.c @@ -143,7 +143,6 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do // LDC llvmForceLogging = false; noModuleInfo = false; - moduleInfoVar = NULL; this->doDocComment = doDocComment; this->doHdrGen = doHdrGen; this->arrayfuncs = 0; diff --git a/dmd2/module.h b/dmd2/module.h index f717846f753..23528e305a7 100644 --- a/dmd2/module.h +++ b/dmd2/module.h @@ -211,11 +211,9 @@ class Module : public Package llvm::Module* genLLVMModule(llvm::LLVMContext& context); void buildTargetFiles(bool singleObj, bool library); File* buildFilePath(const char* forcename, const char* path, const char* ext); - llvm::GlobalVariable* moduleInfoSymbol(); bool llvmForceLogging; bool noModuleInfo; /// Do not emit any module metadata. - llvm::GlobalVariable* moduleInfoVar; // array ops emitted in this module already AA *arrayfuncs; diff --git a/driver/codegenerator.cpp b/driver/codegenerator.cpp new file mode 100644 index 00000000000..7c9e1358d26 --- /dev/null +++ b/driver/codegenerator.cpp @@ -0,0 +1,221 @@ +//===-- codegenerator.cpp -------------------------------------------------===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// + +#include "driver/codegenerator.h" + +#include "id.h" +#include "mars.h" +#include "module.h" +#include "parse.h" +#include "scope.h" +#include "driver/toobj.h" +#include "gen/logger.h" +#include "gen/runtime.h" + +void codegenModule(IRState *irs, Module *m, bool emitFullModuleInfo); + +namespace { +Module *g_entrypointModule = 0; +Module *g_dMainModule = 0; +} + +/// Callback to generate a C main() function, invoked by the frontend. +void genCmain(Scope *sc) { + if (g_entrypointModule) return; + + /* The D code to be generated is provided as D source code in the form of a + * string. + * Note that Solaris, for unknown reasons, requires both a main() and an + * _main() + */ + static utf8_t code[] = "extern(C) {\n\ + int _d_run_main(int argc, char **argv, void* mainFunc);\n\ + int _Dmain(char[][] args);\n\ + int main(int argc, char **argv) { return _d_run_main(argc, argv, &_Dmain); }\n\ + version (Solaris) int _main(int argc, char** argv) { return main(argc, argv); }\n\ + }\n\ + pragma(LDC_no_moduleinfo);\n\ + "; + + Identifier *id = Id::entrypoint; + Module *m = new Module("__entrypoint.d", id, 0, 0); + + Parser p(m, code, sizeof(code) / sizeof(code[0]), 0); + p.scanloc = Loc(); + p.nextToken(); + m->members = p.parseModule(); + assert(p.token.value == TOKeof); + + char v = global.params.verbose; + global.params.verbose = 0; + m->importedFrom = m; + m->importAll(0); + m->semantic(); + m->semantic2(); + m->semantic3(); + global.params.verbose = v; + + g_entrypointModule = m; + g_dMainModule = sc->module; +} + +namespace { +/// Emits a declaration for the given symbol, which is assumed to be of type +/// i8*, and defines a second globally visible i8* that contains the address +/// of the first symbol. +void emitSymbolAddrGlobal(llvm::Module &lm, const char *symbolName, + const char *addrName) { + llvm::Type *voidPtr = + llvm::PointerType::get(llvm::Type::getInt8Ty(lm.getContext()), 0); + llvm::GlobalVariable *targetSymbol = new llvm::GlobalVariable( + lm, voidPtr, false, llvm::GlobalValue::ExternalWeakLinkage, 0, + symbolName); + new llvm::GlobalVariable( + lm, voidPtr, false, llvm::GlobalValue::ExternalLinkage, + llvm::ConstantExpr::getBitCast(targetSymbol, voidPtr), addrName); +} +} + +namespace ldc { +CodeGenerator::CodeGenerator(llvm::LLVMContext &context, bool singleObj) + : context_(context), moduleCount_(0), singleObj_(singleObj), ir_(0), + firstModuleObjfileName_(0) { + if (!ClassDeclaration::object) { + error(Loc(), "declaration for class Object not found; druntime not " + "configured properly"); + fatal(); + } +} + +CodeGenerator::~CodeGenerator() { + if (singleObj_) { + const char *oname; + const char *filename; + if ((oname = global.params.exefile) || + (oname = global.params.objname)) { + filename = FileName::forceExt(oname, global.obj_ext); + if (global.params.objdir) { + filename = FileName::combine(global.params.objdir, + FileName::name(filename)); + } + } else { + filename = firstModuleObjfileName_; + } + + writeAndFreeLLModule(filename); + } +} + +void CodeGenerator::prepareLLModule(Module *m) { + if (!firstModuleObjfileName_) { + firstModuleObjfileName_ = m->objfile->name->str; + } + ++moduleCount_; + + if (singleObj_ && ir_) return; + + assert(!ir_); + + // See http://llvm.org/bugs/show_bug.cgi?id=11479 – just use the source file + // name, as it should not collide with a symbol name used somewhere in the + // module. + ir_ = new IRState(m->srcfile->toChars(), context_); + ir_->module.setTargetTriple(global.params.targetTriple.str()); + ir_->module.setDataLayout(gDataLayout->getStringRepresentation()); + + // TODO: Make ldc::DIBuilder per-Module to be able to emit several CUs for + // singleObj compilations? + ir_->DBuilder.EmitCompileUnit(m); + + IrDsymbol::resetAll(); +} + +void CodeGenerator::finishLLModule(Module *m) { + if (singleObj_) return; + + m->deleteObjFile(); + writeAndFreeLLModule(m->objfile->name->str); +} + +void CodeGenerator::writeAndFreeLLModule(const char *filename) { + ir_->DBuilder.Finalize(); + +#if LDC_LLVM_VER >= 303 + // Add the linker options metadata flag. + ir_->module.addModuleFlag( + llvm::Module::AppendUnique, "Linker Options", + llvm::MDNode::get(ir_->context(), ir_->LinkerMetadataArgs)); +#endif + +#if LDC_LLVM_VER >= 304 + // Emit ldc version as llvm.ident metadata. + llvm::NamedMDNode *IdentMetadata = + ir_->module.getOrInsertNamedMetadata("llvm.ident"); + std::string Version("ldc version "); + Version.append(global.ldc_version); +#if LDC_LLVM_VER >= 306 + llvm::Metadata *IdentNode[] = +#else + llvm::Value *IdentNode[] = +#endif + {llvm::MDString::get(ir_->context(), Version)}; + IdentMetadata->addOperand(llvm::MDNode::get(ir_->context(), IdentNode)); +#endif + + writeModule(&ir_->module, filename); + global.params.objfiles->push(const_cast(filename)); + delete ir_; + ir_ = 0; +} + +void CodeGenerator::emit(Module *m) { + bool const loggerWasEnabled = Logger::enabled(); + if (m->llvmForceLogging && !loggerWasEnabled) { + Logger::enable(); + } + + IF_LOG Logger::println("CodeGenerator::emit(%s)", m->toPrettyChars()); + LOG_SCOPE; + + if (global.params.verbose_cg) { + printf("codegen: %s (%s)\n", m->toPrettyChars(), m->srcfile->toChars()); + } + + if (global.errors) { + Logger::println("Aborting because of errors"); + fatal(); + } + + prepareLLModule(m); + + // If we are compiling to a single object file then only the first module needs + // to generate a call to _d_dso_registry(). All other modules only add a module + // reference. + // FIXME Find better name. + const bool emitFullModuleInfo = !singleObj_ || (singleObj_ && moduleCount_ == 1); + codegenModule(ir_, m, emitFullModuleInfo); + if (m == g_dMainModule) { + codegenModule(ir_, g_entrypointModule, emitFullModuleInfo); + + // On Linux, strongly define the excecutabe BSS bracketing symbols in + // the main module for druntime use (see rt.sections_linux). + if (global.params.isLinux) { + emitSymbolAddrGlobal(ir_->module, "__bss_start", + "_d_execBssBegAddr"); + emitSymbolAddrGlobal(ir_->module, "_end", "_d_execBssEndAddr"); + } + } + + finishLLModule(m); + + if (m->llvmForceLogging && !loggerWasEnabled) { + Logger::disable(); + } +} +} diff --git a/driver/codegenerator.h b/driver/codegenerator.h new file mode 100644 index 00000000000..359083e3b18 --- /dev/null +++ b/driver/codegenerator.h @@ -0,0 +1,46 @@ +//===-- driver/codegenerator.h - D module codegen entry point ---*- C++ -*-===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// +// +// Contains ldc::CodeGenerator, which is the main entry point for emitting code +// for one or more D modules to LLVM IR and subsequently to whatever output +// format has been chosen globally. +// +// Currently reads parts of the configuration from global.params, as the code +// has been extracted straight out of main(). This should be cleaned up in the +// future. +// +//===----------------------------------------------------------------------===// + +#ifndef LDC_DRIVER_CODEGENERATOR_H +#define LDC_DRIVER_CODEGENERATOR_H + +#include "gen/irstate.h" + +namespace ldc { + +class CodeGenerator { +public: + CodeGenerator(llvm::LLVMContext &context, bool singleObj); + ~CodeGenerator(); + void emit(Module *m); + +private: + void prepareLLModule(Module *m); + void finishLLModule(Module *m); + void writeAndFreeLLModule(const char *filename); + + llvm::LLVMContext &context_; + int moduleCount_; + bool const singleObj_; + IRState *ir_; + const char *firstModuleObjfileName_; +}; +} + +#endif diff --git a/driver/linker.cpp b/driver/linker.cpp index 31ef93283ee..1d26cfde413 100644 --- a/driver/linker.cpp +++ b/driver/linker.cpp @@ -18,11 +18,6 @@ #include "gen/optimizer.h" #include "gen/programs.h" #include "llvm/ADT/Triple.h" -#if LDC_LLVM_VER >= 305 -#include "llvm/Linker/Linker.h" -#else -#include "llvm/Linker.h" -#endif #include "llvm/Support/FileSystem.h" #include "llvm/Support/Program.h" #include "llvm/Support/Path.h" diff --git a/driver/main.cpp b/driver/main.cpp index 267ad55bb94..5694ef0abfa 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -21,11 +21,11 @@ #include "scope.h" #include "dmd2/target.h" #include "driver/cl_options.h" +#include "driver/codegenerator.h" #include "driver/configfile.h" #include "driver/ldc-version.h" #include "driver/linker.h" #include "driver/targetmachine.h" -#include "driver/toobj.h" #include "gen/cl_helpers.h" #include "gen/irstate.h" #include "gen/linkage.h" @@ -40,11 +40,6 @@ #include "llvm/InitializePasses.h" #endif #include "llvm/LinkAllPasses.h" -#if LDC_LLVM_VER >= 305 -#include "llvm/Linker/Linker.h" -#else -#include "llvm/Linker.h" -#endif #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" #include "llvm/Support/ManagedStatic.h" @@ -865,105 +860,52 @@ static void dumpPredefinedVersions() } } -static Module *entrypoint = NULL; -static Module *rootHasMain = NULL; - -/// Callback to generate a C main() function, invoked by the frontend. -void genCmain(Scope *sc) +/// Emits the .json AST description file. +/// +/// This (ugly) piece of code has been taken from DMD's mars.c and should be +/// kept in sync with the former. +static void emitJson(Modules &modules) { - if (entrypoint) - return; - - /* The D code to be generated is provided as D source code in the form of a string. - * Note that Solaris, for unknown reasons, requires both a main() and an _main() - */ - static utf8_t code[] = "extern(C) {\n\ - int _d_run_main(int argc, char **argv, void* mainFunc);\n\ - int _Dmain(char[][] args);\n\ - int main(int argc, char **argv) { return _d_run_main(argc, argv, &_Dmain); }\n\ - version (Solaris) int _main(int argc, char** argv) { return main(argc, argv); }\n\ - }\n\ - pragma(LDC_no_moduleinfo);\n\ - "; - - Identifier *id = Id::entrypoint; - Module *m = new Module("__entrypoint.d", id, 0, 0); - - Parser p(m, code, sizeof(code) / sizeof(code[0]), 0); - p.scanloc = Loc(); - p.nextToken(); - m->members = p.parseModule(); - assert(p.token.value == TOKeof); - - char v = global.params.verbose; - global.params.verbose = 0; - m->importedFrom = m; - m->importAll(NULL); - m->semantic(); - m->semantic2(); - m->semantic3(); - global.params.verbose = v; - - entrypoint = m; - rootHasMain = sc->module; -} + OutBuffer buf; + json_generate(&buf, &modules); -/// Emits a declaration for the given symbol, which is assumed to be of type -/// i8*, and defines a second globally visible i8* that contains the address -/// of the first symbol. -static void emitSymbolAddrGlobal(llvm::Module& lm, const char* symbolName, - const char* addrName) -{ - llvm::Type* voidPtr = llvm::PointerType::get( - llvm::Type::getInt8Ty(lm.getContext()), 0); - llvm::GlobalVariable* targetSymbol = new llvm::GlobalVariable( - lm, voidPtr, false, llvm::GlobalValue::ExternalWeakLinkage, - NULL, symbolName - ); - new llvm::GlobalVariable(lm, voidPtr, false, - llvm::GlobalValue::ExternalLinkage, - llvm::ConstantExpr::getBitCast(targetSymbol, voidPtr), - addrName - ); -} + // Write buf to file + const char *name = global.params.jsonfilename; -/// Adds the __entrypoint module and related support code into the given LLVM -/// module. This assumes that genCmain() has already been called. -static void emitEntryPointInto(llvm::Module* lm) -{ - assert(entrypoint && "Entry point Dmodule has not been generated."); -#if LDC_LLVM_VER >= 303 - llvm::Linker linker(lm); -#else - llvm::Linker linker("ldc", lm); -#endif + if (name && name[0] == '-' && name[1] == 0) + { // Write to stdout; assume it succeeds + (void)fwrite(buf.data, 1, buf.offset, stdout); + } + else + { + /* The filename generation code here should be harmonized with Module::setOutfile() + */ + const char *jsonfilename; - llvm::LLVMContext& context = lm->getContext(); - llvm::Module* entryModule = entrypoint->genLLVMModule(context); + if (name && *name) + { + jsonfilename = FileName::defaultExt(name, global.json_ext); + } + else + { + // Generate json file name from first obj name + const char *n = (*global.params.objfiles)[0]; + n = FileName::name(n); - // On Linux, strongly define the excecutabe BSS bracketing symbols in the - // main module for druntime use (see rt.sections_linux). - if (global.params.isLinux) - { - emitSymbolAddrGlobal(*entryModule, "__bss_start", "_d_execBssBegAddr"); - emitSymbolAddrGlobal(*entryModule, "_end", "_d_execBssEndAddr"); - } + //if (!FileName::absolute(name)) + //name = FileName::combine(dir, name); -#if LDC_LLVM_VER >= 306 - // FIXME: A possible error message is written to the diagnostic context - // Do we show these messages? - linker.linkInModule(entryModule); -#else - std::string linkError; -#if LDC_LLVM_VER >= 303 - const bool hadError = linker.linkInModule(entryModule, &linkError); -#else - const bool hadError = linker.LinkInModule(entryModule, &linkError); - linker.releaseModule(); -#endif - if (hadError) - error(Loc(), "%s", linkError.c_str()); -#endif + jsonfilename = FileName::forceExt(n, global.json_ext); + } + + ensurePathToNameExists(Loc(), jsonfilename); + + File *jsonfile = new File(jsonfilename); + + jsonfile->setbuffer(buf.data, buf.offset); + jsonfile->ref = 1; + writeFile(Loc(), jsonfile); + } } @@ -1325,175 +1267,42 @@ int main(int argc, char **argv) // the user requested it. if (global.params.moduleDepsFile != NULL) { - assert (global.params.moduleDepsFile != NULL); - File deps(global.params.moduleDepsFile); OutBuffer* ob = global.params.moduleDeps; deps.setbuffer(static_cast(ob->data), ob->offset); deps.write(); } - // collects llvm modules to be linked if singleobj is passed - std::vector llvmModules; - llvm::LLVMContext& context = llvm::getGlobalContext(); - - // Generate output files - for (unsigned i = 0; i < modules.dim; i++) + // Generate one or more object/IR/bitcode files. + if (global.params.obj && !modules.empty()) { - Module *m = modules[i]; - if (global.params.verbose) - fprintf(global.stdmsg, "code %s\n", m->toChars()); - if (global.params.obj) + ldc::CodeGenerator cg(llvm::getGlobalContext(), singleObj); + + for (unsigned i = 0; i < modules.dim; i++) { - llvm::Module* lm = m->genLLVMModule(context); + Module * const m = modules[i]; + if (global.params.verbose) + fprintf(global.stdmsg, "code %s\n", m->toChars()); + + cg.emit(m); if (global.errors) fatal(); - - if (entrypoint && rootHasMain == m) - emitEntryPointInto(lm); - - if (!singleObj) - { - m->deleteObjFile(); - writeModule(lm, m->objfile->name->str); - global.params.objfiles->push(const_cast(m->objfile->name->str)); - delete lm; - } - else - { - llvmModules.push_back(lm); - } } - if (global.params.doDocComments) - gendocfile(m); } - // internal linking for singleobj - if (singleObj && llvmModules.size() > 0) + // Generate DDoc output files. + if (global.params.doDocComments) { - Module *m = modules[0]; - - const char* oname; - const char* filename; - if ((oname = global.params.exefile) || (oname = global.params.objname)) - { - filename = FileName::forceExt(oname, global.obj_ext); - if (global.params.objdir) - { - filename = FileName::combine(global.params.objdir, FileName::name(filename)); - } - } - else - filename = m->objfile->name->str; - -#if 1 - // Temporary workaround for http://llvm.org/bugs/show_bug.cgi?id=11479. - char* moduleName = const_cast(filename); -#else - char* moduleName = m->toChars(); -#endif - -#if LDC_LLVM_VER >= 306 - llvm::Linker linker(llvmModules[0]); -#elif LDC_LLVM_VER >= 303 - llvm::Linker linker(new llvm::Module(moduleName, context)); -#else - llvm::Linker linker("ldc", moduleName, context); -#endif - - std::string errormsg; -#if LDC_LLVM_VER >= 306 - for (size_t i = 1; i < llvmModules.size(); i++) -#else - for (size_t i = 0; i < llvmModules.size(); i++) -#endif + for (unsigned i = 0; i < modules.dim; i++) { -#if LDC_LLVM_VER >= 306 - // Issue #855: There seems to be a problem with identified structs. - // If a module imports a class or struct from another module and - // both modules are compiled together then both modules use the - // same type object. The error happens if the type is already - // remapped in one module and then the other module is linked. - // The workaround seems to be to do the linking twice, always - // uniquing all identified structs. - // - // This replaces the line: - // linker.linkInModule(llvmModules[i]); - // - // TODO: Check LLVM bug database if this is a bug. - llvm::Linker dummy(new llvm::Module("dummy module", context)); - dummy.linkInModule(llvmModules[i]); - linker.linkInModule(dummy.getModule()); - dummy.deleteModule(); -#else -#if LDC_LLVM_VER >= 303 - if (linker.linkInModule(llvmModules[i], &errormsg)) -#else - if (linker.LinkInModule(llvmModules[i], &errormsg)) -#endif - error(Loc(), "%s", errormsg.c_str()); -#endif - delete llvmModules[i]; + gendocfile(modules[i]); } - - m->deleteObjFile(); - writeModule(linker.getModule(), filename); - global.params.objfiles->push(const_cast(filename)); - -#if LDC_LLVM_VER >= 304 - linker.deleteModule(); -#elif LDC_LLVM_VER == 303 - delete linker.getModule(); -#endif } - // output json file + // Generate the AST-describing JSON file. if (global.params.doJsonGeneration) - { - OutBuffer buf; - json_generate(&buf, &modules); - - // Write buf to file - const char *name = global.params.jsonfilename; - - if (name && name[0] == '-' && name[1] == 0) - { // Write to stdout; assume it succeeds - (void)fwrite(buf.data, 1, buf.offset, stdout); - } - else - { - /* The filename generation code here should be harmonized with Module::setOutfile() - */ - - const char *jsonfilename; - - if (name && *name) - { - jsonfilename = FileName::defaultExt(name, global.json_ext); - } - else - { - // Generate json file name from first obj name - const char *n = (*global.params.objfiles)[0]; - n = FileName::name(n); - - //if (!FileName::absolute(name)) - //name = FileName::combine(dir, name); - - jsonfilename = FileName::forceExt(n, global.json_ext); - } - - ensurePathToNameExists(Loc(), jsonfilename); - - File *jsonfile = new File(jsonfilename); - - jsonfile->setbuffer(buf.data, buf.offset); - jsonfile->ref = 1; - writeFile(Loc(), jsonfile); - } - } - + emitJson(modules); LLVM_D_FreeRuntime(); llvm::llvm_shutdown(); @@ -1501,6 +1310,8 @@ int main(int argc, char **argv) if (global.errors) fatal(); + // Finally, produce the final executable/archive and run it, if we are + // supposed to. int status = EXIT_SUCCESS; if (!global.params.objfiles->dim) { @@ -1520,8 +1331,7 @@ int main(int argc, char **argv) { status = runExecutable(); - /* Delete .obj files and .exe file - */ + /// Delete .obj files and .exe file. for (unsigned i = 0; i < modules.dim; i++) { modules[i]->deleteObjFile(); diff --git a/gen/arrays.cpp b/gen/arrays.cpp index b8dda90aad4..f558c809e0a 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -376,7 +376,7 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit) // we need to make a global with the data, so we have a pointer to the array // Important: don't make the gvar constant, since this const initializer might // be used as an initializer for a static T[] - where modifying contents is allowed. - LLGlobalVariable* gvar = new LLGlobalVariable(*gIR->module, constarr->getType(), false, LLGlobalValue::InternalLinkage, constarr, ".constarray"); + LLGlobalVariable* gvar = new LLGlobalVariable(gIR->module, constarr->getType(), false, LLGlobalValue::InternalLinkage, constarr, ".constarray"); if (arrty->ty == Tpointer) // we need to return pointer to the static array. @@ -472,7 +472,7 @@ void initializeArrayLiteral(IRState* p, ArrayLiteralExp* ale, LLValue* dstMem) else { llvm::GlobalVariable* gvar = new llvm::GlobalVariable( - *gIR->module, + gIR->module, constarr->getType(), true, LLGlobalValue::InternalLinkage, diff --git a/gen/classes.cpp b/gen/classes.cpp index c652edb7828..2efc32c4052 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -501,7 +501,7 @@ static LLConstant* build_offti_array(ClassDeclaration* cd, LLType* arrayT) LLConstant* arrInit = LLConstantArray::get(arrTy, arrayInits); // create symbol - llvm::GlobalVariable* gvar = getOrCreateGlobal(cd->loc, *gIR->module, arrTy, + llvm::GlobalVariable* gvar = getOrCreateGlobal(cd->loc, gIR->module, arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit, ".offti"); ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType())); diff --git a/gen/coverage.cpp b/gen/coverage.cpp index 0a7af5a504f..bef1df98dd3 100644 --- a/gen/coverage.cpp +++ b/gen/coverage.cpp @@ -17,39 +17,38 @@ void emitCoverageLinecountInc(Loc &loc) { // Only emit coverage increment for locations in the source of the current module // (for example, 'inlined' methods from other source files should be skipped). - if ( global.params.cov && (loc.linnum != 0) && loc.filename - && (gIR->module->getModuleIdentifier().compare(loc.filename) == 0) ) - { - unsigned line = loc.linnum-1; // convert to 0-based line# index - assert(line < gIR->dmodule->numlines); - { - IF_LOG Logger::println("Coverage: increment _d_cover_data[%d]", line); - - // Get GEP into _d_cover_data array - LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(line) }; - LLValue* ptr = llvm::ConstantExpr::getGetElementPtr( + if (!global.params.cov || !loc.linnum || !loc.filename || + strcmp(gIR->dmodule->srcfile->name->toChars(), loc.filename) != 0) { + return; + } + + const unsigned line = loc.linnum - 1; // convert to 0-based line# index + assert(line < gIR->dmodule->numlines); + + IF_LOG Logger::println("Coverage: increment _d_cover_data[%d]", line); + LOG_SCOPE; + + // Get GEP into _d_cover_data array + LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(line) }; + LLValue* ptr = llvm::ConstantExpr::getGetElementPtr( #if LDC_LLVM_VER >= 307 - LLArrayType::get(LLType::getInt32Ty(gIR->context()), gIR->dmodule->numlines), + LLArrayType::get(LLType::getInt32Ty(gIR->context()), gIR->dmodule->numlines), #endif - gIR->dmodule->d_cover_data, idxs, true); - - // Do an atomic increment, so this works when multiple threads are executed. - gIR->ir->CreateAtomicRMW( - llvm::AtomicRMWInst::Add, - ptr, - DtoConstUint(1), - llvm::Monotonic - ); - } - - { - unsigned num_sizet_bits = gDataLayout->getTypeSizeInBits(DtoSize_t()); - unsigned idx = line / num_sizet_bits; - unsigned bitidx = line % num_sizet_bits; - - IF_LOG Logger::println(" _d_cover_valid[%d] |= (1 << %d)", idx, bitidx); - - gIR->dmodule->d_cover_valid_init[idx] |= (size_t(1) << bitidx); - } - } -} \ No newline at end of file + gIR->dmodule->d_cover_data, idxs, true); + + // Do an atomic increment, so this works when multiple threads are executed. + gIR->ir->CreateAtomicRMW( + llvm::AtomicRMWInst::Add, + ptr, + DtoConstUint(1), + llvm::Monotonic + ); + + unsigned num_sizet_bits = gDataLayout->getTypeSizeInBits(DtoSize_t()); + unsigned idx = line / num_sizet_bits; + unsigned bitidx = line % num_sizet_bits; + + IF_LOG Logger::println("_d_cover_valid[%d] |= (1 << %d)", idx, bitidx); + + gIR->dmodule->d_cover_valid_init[idx] |= (size_t(1) << bitidx); +} diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 2a8323cf54b..bcb3949b79b 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -256,7 +256,7 @@ class CodegenVisitor : public Visitor { if (initVal->getType() != gvar->getType()->getElementType()) { llvm::GlobalVariable* newGvar = getOrCreateGlobal(decl->loc, - *irs->module, initVal->getType(), gvar->isConstant(), + irs->module, initVal->getType(), gvar->isConstant(), llLinkage, 0, "", // We take on the name of the old global below. gvar->isThreadLocal()); diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index 53dffe2c335..afee1c61600 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -53,8 +53,8 @@ Module *ldc::DIBuilder::getDefinedModule(Dsymbol *s) //////////////////////////////////////////////////////////////////////////////// -ldc::DIBuilder::DIBuilder(IRState *const IR, llvm::Module &M) - : IR(IR), DBuilder(M) +ldc::DIBuilder::DIBuilder(IRState *const IR) + : IR(IR), DBuilder(IR->module), CUNode(0) { } @@ -656,13 +656,16 @@ void ldc::DIBuilder::EmitCompileUnit(Module *m) Logger::println("D to dwarf compile_unit"); LOG_SCOPE; + assert(!CUNode && + "Already created compile unit for this DIBuilder instance"); + // prepare srcpath llvm::SmallString<128> srcpath(m->srcfile->name->toChars()); llvm::sys::fs::make_absolute(srcpath); #if LDC_LLVM_VER >= 304 // Metadata without a correct version will be stripped by UpgradeDebugInfo. - gIR->module->addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); + IR->module.addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); CUNode = #endif @@ -971,7 +974,7 @@ ldc::DIGlobalVariable ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *l ); } -void ldc::DIBuilder::EmitModuleEnd() +void ldc::DIBuilder::Finalize() { if (!global.params.symdebug) return; diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 1b58ae3a45a..43b4196fd01 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -127,7 +127,7 @@ class DIBuilder } public: - DIBuilder(IRState *const IR, llvm::Module &M); + DIBuilder(IRState *const IR); /// \brief Emit the Dwarf compile_unit global for a Module m. /// \param m Module to emit as compile unit. @@ -183,7 +183,7 @@ class DIBuilder /// \param vd Variable declaration to emit debug info for. DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd); // FIXME - void EmitModuleEnd(); + void Finalize(); private: llvm::LLVMContext &getContext(); diff --git a/gen/functions.cpp b/gen/functions.cpp index 12641f3cb4d..1eca05883b0 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "gen/functions.h" + #include "aggregate.h" #include "declaration.h" #include "id.h" @@ -20,6 +21,7 @@ #include "gen/arrays.h" #include "gen/classes.h" #include "gen/dvalue.h" +#include "gen/inlineir.h" #include "gen/irstate.h" #include "gen/linkage.h" #include "gen/llvm.h" @@ -30,11 +32,7 @@ #include "gen/pragma.h" #include "gen/runtime.h" #include "gen/tollvm.h" -#if LDC_LLVM_VER >= 305 -#include "llvm/Linker/Linker.h" -#else -#include "llvm/Linker.h" -#endif +#include "ir/irmodule.h" #if LDC_LLVM_VER >= 303 #include "llvm/IR/Intrinsics.h" #else @@ -224,114 +222,6 @@ llvm::FunctionType* DtoFunctionType(Type* type, IrFuncTy &irFty, Type* thistype, ////////////////////////////////////////////////////////////////////////////////////////// -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/SourceMgr.h" -#if LDC_LLVM_VER >= 305 -#include "llvm/AsmParser/Parser.h" -#else -#include "llvm/Assembly/Parser.h" -#endif - -LLFunction* DtoInlineIRFunction(FuncDeclaration* fdecl) -{ - const char* mangled_name = mangleExact(fdecl); - TemplateInstance* tinst = fdecl->parent->isTemplateInstance(); - assert(tinst); - - Objects& objs = tinst->tdtypes; - assert(objs.dim == 3); - - Expression* a0 = isExpression(objs[0]); - assert(a0); - StringExp* strexp = a0->toStringExp(); - assert(strexp); - assert(strexp->sz == 1); - std::string code(static_cast(strexp->string), strexp->len); - - Type* ret = isType(objs[1]); - assert(ret); - - Tuple* a2 = isTuple(objs[2]); - assert(a2); - Objects& arg_types = a2->objects; - - std::string str; - llvm::raw_string_ostream stream(str); - stream << "define " << *DtoType(ret) << " @" << mangled_name << "("; - - for(size_t i = 0; ;) - { - Type* ty = isType(arg_types[i]); - //assert(ty); - if(!ty) - { - error(tinst->loc, - "All parameters of a template defined with pragma llvm_inline_ir, except for the first one, should be types"); - fatal(); - } - stream << *DtoType(ty); - - i++; - if(i >= arg_types.dim) - break; - - stream << ", "; - } - - if(ret->ty == Tvoid) - code.append("\nret void"); - - stream << ")\n{\n" << code << "\n}"; - - llvm::SMDiagnostic err; - -#if LDC_LLVM_VER >= 306 - std::unique_ptr m = llvm::parseAssemblyString( - stream.str().c_str(), err, gIR->context()); -#elif LDC_LLVM_VER >= 303 - llvm::Module* m = llvm::ParseAssemblyString( - stream.str().c_str(), NULL, err, gIR->context()); -#else - llvm::ParseAssemblyString( - stream.str().c_str(), gIR->module, err, gIR->context()); -#endif - - std::string errstr = err.getMessage(); - if(errstr != "") - error(tinst->loc, - "can't parse inline LLVM IR:\n%s\n%s\n%s\nThe input string was: \n%s", -#if LDC_LLVM_VER >= 303 - err.getLineContents().str().c_str(), -#else - err.getLineContents().c_str(), -#endif - (std::string(err.getColumnNo(), ' ') + '^').c_str(), - errstr.c_str(), stream.str().c_str()); - -#if LDC_LLVM_VER >= 306 - llvm::Linker(gIR->module).linkInModule(m.get()); -#else -#if LDC_LLVM_VER >= 303 - std::string errstr2 = ""; -#if LDC_LLVM_VER >= 306 - llvm::Linker(gIR->module).linkInModule(m.get(), &errstr2); -#else - llvm::Linker(gIR->module).linkInModule(m, &errstr2); -#endif - if(errstr2 != "") - error(tinst->loc, - "Error when linking in llvm inline ir: %s", errstr2.c_str()); -#endif -#endif - - LLFunction* fun = gIR->module->getFunction(mangled_name); - fun->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); - fun->addFnAttr(LDC_ATTRIBUTE(AlwaysInline)); - return fun; -} - -////////////////////////////////////////////////////////////////////////////////////////// - static llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl) { IrFuncTy &irFty = getIrFunc(fdecl, true)->irFty; @@ -595,7 +485,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) // construct function LLFunctionType* functype = DtoFunctionType(fdecl); - LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName); + LLFunction* func = vafunc ? vafunc : gIR->module.getFunction(mangledName); if (!func) { if(fdecl->llvmInternal == LLVMinline_ir) { @@ -606,7 +496,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) // All function declarations are "external" - any other linkage type // is set when actually defining the function. func = LLFunction::Create(functype, - llvm::GlobalValue::ExternalLinkage, mangledName, gIR->module); + llvm::GlobalValue::ExternalLinkage, mangledName, &gIR->module); } } else if (func->getFunctionType() != functype) { error(fdecl->loc, "Function type does not match previously declared function with the same mangled name: %s", mangleExact(fdecl)); @@ -835,19 +725,21 @@ void DtoDefineFunction(FuncDeclaration* fd) assert(fd->ident != Id::empty); if (fd->isUnitTestDeclaration()) { - gIR->unitTests.push_back(fd); + getIrModule(gIR->dmodule)->unitTests.push_back(fd); } else if (fd->isSharedStaticCtorDeclaration()) { - gIR->sharedCtors.push_back(fd); + getIrModule(gIR->dmodule)->sharedCtors.push_back(fd); } else if (StaticDtorDeclaration *dtorDecl = fd->isSharedStaticDtorDeclaration()) { - gIR->sharedDtors.push_front(fd); - if (dtorDecl->vgate) - gIR->sharedGates.push_front(dtorDecl->vgate); + getIrModule(gIR->dmodule)->sharedDtors.push_front(fd); + if (dtorDecl->vgate) { + getIrModule(gIR->dmodule)->sharedGates.push_front(dtorDecl->vgate); + } } else if (fd->isStaticCtorDeclaration()) { - gIR->ctors.push_back(fd); + getIrModule(gIR->dmodule)->ctors.push_back(fd); } else if (StaticDtorDeclaration *dtorDecl = fd->isStaticDtorDeclaration()) { - gIR->dtors.push_front(fd); - if (dtorDecl->vgate) - gIR->gates.push_front(dtorDecl->vgate); + getIrModule(gIR->dmodule)->dtors.push_front(fd); + if (dtorDecl->vgate) { + getIrModule(gIR->dmodule)->gates.push_front(dtorDecl->vgate); + } } @@ -877,9 +769,6 @@ void DtoDefineFunction(FuncDeclaration* fd) IF_LOG Logger::println("Doing function body for: %s", fd->toChars()); gIR->functions.push_back(irFunc); - if (fd->isMain()) - gIR->emitMain = true; - func->setLinkage(lowerFuncLinkage(fd)); // On x86_64, always set 'uwtable' for System V ABI compatibility. diff --git a/gen/inlineir.cpp b/gen/inlineir.cpp new file mode 100644 index 00000000000..d3906fe01d6 --- /dev/null +++ b/gen/inlineir.cpp @@ -0,0 +1,107 @@ +#include "gen/inlineir.h" + +#include "declaration.h" +#include "template.h" +#include "gen/irstate.h" +#include "gen/tollvm.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#if LDC_LLVM_VER >= 305 +#include "llvm/AsmParser/Parser.h" +#include "llvm/Linker/Linker.h" +#else +#include "llvm/Assembly/Parser.h" +#include "llvm/Linker.h" +#endif + +llvm::Function* DtoInlineIRFunction(FuncDeclaration* fdecl) +{ + const char* mangled_name = mangleExact(fdecl); + TemplateInstance* tinst = fdecl->parent->isTemplateInstance(); + assert(tinst); + + Objects& objs = tinst->tdtypes; + assert(objs.dim == 3); + + Expression* a0 = isExpression(objs[0]); + assert(a0); + StringExp* strexp = a0->toStringExp(); + assert(strexp); + assert(strexp->sz == 1); + std::string code(static_cast(strexp->string), strexp->len); + + Type* ret = isType(objs[1]); + assert(ret); + + Tuple* a2 = isTuple(objs[2]); + assert(a2); + Objects& arg_types = a2->objects; + + std::string str; + llvm::raw_string_ostream stream(str); + stream << "define " << *DtoType(ret) << " @" << mangled_name << "("; + + for(size_t i = 0; ;) + { + Type* ty = isType(arg_types[i]); + //assert(ty); + if(!ty) + { + error(tinst->loc, + "All parameters of a template defined with pragma llvm_inline_ir, except for the first one, should be types"); + fatal(); + } + stream << *DtoType(ty); + + i++; + if(i >= arg_types.dim) + break; + + stream << ", "; + } + + if(ret->ty == Tvoid) + code.append("\nret void"); + + stream << ")\n{\n" << code << "\n}"; + + llvm::SMDiagnostic err; + +#if LDC_LLVM_VER >= 306 + std::unique_ptr m = llvm::parseAssemblyString( + stream.str().c_str(), err, gIR->context()); +#elif LDC_LLVM_VER >= 303 + llvm::Module* m = llvm::ParseAssemblyString( + stream.str().c_str(), NULL, err, gIR->context()); +#else + llvm::ParseAssemblyString( + stream.str().c_str(), &gIR->module, err, gIR->context()); +#endif + + std::string errstr = err.getMessage(); + if(errstr != "") + error(tinst->loc, + "can't parse inline LLVM IR:\n%s\n%s\n%s\nThe input string was: \n%s", +#if LDC_LLVM_VER >= 303 + err.getLineContents().str().c_str(), +#else + err.getLineContents().c_str(), +#endif + (std::string(err.getColumnNo(), ' ') + '^').c_str(), + errstr.c_str(), stream.str().c_str()); + +#if LDC_LLVM_VER >= 306 + llvm::Linker(&gIR->module).linkInModule(m.get()); +#elif LDC_LLVM_VER >= 303 + std::string errstr2 = ""; + llvm::Linker(&gIR->module).linkInModule(m, &errstr2); + if(errstr2 != "") + error(tinst->loc, + "Error when linking in llvm inline ir: %s", errstr2.c_str()); +#endif + + LLFunction* fun = gIR->module.getFunction(mangled_name); + fun->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); + fun->addFnAttr(LDC_ATTRIBUTE(AlwaysInline)); + return fun; +} diff --git a/gen/inlineir.h b/gen/inlineir.h new file mode 100644 index 00000000000..33caa38d98e --- /dev/null +++ b/gen/inlineir.h @@ -0,0 +1,24 @@ +//===-- gen/irstate.h - Inline IR implementation-----------------*- C++ -*-===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the implementation for the LDC-specific LLVM inline IR feature. +// +//===----------------------------------------------------------------------===// + +#ifndef LDC_GEN_INLINEIR_H +#define LDC_GEN_INLINEIR_H + +class FuncDeclaration; +namespace llvm { + class Function; +} + +llvm::Function* DtoInlineIRFunction(FuncDeclaration* fdecl); + +#endif diff --git a/gen/irstate.cpp b/gen/irstate.cpp index 2dab81a9200..dff15b94feb 100644 --- a/gen/irstate.cpp +++ b/gen/irstate.cpp @@ -67,15 +67,13 @@ IRTargetScope::IRTargetScope( } ////////////////////////////////////////////////////////////////////////////////////////// -IRState::IRState(llvm::Module* m) - : module(m), DBuilder(this, *m) +IRState::IRState(const char *name, llvm::LLVMContext &context) + : module(name, context), DBuilder(this) { - interfaceInfoType = NULL; mutexType = NULL; moduleRefType = NULL; dmodule = 0; - emitMain = false; mainFunc = 0; ir.state = this; asmBlock = NULL; @@ -93,12 +91,6 @@ llvm::Function* IRState::topfunc() return functions.back()->func; } -TypeFunction* IRState::topfunctype() -{ - assert(!functions.empty() && "Function stack is empty!"); - return functions.back()->type; -} - llvm::Instruction* IRState::topallocapoint() { assert(!functions.empty() && "AllocaPoint stack is empty!"); diff --git a/gen/irstate.h b/gen/irstate.h index 2bba0749f92..d6491253c5f 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -121,31 +121,26 @@ struct IRAsmBlock // represents the module struct IRState { - IRState(llvm::Module* m); + IRState(const char *name, llvm::LLVMContext &context); - // module - Module* dmodule; - llvm::Module* module; + llvm::Module module; + llvm::LLVMContext& context() const { return module.getContext(); } + + Module *dmodule; - // interface info type, used in DtoInterfaceInfoType - LLStructType* interfaceInfoType; LLStructType* mutexType; LLStructType* moduleRefType; - // helper to get the LLVMContext of the module - llvm::LLVMContext& context() const { return module->getContext(); } - // functions typedef std::vector FunctionVector; FunctionVector functions; IrFunction* func(); llvm::Function* topfunc(); - TypeFunction* topfunctype(); llvm::Instruction* topallocapoint(); - // D main function - bool emitMain; + // The function containing the D main() body, if any (not the actual main() + // implicitly emitted). llvm::Function* mainFunc; // basic block scopes @@ -177,17 +172,6 @@ struct IRState // debug info helper ldc::DIBuilder DBuilder; - // static ctors/dtors/unittests - typedef std::list FuncDeclList; - typedef std::list GatesList; - FuncDeclList ctors; - FuncDeclList dtors; - FuncDeclList sharedCtors; - FuncDeclList sharedDtors; - GatesList gates; - GatesList sharedGates; - FuncDeclList unitTests; - // for inline asm IRAsmBlock* asmBlock; std::ostringstream nakedAsm; diff --git a/gen/llvm.h b/gen/llvm.h index 288e6668bd8..f6af6c2ecd1 100644 --- a/gen/llvm.h +++ b/gen/llvm.h @@ -69,7 +69,7 @@ using llvm::IRBuilder; -#define GET_INTRINSIC_DECL(_X) (llvm::Intrinsic::getDeclaration(gIR->module, llvm::Intrinsic:: _X )) +#define GET_INTRINSIC_DECL(_X) (llvm::Intrinsic::getDeclaration(&gIR->module, llvm::Intrinsic:: _X )) // shortcuts for the common llvm types diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 0bbbdee4960..c310353f4fb 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -208,17 +208,8 @@ void DtoAssert(Module* M, Loc& loc, DValue* msg) LLValue *DtoModuleFileName(Module* M, const Loc& loc) { - // we might be generating for an imported template function - const char* cur_file = M->srcfile->name->toChars(); - if (loc.filename && strcmp(loc.filename, cur_file) != 0) - { - return DtoConstString(loc.filename); - } - else - { - IrModule* irmod = getIrModule(M); - return DtoLoad(irmod->fileName); - } + return DtoConstString(loc.filename ? loc.filename : + M->srcfile->name->toChars()); } /****************************************************************************************/ @@ -961,7 +952,7 @@ void DtoResolveVariable(VarDeclaration* vd) linkage = llvm::GlobalValue::ExternalWeakLinkage; } - llvm::GlobalVariable* gvar = getOrCreateGlobal(vd->loc, *gIR->module, + llvm::GlobalVariable* gvar = getOrCreateGlobal(vd->loc, gIR->module, i1ToI8(DtoType(vd->type)), isLLConst, linkage, 0, llName, vd->isThreadlocal()); getIrGlobal(vd)->value = gvar; @@ -1616,9 +1607,9 @@ void printLabelName(std::ostream& target, const char* func_mangle, const char* l void AppendFunctionToLLVMGlobalCtorsDtors(llvm::Function* func, const uint32_t priority, const bool isCtor) { if (isCtor) - llvm::appendToGlobalCtors(*gIR->module, func, priority); + llvm::appendToGlobalCtors(gIR->module, func, priority); else - llvm::appendToGlobalDtors(*gIR->module, func, priority); + llvm::appendToGlobalDtors(gIR->module, func, priority); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/logger.cpp b/gen/logger.cpp index a3e089fedc2..26769367fe7 100644 --- a/gen/logger.cpp +++ b/gen/logger.cpp @@ -45,9 +45,9 @@ void Stream::writeValue(std::ostream& OS, const llvm::Value& V) { llvm::raw_os_ostream raw(OS); if (llvm::isa(V) && !llvm::isa(V)) #if LDC_LLVM_VER >= 305 - V.printAsOperand(raw, true, gIR->module); + V.printAsOperand(raw, true, &gIR->module); #else - llvm::WriteAsOperand(raw, &V, true, gIR->module); + llvm::WriteAsOperand(raw, &V, true, &gIR->module); #endif else V.print(raw); diff --git a/gen/module.cpp b/gen/module.cpp index e987aed9331..dd8e81cd1dc 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -94,7 +94,7 @@ void Module::buildTargetFiles(bool singleObj, bool library) return; if (!objfile) { - const char *objname = library ? 0 : global.params.objname; + const char *objname = library ? 0 : global.params.objname; if (global.params.output_o) objfile = Module::buildFilePath(objname, global.params.objdir, global.params.targetTriple.isOSWindows() ? global.obj_ext_alt : global.obj_ext); @@ -168,10 +168,10 @@ File* Module::buildFilePath(const char* forcename, const char* path, const char* FileName::ensurePathExists(FileName::path(argobj)); // always append the extension! otherwise hard to make output switches consistent - // if (forcename) - // return new File(argobj); - // else - // allow for .o and .obj on windows + // if (forcename) + // return new File(argobj); + // else + // allow for .o and .obj on windows #if _WIN32 if (ext == global.params.objdir && FileName::ext(argobj) && Port::stricmp(FileName::ext(argobj), global.obj_ext_alt) == 0) @@ -195,9 +195,9 @@ static llvm::Function* build_module_function(const std::string &name, const std: LLFunctionType* fnTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); std::string const symbolName = gABI->mangleForLLVM(name, LINKd); - assert(gIR->module->getFunction(symbolName) == NULL); + assert(gIR->module.getFunction(symbolName) == NULL); llvm::Function* fn = llvm::Function::Create(fnTy, - llvm::GlobalValue::InternalLinkage, symbolName, gIR->module); + llvm::GlobalValue::InternalLinkage, symbolName, &gIR->module); fn->setCallingConv(gABI->callingConv(LINKd)); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "", fn); @@ -234,67 +234,69 @@ static llvm::Function* build_module_function(const std::string &name, const std: // build module ctor -llvm::Function* build_module_ctor() +static llvm::Function* build_module_ctor(Module *m) { std::string name("_D"); - name.append(mangle(gIR->dmodule)); + name.append(mangle(m)); name.append("6__ctorZ"); - return build_module_function(name, gIR->ctors, gIR->gates); + IrModule *irm = getIrModule(m); + return build_module_function(name, irm->ctors, irm->gates); } // build module dtor -static llvm::Function* build_module_dtor() +static llvm::Function* build_module_dtor(Module *m) { std::string name("_D"); - name.append(mangle(gIR->dmodule)); + name.append(mangle(m)); name.append("6__dtorZ"); - return build_module_function(name, gIR->dtors); + return build_module_function(name, getIrModule(m)->dtors); } // build module unittest -static llvm::Function* build_module_unittest() +static llvm::Function* build_module_unittest(Module *m) { std::string name("_D"); - name.append(mangle(gIR->dmodule)); + name.append(mangle(m)); name.append("10__unittestZ"); - return build_module_function(name, gIR->unitTests); + return build_module_function(name, getIrModule(m)->unitTests); } // build module shared ctor -llvm::Function* build_module_shared_ctor() +static llvm::Function* build_module_shared_ctor(Module *m) { std::string name("_D"); - name.append(mangle(gIR->dmodule)); + name.append(mangle(m)); name.append("13__shared_ctorZ"); - return build_module_function(name, gIR->sharedCtors, gIR->sharedGates); + IrModule *irm = getIrModule(m); + return build_module_function(name, irm->sharedCtors, irm->sharedGates); } // build module shared dtor -static llvm::Function* build_module_shared_dtor() +static llvm::Function* build_module_shared_dtor(Module *m) { std::string name("_D"); - name.append(mangle(gIR->dmodule)); + name.append(mangle(m)); name.append("13__shared_dtorZ"); - return build_module_function(name, gIR->sharedDtors); + return build_module_function(name, getIrModule(m)->sharedDtors); } // build ModuleReference and register function, to register the module info in the global linked list -static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) +static LLFunction* build_module_reference_and_ctor(const char *moduleMangle, LLConstant* moduleinfo) { // build ctor type LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); // build ctor name std::string fname = "_D"; - fname += mangle(gIR->dmodule); + fname += moduleMangle; 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); + LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, &gIR->module); // provide the default initializer LLStructType* modulerefTy = DtoModuleReferenceType(); @@ -306,17 +308,17 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) // create the ModuleReference node for this module std::string thismrefname = "_D"; - thismrefname += mangle(gIR->dmodule); + thismrefname += moduleMangle; thismrefname += "11__moduleRefZ"; Loc loc; - LLGlobalVariable* thismref = getOrCreateGlobal(loc, *gIR->module, + LLGlobalVariable* thismref = getOrCreateGlobal(loc, gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, thismrefname); // make sure _Dmodule_ref is declared - LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref"); + 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 = 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 @@ -419,7 +421,28 @@ static void build_dso_ctor_dtor_body( } } -static void build_dso_registry_calls(llvm::Constant* thisModuleInfo) +static void build_module_ref(std::string moduleMangle, llvm::Constant* thisModuleInfo) +{ + // Build the ModuleInfo reference and bracketing symbols. + llvm::Type* const moduleInfoPtrTy = + getPtrToType(DtoType(Module::moduleinfo->type)); + + std::string thismrefname = "_D"; + thismrefname += moduleMangle; + thismrefname += "11__moduleRefZ"; + llvm::GlobalVariable* thismref = new llvm::GlobalVariable( + gIR->module, + moduleInfoPtrTy, + false, // FIXME: mRelocModel != llvm::Reloc::PIC_ + llvm::GlobalValue::LinkOnceODRLinkage, + DtoBitCast(thisModuleInfo, moduleInfoPtrTy), + thismrefname + ); + thismref->setSection(".minfo"); + gIR->usedArray.push_back(thismref); +} + +static void build_dso_registry_calls(std::string moduleMangle, llvm::Constant* thisModuleInfo) { // Build the ModuleInfo reference and bracketing symbols. llvm::Type* const moduleInfoPtrTy = @@ -429,7 +452,7 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo) // bracketing sections right before/after the ModuleInfo reference // so that they end up in the correct order in the object file. llvm::GlobalVariable* minfoBeg = new llvm::GlobalVariable( - *gIR->module, + gIR->module, moduleInfoPtrTy, false, // FIXME: mRelocModel != llvm::Reloc::PIC_ llvm::GlobalValue::LinkOnceODRLinkage, @@ -440,10 +463,10 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo) minfoBeg->setVisibility(llvm::GlobalValue::HiddenVisibility); std::string thismrefname = "_D"; - thismrefname += mangle(gIR->dmodule); + thismrefname += moduleMangle; thismrefname += "11__moduleRefZ"; llvm::GlobalVariable* thismref = new llvm::GlobalVariable( - *gIR->module, + gIR->module, moduleInfoPtrTy, false, // FIXME: mRelocModel != llvm::Reloc::PIC_ llvm::GlobalValue::LinkOnceODRLinkage, @@ -454,7 +477,7 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo) gIR->usedArray.push_back(thismref); llvm::GlobalVariable* minfoEnd = new llvm::GlobalVariable( - *gIR->module, + gIR->module, moduleInfoPtrTy, false, // FIXME: mRelocModel != llvm::Reloc::PIC_ llvm::GlobalValue::LinkOnceODRLinkage, @@ -468,7 +491,7 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo) // This is the DSO slot for use by the druntime implementation. llvm::GlobalVariable* dsoSlot = new llvm::GlobalVariable( - *gIR->module, + gIR->module, getVoidPtrType(), false, llvm::GlobalValue::LinkOnceODRLinkage, @@ -507,7 +530,7 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo) // directly using e.g. "g++ dcode.o cppcode.o", though. llvm::GlobalVariable* dsoInitialized = new llvm::GlobalVariable( - *gIR->module, + gIR->module, llvm::Type::getInt8Ty(gIR->context()), false, llvm::GlobalValue::LinkOnceODRLinkage, @@ -524,26 +547,28 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo) llvm::Value* minfoRefPtr = DtoBitCast(thismref, getVoidPtrType()); std::string ctorName = "ldc.dso_ctor."; - ctorName += mangle(gIR->dmodule); + ctorName += moduleMangle; llvm::Function* dsoCtor = llvm::Function::Create( llvm::FunctionType::get(llvm::Type::getVoidTy(gIR->context()), false), llvm::GlobalValue::LinkOnceODRLinkage, ctorName, - gIR->module + &gIR->module ); dsoCtor->setVisibility(llvm::GlobalValue::HiddenVisibility); build_dso_ctor_dtor_body(dsoCtor, dsoInitialized, dsoSlot, minfoBeg, minfoEnd, minfoRefPtr, false); - llvm::appendToGlobalCtors(*gIR->module, dsoCtor, 65535); + llvm::appendToGlobalCtors(gIR->module, dsoCtor, 65535); + std::string dtorName = "ldc.dso_dtor."; + dtorName += moduleMangle; llvm::Function* dsoDtor = llvm::Function::Create( llvm::FunctionType::get(llvm::Type::getVoidTy(gIR->context()), false), llvm::GlobalValue::LinkOnceODRLinkage, - "ldc.dso_dtor", - gIR->module + dtorName, + &gIR->module ); dsoDtor->setVisibility(llvm::GlobalValue::HiddenVisibility); build_dso_ctor_dtor_body(dsoDtor, dsoInitialized, dsoSlot, minfoBeg, minfoEnd, minfoRefPtr, true); - llvm::appendToGlobalDtors(*gIR->module, dsoDtor, 65535); + llvm::appendToGlobalDtors(gIR->module, dsoDtor, 65535); } static void build_llvm_used_array(IRState* p) @@ -562,7 +587,7 @@ static void build_llvm_used_array(IRState* p) llvm::ArrayType *arrayType = llvm::ArrayType::get( getVoidPtrType(), usedVoidPtrs.size()); llvm::GlobalVariable* llvmUsed = new llvm::GlobalVariable( - *p->module, + p->module, arrayType, false, llvm::GlobalValue::AppendingLinkage, @@ -591,11 +616,11 @@ static void addCoverageAnalysis(Module* m) // For safety, make the array large enough such that the slice passed to _d_cover_register2 is completely valid. array_size = m->numlines; - IF_LOG Logger::println("Build private variable: size_t[%llu] _d_cover_valid", (ulonglong) array_size); + IF_LOG Logger::println("Build private variable: size_t[%llu] _d_cover_valid", static_cast(array_size)); llvm::ArrayType* type = llvm::ArrayType::get(DtoSize_t(), array_size); llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type); - m->d_cover_valid = new llvm::GlobalVariable(*gIR->module, type, true, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_valid"); + m->d_cover_valid = new llvm::GlobalVariable(gIR->module, type, true, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_valid"); LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) }; d_cover_valid_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), llvm::ConstantExpr::getGetElementPtr( @@ -616,7 +641,7 @@ static void addCoverageAnalysis(Module* m) LLArrayType* type = LLArrayType::get(LLType::getInt32Ty(gIR->context()), m->numlines); llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type); - m->d_cover_data = new llvm::GlobalVariable(*gIR->module, type, false, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_data"); + m->d_cover_data = new llvm::GlobalVariable(gIR->module, type, false, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_data"); LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) }; d_cover_data_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()), llvm::ConstantExpr::getGetElementPtr( @@ -630,13 +655,13 @@ static void addCoverageAnalysis(Module* m) // Build ctor name LLFunction* ctor = NULL; std::string ctorname = "_D"; - ctorname += mangle(gIR->dmodule); + ctorname += mangle(m); ctorname += "12_coverageanalysisCtor1FZv"; { IF_LOG Logger::println("Build Coverage Analysis constructor: %s", ctorname.c_str()); LLFunctionType* ctorTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); - ctor = LLFunction::Create(ctorTy, LLGlobalValue::InternalLinkage, ctorname, gIR->module); + ctor = LLFunction::Create(ctorTy, LLGlobalValue::InternalLinkage, ctorname, &gIR->module); ctor->setCallingConv(gABI->callingConv(LINKd)); // Set function attributes. See functions.cpp:DtoDefineFunction() if (global.params.targetTriple.getArch() == llvm::Triple::x86_64) @@ -650,7 +675,7 @@ static void addCoverageAnalysis(Module* m) // Set up call to _d_cover_register2 llvm::Function* fn = LLVM_D_GetRuntimeFunction(Loc(), gIR->module, "_d_cover_register2"); LLValue* args[] = { - getIrModule(m)->fileName->getInitializer(), + DtoConstString(m->srcfile->name->toChars()), d_cover_valid_slice, d_cover_data_slice, DtoConstUbyte(global.params.covPercent) @@ -660,7 +685,7 @@ static void addCoverageAnalysis(Module* m) assert(args[i]->getType() == fn->getFunctionType()->getParamType(i)); } - llvm::CallInst* call = builder.CreateCall(fn, args); + builder.CreateCall(fn, args); builder.CreateRetVoid(); } @@ -672,7 +697,7 @@ static void addCoverageAnalysis(Module* m) fd->linkage = LINKd; IrFunction* irfunc = getIrFunc(fd, true); irfunc->func = ctor; - gIR->sharedCtors.push_back(fd); + getIrModule(m)->sharedCtors.push_back(fd); } IF_LOG Logger::undent(); @@ -693,216 +718,96 @@ static void addCoverageAnalysisInitializer(Module* m) { m->d_cover_valid->setInitializer(llvm::ConstantArray::get(type, arrayInits)); } -static void codegenModule(Module* m) +static void genModuleInfo(Module *m, bool emitFullModuleInfo); + +void codegenModule(IRState *irs, Module* m, bool emitFullModuleInfo) { - // debug info - gIR->DBuilder.EmitCompileUnit(m); + assert(!irs->dmodule && "irs->module not null, codegen already in progress?!"); + irs->dmodule = m; + assert(!gIR && "gIR not null, codegen already in progress?!"); + gIR = irs; + + LLVM_D_InitRuntime(); + + // Skip pseudo-modules for coverage analysis + std::string name = m->toChars(); + if (global.params.cov && name != "__entrypoint" && name != "__main") + { + addCoverageAnalysis(m); + } // process module members - for (unsigned k=0; k < m->members->dim; k++) { + for (unsigned k=0; k < m->members->dim; k++) + { Dsymbol* dsym = (*m->members)[k]; assert(dsym); Declaration_codegen(dsym); } - if (global.errors) return; + if (global.errors) fatal(); // Skip emission of all the additional module metadata if requested by the user. if (!m->noModuleInfo) { // generate ModuleInfo - m->genmoduleinfo(); - - build_llvm_used_array(gIR); - - #if LDC_LLVM_VER >= 303 - // Add the linker options metadata flag. - gIR->module->addModuleFlag(llvm::Module::AppendUnique, "Linker Options", - llvm::MDNode::get(gIR->context(), gIR->LinkerMetadataArgs)); - #endif - - #if LDC_LLVM_VER >= 304 - // Emit ldc version as llvm.ident metadata. - llvm::NamedMDNode *IdentMetadata = gIR->module->getOrInsertNamedMetadata("llvm.ident"); - std::string Version("ldc version "); - Version.append(global.ldc_version); -#if LDC_LLVM_VER >= 306 - llvm::Metadata *IdentNode[] = -#else - llvm::Value *IdentNode[] = -#endif - { - llvm::MDString::get(gIR->context(), Version) - }; - IdentMetadata->addOperand(llvm::MDNode::get(gIR->context(), IdentNode)); - #endif - } - - // finalize debug info - gIR->DBuilder.EmitModuleEnd(); - - // verify the llvm - verifyModule(*gIR->module); -} - -llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context) -{ - bool logenabled = Logger::enabled(); - if (llvmForceLogging && !logenabled) - { - Logger::enable(); - } + genModuleInfo(m, emitFullModuleInfo); - IF_LOG Logger::println("Generating module: %s", (md ? md->toChars() : toChars())); - LOG_SCOPE; - - if (global.params.verbose_cg) - printf("codegen: %s (%s)\n", toPrettyChars(), srcfile->toChars()); - - if (global.errors) - { - Logger::println("Aborting because of errors"); - fatal(); - } - - // name the module -#if 1 - // Temporary workaround for http://llvm.org/bugs/show_bug.cgi?id=11479 – - // just use the source file name, as it is unlikely to collide with a - // symbol name used somewhere in the module. - llvm::StringRef mname(srcfile->toChars()); -#else - llvm::StringRef mname(toChars()); - if (md != 0) - mname = md->toChars(); -#endif - - // 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(); - - // set target triple - ir.module->setTargetTriple(global.params.targetTriple.str()); - - // set final data layout - ir.module->setDataLayout(gDataLayout->getStringRepresentation()); -#if LDC_LLVM_VER >= 307 - IF_LOG Logger::cout() << "Final data layout: " << ir.module->getDataLayout().getStringRepresentation() << '\n'; -#else - IF_LOG Logger::cout() << "Final data layout: " << ir.module->getDataLayout() << '\n'; -#endif - - // handle invalid 'objectø module - if (!ClassDeclaration::object) { - error("is missing 'class Object'"); - fatal(); - } - - LLVM_D_InitRuntime(); - - // Note, skip pseudo-modules for coverage analysis - if ( global.params.cov && !mname.equals("__entrypoint.d") && !mname.equals("__main.d") ) - { - addCoverageAnalysis(this); - } - - codegenModule(this); - - if ( gIR->dmodule->d_cover_valid ) - { - addCoverageAnalysisInitializer(this); + build_llvm_used_array(irs); } - gIR = NULL; - - if (llvmForceLogging && !logenabled) + if (m->d_cover_valid) { - Logger::disable(); + addCoverageAnalysisInitializer(m); } - return ir.module; -} - -llvm::GlobalVariable* Module::moduleInfoSymbol() -{ - // create name - std::string MIname("_D"); - MIname.append(mangle(this)); - MIname.append("12__ModuleInfoZ"); - - 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) { - // declare global - // flags will be modified at runtime so can't make it constant - LLType *moduleInfoType = llvm::StructType::create(llvm::getGlobalContext()); - moduleInfoVar = getOrCreateGlobal(loc, *gIR->module, moduleInfoType, - false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); - } - - return moduleInfoVar; + gIR = 0; + irs->dmodule = 0; } // Put out instance of ModuleInfo for this Module -void Module::genmoduleinfo() +static void genModuleInfo(Module *m, bool emitFullModuleInfo) { // resolve ModuleInfo - if (!moduleinfo) + if (!Module::moduleinfo) { - error("object.d is missing the ModuleInfo struct"); + m->error("object.d is missing the ModuleInfo struct"); fatal(); } // check for patch else { // The base struct should consist only of _flags/_index. - if (moduleinfo->structsize != 4 + 4) + if (Module::moduleinfo->structsize != 4 + 4) { - error("object.d ModuleInfo class is incorrect"); + m->error("object.d ModuleInfo class is incorrect"); fatal(); } } // use the RTTIBuilder - RTTIBuilder b(moduleinfo); + RTTIBuilder b(Module::moduleinfo); // some types - LLType* moduleinfoTy = moduleinfo->type->ctype->getLLType(); + llvm::Type* const moduleInfoPtrTy = + getPtrToType(DtoType(Module::moduleinfo->type)); LLType* classinfoTy = Type::typeinfoclass->type->ctype->getLLType(); // importedModules[] std::vector importInits; LLConstant* importedModules = 0; llvm::ArrayType* importedModulesTy = 0; - for (size_t i = 0; i < aimports.dim; i++) + for (size_t i = 0; i < m->aimports.dim; i++) { - Module *m = static_cast(aimports.data[i]); - if (!m->needModuleInfo() || m == this) - continue; + Module *mod = static_cast(m->aimports.data[i]); + if (!mod->needModuleInfo() || mod == m) continue; - // declare the imported module info - std::string m_name("_D"); - m_name.append(mangle(m)); - m_name.append("12__ModuleInfoZ"); - 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); + importInits.push_back( + DtoBitCast(getIrModule(mod)->moduleInfoSymbol(), moduleInfoPtrTy)); } // has import array? if (!importInits.empty()) { - importedModulesTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size()); + importedModulesTy = llvm::ArrayType::get(moduleInfoPtrTy, importInits.size()); importedModules = LLConstantArray::get(importedModulesTy, importInits); } @@ -911,9 +816,9 @@ void Module::genmoduleinfo() llvm::ArrayType* localClassesTy = 0; ClassDeclarations aclasses; //printf("members->dim = %d\n", members->dim); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < m->members->dim; i++) { - (*members)[i]->addLocalClass(&aclasses); + (*m->members)[i]->addLocalClass(&aclasses); } // fill inits std::vector classInits; @@ -956,11 +861,11 @@ void Module::genmoduleinfo() #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(); + llvm::Function* fsharedctor = build_module_shared_ctor(m); + llvm::Function* fshareddtor = build_module_shared_dtor(m); + llvm::Function* funittest = build_module_unittest(m); + llvm::Function* fctor = build_module_ctor(m); + llvm::Function* fdtor = build_module_dtor(m); unsigned flags = MInew; if (fctor) @@ -984,7 +889,7 @@ void Module::genmoduleinfo() if (localClasses) flags |= MIlocalClasses; - if (!needmoduleinfo) + if (!m->needmoduleinfo) flags |= MIstandalone; b.push_uint(flags); // flags @@ -1016,22 +921,25 @@ void Module::genmoduleinfo() } // Put out module name as a 0-terminated string. - const char *name = toPrettyChars(); + const char *name = m->toPrettyChars(); const size_t len = strlen(name) + 1; llvm::IntegerType *it = llvm::IntegerType::getInt8Ty(gIR->context()); llvm::ArrayType *at = llvm::ArrayType::get(it, len); b.push(toConstantArray(it, at, name, len, false)); // create and set initializer - LLGlobalVariable *moduleInfoSym = moduleInfoSymbol(); + LLGlobalVariable *moduleInfoSym = getIrModule(m)->moduleInfoSymbol(); b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym); moduleInfoSym->setLinkage(llvm::GlobalValue::ExternalLinkage); if (global.params.isLinux) { - build_dso_registry_calls(moduleInfoSym); + if (emitFullModuleInfo) + build_dso_registry_calls(mangle(m), moduleInfoSym); + else + build_module_ref(mangle(m), moduleInfoSym); } else { // build the modulereference and ctor for registering it - LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSym); + LLFunction* mictor = build_module_reference_and_ctor(mangle(m), moduleInfoSym); AppendFunctionToLLVMGlobalCtorsDtors(mictor, 65535, true); } } diff --git a/gen/naked.cpp b/gen/naked.cpp index e00c014b665..7a5e487e968 100644 --- a/gen/naked.cpp +++ b/gen/naked.cpp @@ -258,7 +258,7 @@ void DtoDefineNakedFunction(FuncDeclaration* fd) asmstr << "\t.size\t" << mangle << ", .-" << mangle << std::endl << std::endl; } - gIR->module->appendModuleInlineAsm(asmstr.str()); + gIR->module.appendModuleInlineAsm(asmstr.str()); asmstr.str(""); gIR->functions.pop_back(); diff --git a/gen/rttibuilder.cpp b/gen/rttibuilder.cpp index f4ea74af81f..976488af4ba 100644 --- a/gen/rttibuilder.cpp +++ b/gen/rttibuilder.cpp @@ -87,7 +87,7 @@ void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* ma initname.append(".rtti.voidarr.data"); LLGlobalVariable* G = new LLGlobalVariable( - *gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); + gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); G->setAlignment(valtype->alignsize()); push_void_array(getTypePaddedSize(CI->getType()), G); @@ -106,7 +106,7 @@ void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, D initname.append(".data"); LLGlobalVariable* G = new LLGlobalVariable( - *gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); + gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); G->setAlignment(valtype->alignsize()); push_array(dim, DtoBitCast(G, DtoType(valtype->pointerTo()))); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 2dbc5061bec..c0d6586f51a 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -126,7 +126,7 @@ void LLVM_D_FreeRuntime() ////////////////////////////////////////////////////////////////////////////////////////////////// -llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target, const char* name) +llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module& target, const char* name) { checkForImplicitGCCall(loc, name); @@ -134,7 +134,7 @@ llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target, LLVM_D_InitRuntime(); } - LLFunction* fn = target->getFunction(name); + LLFunction* fn = target.getFunction(name); if (fn) return fn; @@ -142,7 +142,7 @@ llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target, assert(fn && "Runtime function not found."); LLFunctionType* fnty = fn->getFunctionType(); - LLFunction* resfn = llvm::cast(target->getOrInsertFunction(name, fnty)); + LLFunction* resfn = llvm::cast(target.getOrInsertFunction(name, fnty)); resfn->setAttributes(fn->getAttributes()); resfn->setCallingConv(fn->getCallingConv()); return resfn; @@ -150,9 +150,9 @@ llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target, ////////////////////////////////////////////////////////////////////////////////////////////////// -llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(Loc& loc, llvm::Module* target, const char* name) +llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(Loc& loc, llvm::Module& target, const char* name) { - LLGlobalVariable* gv = target->getNamedGlobal(name); + LLGlobalVariable* gv = target.getNamedGlobal(name); if (gv) { return gv; } @@ -171,7 +171,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(Loc& loc, llvm::Module* target, co } LLPointerType* t = g->getType(); - return getOrCreateGlobal(loc, *target, t->getElementType(), g->isConstant(), + return getOrCreateGlobal(loc, target, t->getElementType(), g->isConstant(), g->getLinkage(), NULL, g->getName()); } diff --git a/gen/runtime.h b/gen/runtime.h index 44a24d6b827..3175cee3f3e 100644 --- a/gen/runtime.h +++ b/gen/runtime.h @@ -28,9 +28,9 @@ struct Loc; bool LLVM_D_InitRuntime(); void LLVM_D_FreeRuntime(); -llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target, const char* name); +llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module& target, const char* name); -llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(const Loc &loc, llvm::Module* target, const char* name); +llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(const Loc &loc, llvm::Module& target, const char* name); #define _adEq "_adEq2" #define _adCmp "_adCmp2" diff --git a/gen/statements.cpp b/gen/statements.cpp index 7e4d83a8a23..89494a71519 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -1210,7 +1210,7 @@ class ToIRVisitor : public Visitor { LLType* elemTy = DtoType(stmt->condition->type); LLArrayType* arrTy = llvm::ArrayType::get(elemTy, inits.size()); LLConstant* arrInit = LLConstantArray::get(arrTy, inits); - LLGlobalVariable* arr = new llvm::GlobalVariable(*gIR->module, arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit, ".string_switch_table_data"); + LLGlobalVariable* arr = new llvm::GlobalVariable(gIR->module, arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit, ".string_switch_table_data"); LLType* elemPtrTy = getPtrToType(elemTy); LLConstant* arrPtr = llvm::ConstantExpr::getBitCast(arr, elemPtrTy); @@ -1781,7 +1781,7 @@ class ToIRVisitor : public Visitor { llvm::Function* fn = LLVM_D_GetRuntimeFunction(stmt->loc, gIR->module, "_d_switch_error"); - LLValue *moduleInfoSymbol = gIR->func()->decl->getModule()->moduleInfoSymbol(); + LLValue *moduleInfoSymbol = getIrModule(gIR->func()->decl->getModule())->moduleInfoSymbol(); LLType *moduleInfoType = DtoType(Module::moduleinfo->type); LLValue* args[] = { diff --git a/gen/tocall.cpp b/gen/tocall.cpp index afdc6c43c1f..dabe0be7670 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -218,7 +218,7 @@ static LLValue* getTypeinfoArrayArgumentForDVarArg(Expressions* arguments, int b LLArrayType* typeinfoarraytype = LLArrayType::get(typeinfotype, numVariadicArgs); llvm::GlobalVariable* typeinfomem = - new llvm::GlobalVariable(*gIR->module, typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage"); + new llvm::GlobalVariable(gIR->module, typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage"); IF_LOG Logger::cout() << "_arguments storage: " << *typeinfomem << '\n'; std::vector vtypeinfos; @@ -239,7 +239,7 @@ static LLValue* getTypeinfoArrayArgumentForDVarArg(Expressions* arguments, int b }; LLType* tiarrty = DtoType(Type::dtypeinfo->type->arrayOf()); tiinits = LLConstantStruct::get(isaStruct(tiarrty), llvm::ArrayRef(pinits)); - LLValue* typeinfoarrayparam = new llvm::GlobalVariable(*gIR->module, tiarrty, + LLValue* typeinfoarrayparam = new llvm::GlobalVariable(gIR->module, tiarrty, true, llvm::GlobalValue::InternalLinkage, tiinits, "._arguments.array"); return DtoLoad(typeinfoarrayparam); diff --git a/gen/toconstelem.cpp b/gen/toconstelem.cpp index fe823e2c57a..6e77f4f2bb9 100644 --- a/gen/toconstelem.cpp +++ b/gen/toconstelem.cpp @@ -214,7 +214,7 @@ class ToConstElemVisitor : public Visitor if (gvar == 0) { llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::PrivateLinkage; - gvar = new llvm::GlobalVariable(*gIR->module, _init->getType(), true, _linkage, _init, ".str"); + gvar = new llvm::GlobalVariable(gIR->module, _init->getType(), true, _linkage, _init, ".str"); gvar->setUnnamedAddr(true); (*stringLiteralCache)[key] = gvar; } @@ -490,7 +490,7 @@ class ToConstElemVisitor : public Visitor return; } - se->globalVar = new llvm::GlobalVariable(*p->module, + se->globalVar = new llvm::GlobalVariable(p->module, DtoType(e->e1->type), false, llvm::GlobalValue::InternalLinkage, 0, ".structliteral"); @@ -498,7 +498,7 @@ class ToConstElemVisitor : public Visitor if (constValue->getType() != se->globalVar->getType()->getContainedType(0)) { llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable( - *p->module, constValue->getType(), false, + p->module, constValue->getType(), false, llvm::GlobalValue::InternalLinkage, 0, ".structliteral"); se->globalVar->replaceAllUsesWith( DtoBitCast(finalGlobalVar, se->globalVar->getType())); @@ -589,7 +589,7 @@ class ToConstElemVisitor : public Visitor } bool canBeConst = e->type->isConst() || e->type->isImmutable(); - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(*gIR->module, + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(gIR->module, initval->getType(), canBeConst, llvm::GlobalValue::InternalLinkage, initval, ".dynarrayStorage"); gvar->setUnnamedAddr(canBeConst); @@ -670,7 +670,7 @@ class ToConstElemVisitor : public Visitor } else { - value->globalVar = new llvm::GlobalVariable(*p->module, + value->globalVar = new llvm::GlobalVariable(p->module, origClass->type->ctype->isClass()->getMemoryLLType(), false, llvm::GlobalValue::InternalLinkage, 0, ".classref"); @@ -713,7 +713,7 @@ class ToConstElemVisitor : public Visitor if (constValue->getType() != value->globalVar->getType()->getContainedType(0)) { llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable( - *p->module, constValue->getType(), false, + p->module, constValue->getType(), false, llvm::GlobalValue::InternalLinkage, 0, ".classref"); value->globalVar->replaceAllUsesWith( DtoBitCast(finalGlobalVar, value->globalVar->getType())); diff --git a/gen/toir.cpp b/gen/toir.cpp index 85d158f6dd1..829d553c079 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -375,7 +375,7 @@ class ToElemVisitor : public Visitor Logger::cout() << "type: " << *at << '\n'; Logger::cout() << "init: " << *_init << '\n'; } - gvar = new llvm::GlobalVariable(*gIR->module, at, true, _linkage, _init, ".str"); + gvar = new llvm::GlobalVariable(gIR->module, at, true, _linkage, _init, ".str"); gvar->setUnnamedAddr(true); (*stringLiteralCache)[key] = gvar; } @@ -2675,7 +2675,7 @@ class ToElemVisitor : public Visitor { llvm::Constant* init = arrayLiteralToConst(p, e); llvm::GlobalVariable* global = new llvm::GlobalVariable( - *gIR->module, + gIR->module, init->getType(), true, llvm::GlobalValue::InternalLinkage, @@ -2865,7 +2865,7 @@ class ToElemVisitor : public Visitor LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) }; LLConstant* initval = arrayConst(keysInits, indexType); - LLConstant* globalstore = new LLGlobalVariable(*gIR->module, initval->getType(), + LLConstant* globalstore = new LLGlobalVariable(gIR->module, initval->getType(), false, LLGlobalValue::InternalLinkage, initval, ".aaKeysStorage"); #if LDC_LLVM_VER >= 307 LLConstant* slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true); @@ -2876,7 +2876,7 @@ class ToElemVisitor : public Visitor LLValue* keysArray = DtoAggrPaint(slice, funcTy->getParamType(1)); initval = arrayConst(valuesInits, vtype); - globalstore = new LLGlobalVariable(*gIR->module, initval->getType(), + globalstore = new LLGlobalVariable(gIR->module, initval->getType(), false, LLGlobalValue::InternalLinkage, initval, ".aaValuesStorage"); #if LDC_LLVM_VER >= 307 slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true); diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 75d4ddc4d42..05b29e2d8a4 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -408,13 +408,13 @@ LLValue* DtoMemCmp(LLValue* lhs, LLValue* rhs, LLValue* nbytes) // int memcmp ( const void * ptr1, const void * ptr2, size_t num ); LLType* VoidPtrTy = getVoidPtrType(); - LLFunction* fn = gIR->module->getFunction("memcmp"); + LLFunction* fn = gIR->module.getFunction("memcmp"); if (!fn) { LLType* Tys[] = { VoidPtrTy, VoidPtrTy, DtoSize_t() }; LLFunctionType* fty = LLFunctionType::get(LLType::getInt32Ty(gIR->context()), Tys, false); - fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, "memcmp", gIR->module); + fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, "memcmp", &gIR->module); } lhs = DtoBitCast(lhs, VoidPtrTy); @@ -507,7 +507,7 @@ LLConstant* DtoConstString(const char* str) if (gvar == 0) { llvm::Constant* init = llvm::ConstantDataArray::getString(gIR->context(), s, true); - gvar = new llvm::GlobalVariable(*gIR->module, init->getType(), true, + gvar = new llvm::GlobalVariable(gIR->module, init->getType(), true, llvm::GlobalValue::PrivateLinkage, init, ".str"); gvar->setUnnamedAddr(true); gIR->stringLiteral1ByteCache[s] = gvar; @@ -740,33 +740,6 @@ unsigned char getABITypeAlign(LLType* t) ////////////////////////////////////////////////////////////////////////////////////////// -LLStructType* DtoInterfaceInfoType() -{ - if (gIR->interfaceInfoType) - return gIR->interfaceInfoType; - - // build interface info type - LLSmallVector types; - // ClassInfo classinfo - ClassDeclaration* cd2 = Type::typeinfoclass; - DtoResolveClass(cd2); - types.push_back(DtoType(cd2->type)); - // void*[] vtbl - LLSmallVector vtbltypes; - vtbltypes.push_back(DtoSize_t()); - LLType* byteptrptrty = getPtrToType(getPtrToType(LLType::getInt8Ty(gIR->context()))); - vtbltypes.push_back(byteptrptrty); - types.push_back(LLStructType::get(gIR->context(), vtbltypes)); - // int offset - types.push_back(LLType::getInt32Ty(gIR->context())); - // create type - gIR->interfaceInfoType = LLStructType::get(gIR->context(), types); - - return gIR->interfaceInfoType; -} - -////////////////////////////////////////////////////////////////////////////////////////// - LLStructType* DtoMutexType() { if (gIR->mutexType) diff --git a/gen/tollvm.h b/gen/tollvm.h index 834d1d1cd0b..3fdc0dcc4ee 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -60,7 +60,6 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym); // some types LLIntegerType* DtoSize_t(); -LLStructType* DtoInterfaceInfoType(); LLStructType* DtoMutexType(); LLStructType* DtoModuleReferenceType(); diff --git a/gen/typinf.cpp b/gen/typinf.cpp index 77187d1f34d..19dd77b394c 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -302,7 +302,7 @@ static void emitTypeMetadata(TypeInfoDeclaration *tid) // Add some metadata for use by optimization passes. std::string metaname(TD_PREFIX); metaname += mangle(tid); - llvm::NamedMDNode* meta = gIR->module->getNamedMetadata(metaname); + llvm::NamedMDNode* meta = gIR->module.getNamedMetadata(metaname); if (!meta) { // Construct the fields @@ -317,7 +317,7 @@ static void emitTypeMetadata(TypeInfoDeclaration *tid) #endif // Construct the metadata and insert it into the module. - llvm::NamedMDNode* node = gIR->module->getOrInsertNamedMetadata(metaname); + llvm::NamedMDNode* node = gIR->module.getOrInsertNamedMetadata(metaname); node->addOperand(llvm::MDNode::get(gIR->context(), llvm::makeArrayRef(mdVals, TD_NumFields))); } @@ -820,7 +820,7 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState* p) } IrGlobal* irg = getIrGlobal(decl, true); - irg->value = gIR->module->getGlobalVariable(mangled); + irg->value = gIR->module.getGlobalVariable(mangled); if (irg->value) { irg->type = irg->value->getType()->getContainedType(0); assert(irg->type->isStructTy()); @@ -829,7 +829,7 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState* p) irg->type = Type::dtypeinfo->type->ctype->isClass()->getMemoryLLType(); else irg->type = LLStructType::create(gIR->context(), decl->toPrettyChars()); - irg->value = new llvm::GlobalVariable(*gIR->module, irg->type, true, + irg->value = new llvm::GlobalVariable(gIR->module, irg->type, true, llvm::GlobalValue::ExternalLinkage, NULL, mangled); } diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp index c5f4b8b59aa..7e275d1f90b 100644 --- a/ir/iraggr.cpp +++ b/ir/iraggr.cpp @@ -55,7 +55,7 @@ LLGlobalVariable * IrAggr::getInitSymbol() initname.append("6__initZ"); init = getOrCreateGlobal(aggrdecl->loc, - *gIR->module, init_type, true, llvm::GlobalValue::ExternalLinkage, NULL, initname); + gIR->module, init_type, true, llvm::GlobalValue::ExternalLinkage, NULL, initname); // set alignment init->setAlignment(type->alignsize()); diff --git a/ir/irclass.cpp b/ir/irclass.cpp index 9ac45d233c4..fb46c39f7b1 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -54,7 +54,7 @@ LLGlobalVariable * IrAggr::getVtblSymbol() LLType* vtblTy = stripModifiers(type)->ctype->isClass()->getVtbl(); vtbl = getOrCreateGlobal(aggrdecl->loc, - *gIR->module, vtblTy, true, llvm::GlobalValue::ExternalLinkage, NULL, initname); + gIR->module, vtblTy, true, llvm::GlobalValue::ExternalLinkage, NULL, initname); return vtbl; } @@ -85,7 +85,7 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol() // classinfos cannot be constants since they're used as locks for synchronized classInfo = getOrCreateGlobal(aggrdecl->loc, - *gIR->module, tc->getMemoryLLType(), false, + gIR->module, tc->getMemoryLLType(), false, llvm::GlobalValue::ExternalLinkage, NULL, initname); // Generate some metadata on this ClassInfo if it's for a class. @@ -110,7 +110,7 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol() #endif // Construct the metadata and insert it into the module. llvm::SmallString<64> name; - llvm::NamedMDNode* node = gIR->module->getOrInsertNamedMetadata( + llvm::NamedMDNode* node = gIR->module.getOrInsertNamedMetadata( llvm::Twine(CD_PREFIX, initname).toStringRef(name)); node->addOperand(llvm::MDNode::get(gIR->context(), llvm::makeArrayRef(mdVals, CD_NumFields))); @@ -144,7 +144,7 @@ LLGlobalVariable * IrAggr::getInterfaceArraySymbol() // We keep this as external for now and only consider template linkage if // we emit the initializer later. - classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module, + classInterfacesArray = getOrCreateGlobal(cd->loc, gIR->module, array_type, true, llvm::GlobalValue::ExternalLinkage, NULL, name); return classInterfacesArray; @@ -348,7 +348,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance name.printf("%i", b->offset); name.writestring(mangleExact(fd)); LLFunction *thunk = LLFunction::Create(isaFunction(fn->getType()->getContainedType(0)), - DtoLinkage(fd), name.extractString(), gIR->module); + DtoLinkage(fd), name.extractString(), &gIR->module); // create entry and end blocks llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(gIR->context(), "", thunk); @@ -397,7 +397,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance mangledName.append("6__vtblZ"); llvm::GlobalVariable* GV = getOrCreateGlobal(cd->loc, - *gIR->module, + gIR->module, vtbl_constant->getType(), true, DtoLinkage(cd), diff --git a/ir/irmodule.cpp b/ir/irmodule.cpp index bd514c979a9..bdc1bec3618 100644 --- a/ir/irmodule.cpp +++ b/ir/irmodule.cpp @@ -14,29 +14,33 @@ #include "ir/irdsymbol.h" #include "ir/irmodule.h" -IrModule::IrModule(Module* module, const char* srcfilename) -{ - M = module; +IrModule::IrModule(Module *module, const char *srcfilename) + : M(module), moduleInfoVar_(0) {} - LLConstant* slice = DtoConstString(srcfilename); - fileName = new llvm::GlobalVariable( - *gIR->module, slice->getType(), true, LLGlobalValue::InternalLinkage, slice, ".modulefilename"); -} +IrModule::~IrModule() {} + +llvm::GlobalVariable *IrModule::moduleInfoSymbol() { + if (moduleInfoVar_) return moduleInfoVar_; + + std::string name("_D"); + name.append(mangle(M)); + name.append("12__ModuleInfoZ"); -IrModule::~IrModule() -{ + moduleInfoVar_ = new llvm::GlobalVariable( + gIR->module, llvm::StructType::create(gIR->context()), false, + llvm::GlobalValue::ExternalLinkage, NULL, name); + return moduleInfoVar_; } -IrModule *getIrModule(Module *m) -{ - if (m == NULL) - m = gIR->func()->decl->getModule(); +IrModule *getIrModule(Module *m) { + if (!m) m = gIR->func()->decl->getModule(); + assert(m && "null module"); - if (m->ir.m_type == IrDsymbol::NotSet) - { + if (m->ir.m_type == IrDsymbol::NotSet) { m->ir.irModule = new IrModule(m, m->srcfile->toChars()); m->ir.m_type = IrDsymbol::ModuleType; } + assert(m->ir.m_type == IrDsymbol::ModuleType); return m->ir.irModule; } diff --git a/ir/irmodule.h b/ir/irmodule.h index 3e0fbc79a82..043cb55cd2f 100644 --- a/ir/irmodule.h +++ b/ir/irmodule.h @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// // -// Represents the state of a D module on its way through code generation. Also -// see the TODO in gen/module.cpp – parts of IRState really belong here. +// Represents the state of a D module on its way through code generation. // //===----------------------------------------------------------------------===// @@ -16,19 +15,31 @@ #define LDC_IR_IRMODULE_H class Module; -namespace llvm -{ - class GlobalVariable; +namespace llvm { +class GlobalVariable; } -struct IrModule -{ - IrModule(Module* module, const char* srcfilename); +struct IrModule { + IrModule(Module *module, const char *srcfilename); virtual ~IrModule(); - Module* M; + Module *const M; - llvm::GlobalVariable* fileName; + llvm::GlobalVariable *moduleInfoSymbol(); + + // static ctors/dtors/unittests + typedef std::list FuncDeclList; + typedef std::list GatesList; + FuncDeclList ctors; + FuncDeclList dtors; + FuncDeclList sharedCtors; + FuncDeclList sharedDtors; + GatesList gates; + GatesList sharedGates; + FuncDeclList unitTests; + +private: + llvm::GlobalVariable *moduleInfoVar_; }; IrModule *getIrModule(Module *m); From 4ce7982014a8c6f31e16fa403008d41c95c0ae1c Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 28 Jun 2015 11:37:30 +0200 Subject: [PATCH 100/101] DMDFE: Replace assert(0) with fatal() after error messages in CPP mangler. assert(0) may cause a stack trace/abort but these are always error conditins. Should go upstream, too. --- dmd2/cppmangle.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/dmd2/cppmangle.c b/dmd2/cppmangle.c index c364d058719..6813ae23fe9 100644 --- a/dmd2/cppmangle.c +++ b/dmd2/cppmangle.c @@ -170,7 +170,11 @@ class CppMangleVisitor : public Visitor else { s->error("ICE: C++ %s template value parameter is not supported", tv->valType->toChars()); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } } else if (!tp || tp->isTemplateTypeParameter()) @@ -186,7 +190,11 @@ class CppMangleVisitor : public Visitor if (!d && !e) { s->error("ICE: %s is unsupported parameter for C++ template: (%s)", o->toChars()); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } if (d && d->isFuncDeclaration()) { @@ -215,14 +223,22 @@ class CppMangleVisitor : public Visitor else { s->error("ICE: %s is unsupported parameter for C++ template", o->toChars()); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } } else { s->error("ICE: C++ templates support only integral value , type parameters, alias templates and alias function parameters"); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } } if (is_var_arg) @@ -295,7 +311,11 @@ class CppMangleVisitor : public Visitor if (!(d->storage_class & (STCextern | STCgshared))) { d->error("ICE: C++ static non- __gshared non-extern variables not supported"); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } Dsymbol *p = d->toParent(); @@ -379,7 +399,11 @@ class CppMangleVisitor : public Visitor { // Mangle static arrays as pointers t->error(Loc(), "ICE: Unable to pass static array to extern(C++) function."); t->error(Loc(), "Use pointer instead."); +#if IN_LLVM + fatal(); +#else assert(0); +#endif //t = t->nextOf()->pointerTo(); } @@ -441,7 +465,11 @@ class CppMangleVisitor : public Visitor { t->error(Loc(), "ICE: Unsupported type %s\n", t->toChars()); } +#if IN_LLVM + fatal(); +#else assert(0); //Assert, because this error should be handled in frontend +#endif } void visit(TypeBasic *t) @@ -781,7 +809,11 @@ class VisualCPPMangler : public Visitor { type->error(Loc(), "ICE: Unsupported type %s\n", type->toChars()); } +#if IN_LLVM + fatal(); +#else assert(0); // Assert, because this error should be handled in frontend +#endif } void visit(TypeBasic *type) @@ -1166,7 +1198,11 @@ class VisualCPPMangler : public Visitor if (!(d->storage_class & (STCextern | STCgshared))) { d->error("ICE: C++ static non- __gshared non-extern variables not supported"); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } buf.writeByte('?'); mangleIdent(d); @@ -1298,7 +1334,11 @@ class VisualCPPMangler : public Visitor else { sym->error("ICE: C++ %s template value parameter is not supported", tv->valType->toChars()); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } } else if (!tp || tp->isTemplateTypeParameter()) @@ -1314,7 +1354,11 @@ class VisualCPPMangler : public Visitor if (!d && !e) { sym->error("ICE: %s is unsupported parameter for C++ template", o->toChars()); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } if (d && d->isFuncDeclaration()) { @@ -1356,7 +1400,11 @@ class VisualCPPMangler : public Visitor else { sym->error("ICE: C++ templates support only integral value , type parameters, alias templates and alias function parameters"); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } } tmp.mangleIdent(d); @@ -1364,14 +1412,22 @@ class VisualCPPMangler : public Visitor else { sym->error("ICE: %s is unsupported parameter for C++ template: (%s)", o->toChars()); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } } else { sym->error("ICE: C++ templates support only integral value , type parameters, alias templates and alias function parameters"); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } } name = tmp.buf.extractString(); @@ -1663,7 +1719,11 @@ class VisualCPPMangler : public Visitor { t->error(Loc(), "ICE: Unable to pass static array to extern(C++) function."); t->error(Loc(), "Use pointer instead."); +#if IN_LLVM + fatal(); +#else assert(0); +#endif } flags &= ~IS_NOT_TOP_TYPE; flags &= ~IGNORE_CONST; From 5d1f68b78065f0df232e938a62acdac77dc8e123 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 28 Jun 2015 12:34:10 +0200 Subject: [PATCH 101/101] DMDFE: Use the right CPP mangler. The choice of the mangler must be based on the current target, not on the host platform. --- dmd2/cppmangle.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/dmd2/cppmangle.c b/dmd2/cppmangle.c index 6813ae23fe9..3d7372fa72e 100644 --- a/dmd2/cppmangle.c +++ b/dmd2/cppmangle.c @@ -38,7 +38,9 @@ * so nothing would be compatible anyway. */ -#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || IN_LLVM +#if !IN_LLVM +//#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS +#endif /* * Follows Itanium C++ ABI 1.86 @@ -742,13 +744,17 @@ class CppMangleVisitor : public Visitor } }; +#if !IN_LLVM char *toCppMangle(Dsymbol *s) { CppMangleVisitor v; return v.mangleOf(s); } +#endif -#elif TARGET_WINDOS +#if !IN_LLVM +//#elif TARGET_WINDOS +#endif // Windows DMC and Microsoft Visual C++ mangling #define VC_SAVED_TYPE_CNT 10 @@ -1731,12 +1737,35 @@ class VisualCPPMangler : public Visitor } }; +#if IN_LLVM +char *toCppMangle(Dsymbol *s) +{ +#if LDC_LLVM_VER >= 305 + const bool isTargetWindowsMSVC = global.params.targetTriple.isWindowsMSVCEnvironment(); +#else + const bool isTargetWindowsMSVC = global.params.targetTriple.getOS() == llvm::Triple::Win32; +#endif + if (isTargetWindowsMSVC) + { + VisualCPPMangler v(!global.params.is64bit); + return v.mangleOf(s); + } + else + { + CppMangleVisitor v; + return v.mangleOf(s); + } +} +#else char *toCppMangle(Dsymbol *s) { VisualCPPMangler v(!global.params.is64bit); return v.mangleOf(s); } - -#else -#error "fix this" #endif + +#if !IN_LLVM +//#else +//#error "fix this" +//#endif +#endif \ No newline at end of file