From d25d28f9148e28e717f646bac3612174dbafcdde Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 8 Dec 2013 20:24:08 +0100 Subject: [PATCH 1/5] Extend error message if -noruntime is used. The name of the implicit called runtime function gives a hint about what goes wrong. --- gen/runtime.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 66f26b73..e5047c62 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -77,7 +77,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"); + error("No implicit runtime calls (%s) allowed with -noruntime option enabled", name); fatal(); } @@ -109,7 +109,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* } if (noruntime) { - error("No implicit runtime calls allowed with -noruntime option enabled"); + error("No implicit runtime calls (%s) allowed with -noruntime option enabled", name); fatal(); } From bea0b597aee74f0ab5c6f1a7e034f365a985161f Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Tue, 10 Dec 2013 18:33:49 +0100 Subject: [PATCH 2/5] Add -nogc switch. This is a replacement for the -noruntime switch. With the new DSO implementation every module generates runtime calls. The main motivation for the -noruntime switch is to avoid implicit GC calls. Therefore a dedicated -nogc switch is introduced. --- gen/runtime.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++ tests/d2/dmd-testsuite | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/gen/runtime.cpp b/gen/runtime.cpp index e5047c62..a8d98726 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 @@ -44,6 +46,10 @@ static llvm::cl::opt noruntime("noruntime", llvm::cl::desc("Do not allow code that generates implicit runtime calls"), 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); + ////////////////////////////////////////////////////////////////////////////////////////////////// static llvm::Module* M = NULL; @@ -52,6 +58,54 @@ 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 ***"); @@ -80,6 +134,7 @@ llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name error("No implicit runtime calls (%s) allowed with -noruntime option enabled", name); fatal(); } + checkForImplicitGCCall(name); if (!M) { LLVM_D_InitRuntime(); @@ -112,6 +167,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* error("No implicit runtime calls (%s) allowed with -noruntime option enabled", name); 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 From 038855e4a024a07868c4a04ab310181cfa947c13 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Thu, 12 Dec 2013 20:02:45 +0100 Subject: [PATCH 3/5] Deprecate -noruntime switch (which has now no function). --- gen/runtime.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/gen/runtime.cpp b/gen/runtime.cpp index a8d98726..d7f99b82 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -43,7 +43,7 @@ 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", @@ -112,7 +112,11 @@ bool LLVM_D_InitRuntime() 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; } @@ -130,10 +134,6 @@ void LLVM_D_FreeRuntime() llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name) { - if (noruntime) { - error("No implicit runtime calls (%s) allowed with -noruntime option enabled", name); - fatal(); - } checkForImplicitGCCall(name); if (!M) { @@ -163,10 +163,6 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* return gv; } - if (noruntime) { - error("No implicit runtime calls (%s) allowed with -noruntime option enabled", name); - fatal(); - } checkForImplicitGCCall(name); if (!M) { From d4f8092ddecf4fde456bfbd8d643d487e0d49d01 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 13 Dec 2013 07:41:22 +0100 Subject: [PATCH 4/5] Support LLVM 3.5. LLVM 3.5 adds a new required component lto. --- CMakeLists.txt | 2 +- cmake/Modules/FindLLVM.cmake | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 847d9b5c..d9b3ae1a 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) From bac536a29c45709f2c5d3ecba9fdae2464242348 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Fri, 13 Dec 2013 06:51:18 +0100 Subject: [PATCH 5/5] Fix for issue #553. Check if a static array is accessed with a known index. In this case the bounds check can be omitted. --- gen/arrays.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) 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