diff --git a/CMakeLists.txt b/CMakeLists.txt index 411be9c9..ab9a9364 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ endif() # find_package(LLVM 3.1 REQUIRED - all-targets bitwriter linker ipo instrumentation backend support tablegen asmparser ${EXTRA_LLVM_MODULES}) + all-targets bitwriter linker ipo instrumentation backend support tablegen asmparser lto ${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 9cc0e380..aabf08d4 100644 --- a/cmake/Modules/FindLLVM.cmake +++ b/cmake/Modules/FindLLVM.cmake @@ -51,6 +51,10 @@ if (WIN32 OR NOT LLVM_CONFIG) list(REMOVE_ITEM LLVM_FIND_COMPONENTS "all-targets" index) list(APPEND LLVM_FIND_COMPONENTS ${LLVM_TARGETS_TO_BUILD}) list(REMOVE_ITEM LLVM_FIND_COMPONENTS "backend" index) + if(${LLVM_VERSION_STRING} MATCHES "3.[0-4][A-Za-z]*") + # Versions below 3.5 do not supoort component lto + list(REMOVE_ITEM LLVM_FIND_COMPONENTS "lto" index) + endif() llvm_map_components_to_libraries(tmplibs ${LLVM_FIND_COMPONENTS}) if(MSVC) @@ -102,6 +106,10 @@ else() endmacro() llvm_set(VERSION_STRING version) + if(${LLVM_VERSION_STRING} MATCHES "3.[0-4][A-Za-z]*") + # Versions below 3.5 do not supoort component lto + list(REMOVE_ITEM LLVM_FIND_COMPONENTS "lto" index) + endif() if(${LLVM_VERSION_STRING} MATCHES "3.0[A-Za-z]*") # Version 3.0 does not support component all-targets llvm_set(TARGETS_TO_BUILD targets-built) diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 399509e9..ac203a20 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -1135,8 +1135,24 @@ void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, DValue* lowerBoun assert((arrty->ty == Tsarray || arrty->ty == Tarray || arrty->ty == Tpointer) && "Can only array bounds check for static or dynamic arrays"); - // static arrays could get static checks for static indices - // but shouldn't since it might be generic code that's never executed + // Do not emit bounds check code if the index is statically known to be + // within bounds. + if (arrty->ty == Tsarray && isaConstantInt(index->getRVal())) { + assert(!arr->isSlice()); + assert(!arr->isNull()); + assert(!lowerBound); + + TypeSArray *sarray = static_cast(arrty); + llvm::ConstantInt *constIndex = static_cast(index->getRVal()); + if (sarray->dim->toUInteger() < constIndex->getZExtValue()) { + // If this happens then it is possible a frontend bug. + // Just output a warning and continue generating a runtime check. + // This could be generic code which is never executed. + warning(loc, "Static array index out of bounds (should have been detected during semantic analysis)"); + } + else + return ; + } // runtime check diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 66f26b73..d7f99b82 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -34,6 +34,8 @@ #include "llvm/Attributes.h" #endif +#include + #if LDC_LLVM_VER < 302 using namespace llvm::Attribute; #endif @@ -41,7 +43,11 @@ using namespace llvm::Attribute; ////////////////////////////////////////////////////////////////////////////////////////////////// static llvm::cl::opt noruntime("noruntime", - llvm::cl::desc("Do not allow code that generates implicit runtime calls"), + llvm::cl::desc("Deprecated. Please use -nogc instead."), + llvm::cl::ZeroOrMore); + +static llvm::cl::opt nogc("nogc", + llvm::cl::desc("Do not allow code that generates implicit garbage collector calls"), llvm::cl::ZeroOrMore); ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -52,13 +58,65 @@ static void LLVM_D_BuildRuntimeModule(); ////////////////////////////////////////////////////////////////////////////////////////////////// +static void checkForImplicitGCCall(const char *name) +{ + if (nogc) + { + static const std::string GCNAMES[] = + { + "_aaDelX", + "_aaGetX", + "_aaKeys", + "_aaRehash", + "_aaValues", + "_adDupT", + "_d_allocmemory", + "_d_allocmemoryT", + "_d_array_cast_len", + "_d_array_slice_copy", + "_d_arrayappendT", + "_d_arrayappendcTX", + "_d_arrayappendcd", + "_d_arrayappendwd", + "_d_arraycatT", + "_d_arraycatnT", + "_d_arraysetlengthT", + "_d_arraysetlengthiT", + "_d_assocarrayliteralTX", + "_d_callfinalizer", + "_d_delarray_t", + "_d_delclass", + "_d_delinterface", + "_d_delmemory", + "_d_newarrayT", + "_d_newarrayiT", + "_d_newarraymT", + "_d_newarraymiT", + "_d_newarrayvT", + "_d_newclass", + }; + + if (binary_search(&GCNAMES[0], &GCNAMES[sizeof(GCNAMES) / sizeof(std::string)], name)) + { + error("No implicit garbage collector calls allowed with -nogc option enabled: %s", name); + fatal(); + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + bool LLVM_D_InitRuntime() { Logger::println("*** Initializing D runtime declarations ***"); LOG_SCOPE; if (!M) + { + if (noruntime) + deprecation(Loc(), "-noruntime has no function and will be removed in 0.14.0. Please use -nogc instead."); LLVM_D_BuildRuntimeModule(); + } return true; } @@ -76,10 +134,7 @@ void LLVM_D_FreeRuntime() llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name) { - if (noruntime) { - error("No implicit runtime calls allowed with -noruntime option enabled"); - fatal(); - } + checkForImplicitGCCall(name); if (!M) { LLVM_D_InitRuntime(); @@ -108,10 +163,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* return gv; } - if (noruntime) { - error("No implicit runtime calls allowed with -noruntime option enabled"); - fatal(); - } + checkForImplicitGCCall(name); if (!M) { LLVM_D_InitRuntime(); diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 51f306f8..2834b349 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 51f306f8570ab6627016a64b17a9ce67c06ab2ce +Subproject commit 2834b34907483afc81f36e29e7963b490ba73813