diff --git a/.clang-format b/.clang-format index 26f1fa70..9e483b59 100644 --- a/.clang-format +++ b/.clang-format @@ -2,18 +2,19 @@ Language: Cpp # BasedOnStyle: Google AccessModifierOffset: -1 AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: true -AlignEscapedNewlinesLeft: true +AlignConsecutiveAssignments: AcrossComments +AlignConsecutiveMacros: AcrossComments +AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false +AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false -AllowShortFunctionsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: false -AlwaysBreakTemplateDeclarations: true +AllowShortFunctionsOnASingleLine: None +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakTemplateDeclarations: Yes AlwaysBreakBeforeMultilineStrings: true BreakBeforeBinaryOperators: None BreakBeforeTernaryOperators: true @@ -27,7 +28,6 @@ DerivePointerAlignment: false ExperimentalAutoDetectBinPacking: false IndentCaseLabels: true IndentWrappedFunctionNames: false -IndentFunctionDeclarationAfterType: false MaxEmptyLinesToKeep: 1 KeepEmptyLinesAtTheStartOfBlocks: false NamespaceIndentation: None @@ -43,7 +43,7 @@ PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Left SpacesBeforeTrailingComments: 2 Cpp11BracedListStyle: true -Standard: Cpp11 +Standard: c++17 IndentWidth: 2 TabWidth: 2 UseTab: Never diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 00000000..340efd6e --- /dev/null +++ b/.codespellrc @@ -0,0 +1,8 @@ +[codespell] +builtin = clear,rare,en-GB_to_en-US,names,informal,code +check-filenames = +check-hidden = +skip = */.git,*/build*,*/.codespellrc,*/install,*/lulesh,wrap.py +quiet-level = 2 +ignore-regex = ^#include <(?:stdio)\.h>$|DEPENDEES|\\endcode +ignore-words-list = uint diff --git a/.github/workflows/basic-ci.yml b/.github/workflows/basic-ci.yml index a7798bba..a1ddec5c 100644 --- a/.github/workflows/basic-ci.yml +++ b/.github/workflows/basic-ci.yml @@ -24,7 +24,7 @@ jobs: -a \( -name "*.c" -o -name "*.cpp" -o -name "*.h" \) \ -not -path "*/lulesh/*" -not -path "*/CallSite.h" \ -print0 \ - | xargs -0 clang-format-10 -i + | xargs -0 clang-format-12 -i - name: Format check run: | @@ -37,9 +37,6 @@ jobs: steps: - uses: actions/checkout@v2 - uses: codespell-project/actions-codespell@master - with: - path: demo lib test - skip: ./.git,*.py,*/lulesh lit-suite: runs-on: ubuntu-20.04 @@ -103,15 +100,15 @@ jobs: - name: Prepare TypeART coverage if: matrix.preset.coverage - run: cmake --build build --target lcov-clean + run: cmake --build build --target typeart-lcov-clean - name: Test TypeART lit-suite if: matrix.preset.skip_test == false - run: cmake --build build --target lit-pass-test + run: cmake --build build --target check-typeart - name: Build coverage report if: matrix.preset.coverage - run: cmake --build build --target lcov-html + run: cmake --build build --target typeart-lcov-html - name: Prepare coverage artifact if: matrix.preset.coverage diff --git a/AUTHORS b/AUTHORS index cdf465cb..df2c1338 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,4 @@ -# This is the official list of TypeART authors for copyright purposes. +# This is the official list of TypeART contributors. # Names should be added to this file as one of # Organization's name @@ -10,6 +10,7 @@ TU Darmstadt, Darmstadt, Germany Jan-Patrick Lehr Alexander Hück Sebastian Kreutzer +Alexander Linne RWTH Aachen, Aachen, Germany Joachim Protze diff --git a/CMakeLists.txt b/CMakeLists.txt index 65058fe3..94017f4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) project(typeart - VERSION 1.7 + VERSION 1.8 HOMEPAGE_URL https://github.com/tudasc/TypeART DESCRIPTION "LLVM-based type and memory allocation tracking sanitizer" ) @@ -13,8 +13,10 @@ else() set(TYPEART_IS_TOP_LEVEL false) endif() -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_VERBOSE_MAKEFILE ON) +if(TYPEART_IS_TOP_LEVEL) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + set(CMAKE_VERBOSE_MAKEFILE OFF) +endif() set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -24,13 +26,12 @@ list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ) -include(ToolchainOptions) +include(typeartToolchainOptions) -add_format_target( - format-sources "Formats project source files" +typeart_add_format_target( + typeart-format-sources "Formats project source files" TARGETS lib/passes/*.cpp lib/passes/*.h lib/runtime/*.cpp @@ -53,13 +54,13 @@ write_basic_package_version_file( COMPATIBILITY SameMinorVersion ) -set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) +set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}) set(LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) set(BINARY_INSTALL_DIR ${CMAKE_INSTALL_BINDIR}) set(CMAKE_INSTALL_DIR ${TYPEART_INSTALL_CONFIGDIR}) configure_package_config_file( - ${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in + ${PROJECT_SOURCE_DIR}/cmake/typeartConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake INSTALL_DESTINATION ${TYPEART_INSTALL_CONFIGDIR} PATH_VARS INCLUDE_INSTALL_DIR @@ -76,12 +77,14 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake # export(PACKAGE ${PROJECT_NAME}) if(TYPEART_IS_TOP_LEVEL) - enable_testing() - add_subdirectory(test) -endif() + if(TYPEART_TEST_CONFIG) + enable_testing() + add_subdirectory(test) + endif() -feature_summary(WHAT ENABLED_FEATURES PACKAGES_FOUND PACKAGES_NOT_FOUND - DESCRIPTION "TypeART ${PROJECT_VERSION} package and feature info:" - INCLUDE_QUIET_PACKAGES - QUIET_ON_EMPTY -) + feature_summary(WHAT ENABLED_FEATURES PACKAGES_FOUND PACKAGES_NOT_FOUND + DESCRIPTION "TypeART ${PROJECT_VERSION} package and feature info:" + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + ) +endif() diff --git a/CMakePresets.json b/CMakePresets.json index e7ec4c1b..17d0a0da 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -19,39 +19,39 @@ "name": "tsan", "hidden": true, "cacheVariables": { - "ENABLE_ASAN": "OFF", - "ENABLE_UBSAN": "OFF", - "ENABLE_TSAN": "ON" + "TYPEART_ASAN": "OFF", + "TYPEART_UBSAN": "OFF", + "TYPEART_TSAN": "ON" } }, { "name": "san", "hidden": true, "cacheVariables": { - "ENABLE_ASAN": "ON", - "ENABLE_UBSAN": "ON", - "ENABLE_TSAN": "OFF" + "TYPEART_ASAN": "ON", + "TYPEART_UBSAN": "ON", + "TYPEART_TSAN": "OFF" } }, { "name": "thread-unsafe", "hidden": true, "cacheVariables": { - "DISABLE_THREAD_SAFETY": "ON" + "TYPEART_DISABLE_THREAD_SAFETY": "ON" } }, { "name": "safe-ptr", "hidden": true, "cacheVariables": { - "ENABLE_SAFEPTR": "ON" + "TYPEART_SAFEPTR": "ON" } }, { "name": "coverage", "hidden": true, "cacheVariables": { - "ENABLE_CODE_COVERAGE": "ON" + "TYPEART_CODE_COVERAGE": "ON" } }, { @@ -65,8 +65,8 @@ ], "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", - "TEST_CONFIG": "ON", - "SOFTCOUNTERS": "ON" + "TYPEART_TEST_CONFIG": "ON", + "TYPEART_SOFTCOUNTERS": "ON" } }, { @@ -89,7 +89,7 @@ "release" ], "cacheVariables": { - "SOFTCOUNTERS": "ON" + "TYPEART_SOFTCOUNTERS": "ON" } }, { @@ -137,8 +137,8 @@ "develop" ], "cacheVariables": { - "ENABLE_ASAN": "OFF", - "ENABLE_UBSAN": "OFF" + "TYPEART_ASAN": "OFF", + "TYPEART_UBSAN": "OFF" } }, { diff --git a/README.md b/README.md index db9cf2a2..b3e9a61f 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ MPI_Send((void*) array, length, MPI_DOUBLE, ...) MUST and TypeART also handle MPI [derived datatypes](https://www.mpi-forum.org/docs/mpi-3.1/mpi31-report/node77.htm) with complex underlying data structures, see our [MPI Demo](#13-example-mpi-demo). For more details, see -our [publications](#references), or download the current release (1.8 or higher) of MUST on +our [publications](#references), or download the current release of MUST (1.8 or higher has TypeART integrated) on its [project page](https://itc.rwth-aachen.de/must/). ## Table of Contents @@ -85,6 +85,9 @@ around Clang and MPI to apply TypeART in the `bin` folder of the TypeART install instrument heap, stack and global allocations. The MPI-wrappers also filter allocations that are not passed to an MPI call, see [Section 1.1.4](#114-filtering-allocations). +*Note*: Currently, the compilation process has to be serialied, e.g., `make -j 1`, due to extraction and consistency of +type information per translation unit. + #### 1.1.1 Building with TypeART A typical compile invocation may first compile code to object files and then link with any libraries: @@ -131,6 +134,20 @@ $> TYPEART_WRAPPER=OFF cmake -B build -DCMAKE_C_COMPILER=*TypeART bin*/typeart-c $> cmake --build build --target install ``` +##### MPI wrapper generation + +For MPI, we rely on detecting the vendor to generate wrappers with appropriate environment variables to force the use of +the Clang/LLVM compiler. +We support detection for OpenMPI, Intel MPI and MPICH based on `mpi.h` symbols, and use the following flags for setting +the Clang +compiler: + +| Vendor | Symbol | C compiler env. var | C++ compiler env. var | +|-----------|---------------|----------------------|------------------------| +| Open MPI | OPEN_MPI | OMPI_CC | OMPI_CXX | +| Intel MPI | I_MPI_VERSION | I_MPI_CC | I_MPI_CXX | +| MPICH | MPICH_NAME | MPICH_CC | MPICH_CXX | + ##### Internal wrapper invocation For reference, the wrapper script executes the following (pseudo): @@ -139,23 +156,25 @@ For reference, the wrapper script executes the following (pseudo): # Compile: 1.Code-To-LLVM | 2.TypeART_HEAP | 3.Optimize | 4.TypeART_Stack | 5.Object-file $> clang++ $(COMPILE_FLAGS) $(EMIT_LLVM_IR_FLAGS) code.cpp | opt $(TYPEART_PLUGIN) $(HEAP_ONLY_FLAGS) | opt -O2 -S | opt $(TYPEART_PLUGIN) $(STACK_ONLY_FLAGS) | llc $(TO_OBJECT_FILE) # Link: -$> clang++ $(LINK_FLAGS) -L$(TYPEART_LIBPATH) -ltypeart-rt code.o -o binary +$> clang++ $(LINK_FLAGS) -L$(TYPEART_LIBPATH) -ltypeartRuntime code.o -o binary ``` #### 1.1.2 Options for TypeART passes For modification of the pass behavior, we provide several options. -| Flag | Default | Description | -|---------------------------------|:------------:|--------------------------------------------------------------------------------------------| -| `typeart` | - | Invoke TypeART pass through LLVM `opt` | -| `typeart-outfile` | `types.yaml` | Serialized type layout information of user-defined types | -| `typeart-no-heap` | `false` | Do **not** instrument heap allocations | -| `typeart-alloca` | `false` | Instrument stack and global allocations | -| `typeart-stats` | `false` | Show instrumentation statistic counters | -| `call-filter` | `false` | Filter stack and global allocations. See also [Section 1.1.4](#114-filtering-allocations) | -| `call-filter-str` | `*MPI_*` | Filter string target (glob string) | -| `typeart-filter-pointer-alloca` | `true` | Filter stack alloca of pointers (typically generated by LLVM for references of stack vars) | +| Flag | Default | Description | +|-----------------------------|:------------:|----------------------------------------------------------------------------------------------------------------------------------------------------| +| `typeart` | - | Invoke TypeART pass through LLVM `opt` | +| `typeart-types` | `types.yaml` | Serialized type layout information of user-defined types. File location and name can also be controlled with the env variable `TYPEART_TYPE_FILE`. | +| `typeart-heap` | `true` | Instrument heap allocations | +| `typeart-stack` | `false` | Instrument stack and global allocations. Enables instrumentation of global allocations. | +| `typeart-global` | `false` | Instrument global allocations (see --typeart-stack). | +| `typeart-stats` | `false` | Show instrumentation statistic counters | +| `typeart-call-filter` | `false` | Filter stack and global allocations. See also [Section 1.1.4](#114-filtering-allocations) | +| `typeart-call-filter-str` | `*MPI_*` | Filter string target (glob string) | +| `typeart-filter-pointer-alloca` | `true` | Filter stack alloca of pointers (typically generated by LLVM for references of stack vars) | + ##### Example invocations @@ -180,19 +199,19 @@ For modification of the pass behavior, we provide several options. ``` - Stack- and global-only instrumentation (*no* stats): ```shell - opt $(TYPEART_PLUGIN) -typeart -typeart-no-heap=true -typeart-alloca + opt $(TYPEART_PLUGIN) -typeart -typeart-heap=true -typeart-stack ``` - Stack- and global-only instrumentation (with default filtering for MPI): ```shell - opt $(TYPEART_PLUGIN) -typeart -typeart-no-heap=true -typeart-alloca -call-filter + opt $(TYPEART_PLUGIN) -typeart -typeart-heap=false -typeart-stack -typeart-call-filter ``` - Filtering w.r.t. non-standard target API: ```shell - opt $(TYPEART_PLUGIN) -typeart -typeart-no-heap=true -typeart-alloca -call-filter -call-filter-str=MY_API* + opt $(TYPEART_PLUGIN) -typeart -typeart-heap=false -typeart-stack -typeart-call-filter -typeart-call-filter-str=MY_API* ``` - Combined instrumentation (with filtering): ```shell - opt $(TYPEART_PLUGIN) -typeart -typeart-alloca -call-filter + opt $(TYPEART_PLUGIN) -typeart -typeart-stack -typeart-call-filter ``` #### 1.1.3 Serialized type information @@ -325,19 +344,19 @@ $> cmake --build build --target install --parallel | Option | Default | Description | | --- | :---: | --- | -| `ENABLE_MPI_WRAPPER` | `ON` | Install TypeART MPI wrapper (mpic, mpic++). Requires MPI. | +| `TYPEART_MPI_WRAPPER` | `ON` | Install TypeART MPI wrapper (mpic, mpic++). Requires MPI. | ##### Runtime -| Option | Default | Description | -| --- | :---: | --- | -| `USE_ABSL` | `ON` | Enable usage of btree-backed map of the [Abseil project](https://abseil.io/) instead of `std::map` | -| `USE_BTREE` | `OFF` | *Deprecated*. Enable usage of a [btree-backed map](https://github.com/ahueck/cpp-btree) (alternative to Abseil) instead of `std::map` | -| `SOFTCOUNTERS` | `OFF` | Enable runtime tracking of #tracked addrs. / #distinct checks / etc. | -| `LOG_LEVEL_RT` | `0` | Granularity of runtime logger. 3 ist most verbose, 0 is least | +| Option | Default | Description | +|------------------------|:-------:|-------------------------------------------------------------------------------------------------------------------------| +| `TYPEART_ABSEIL` | `ON` | Enable usage of btree-backed map of the [Abseil project](https://abseil.io/) (LTS release) for storing allocation data. | +| `TYPEART_PHMAP` | `OFF` | Enable usage of a [btree-backed map](https://github.com/greg7mdp/parallel-hashmap) (alternative to Abseil). | +| `TYPEART_SOFTCOUNTERS` | `OFF` | Enable runtime tracking of #tracked addrs. / #distinct checks / etc. | +| `TYPEART_LOG_LEVEL_RT` | `0` | Granularity of runtime logger. 3 is most verbose, 0 is least. | @@ -349,8 +368,8 @@ Default mode is to protect the global data structure with a (shared) mutex. Two | Option | Default | Description | | --- | :---: | --- | -| `DISABLE_THREAD_SAFETY` | `OFF` | Disable thread safety of runtime | -| `ENABLE_SAFEPTR` | `OFF` | Instead of a mutex, use a special data structure wrapper for concurrency, see [object_threadsafe](https://github.com/AlexeyAB/object_threadsafe) | +| `TYPEART_DISABLE_THREAD_SAFETY` | `OFF` | Disable thread safety of runtime | +| `TYPEART_SAFEPTR` | `OFF` | Instead of a mutex, use a special data structure wrapper for concurrency, see [object_threadsafe](https://github.com/AlexeyAB/object_threadsafe) | @@ -360,10 +379,10 @@ Default mode is to protect the global data structure with a (shared) mutex. Two | Option | Default | Description | | --- | :---: | --- | -| `SHOW_STATS` | `ON` | Passes show compile-time summary w.r.t. allocations counts | -| `MPI_INTERCEPT_LIB` | `ON` | Library to intercept MPI calls by preloading and check whether TypeART tracks the buffer pointer | -| `MPI_LOGGER` | `ON` | Enable better logging support in MPI execution context | -| `LOG_LEVEL` | `0` | Granularity of pass logger. 3 ist most verbose, 0 is least | +| `TYPEART_SHOW_STATS` | `ON` | Passes show compile-time summary w.r.t. allocations counts | +| `TYPEART_MPI_INTERCEPT_LIB` | `ON` | Library to intercept MPI calls by preloading and check whether TypeART tracks the buffer pointer | +| `TYPEART_MPI_LOGGER` | `ON` | Enable better logging support in MPI execution context | +| `TYPEART_LOG_LEVEL` | `0` | Granularity of pass logger. 3 is most verbose, 0 is least | @@ -371,12 +390,12 @@ Default mode is to protect the global data structure with a (shared) mutex. Two -| Option | Default | Description | -| --- | :---: | --- | -| `TEST_CONFIG` | `OFF` | Set (force) logging levels to appropriate levels for test runner to succeed | -| `ENABLE_CODE_COVERAGE` | `OFF` | Enable code coverage statistics using LCOV 1.14 and genhtml (gcovr optional) | -| `ENABLE_LLVM_CODE_COVERAGE` | `OFF` | Enable llvm-cov code coverage statistics (llvm-cov and llvm-profdata required) | -| `ENABLE_ASAN, TSAN, UBSAN` | `OFF` | Enable Clang sanitizers (tsan is mutually exlusive w.r.t. ubsan and asan as they don't play well together) | +| Option | Default | Description | +| --- | :---: |--------------------------------------------------------------------------------------------------------------| +| `TYPEART_TEST_CONFIG` | `OFF` | Enable testing, and set (force) logging levels to appropriate levels for test runner to succeed | +| `TYPEART_CODE_COVERAGE` | `OFF` | Enable code coverage statistics using LCOV 1.14 and genhtml (gcovr optional) | +| `TYPEART_LLVM_CODE_COVERAGE` | `OFF` | Enable llvm-cov code coverage statistics (llvm-cov and llvm-profdata required) | +| `TYPEART_ASAN, TSAN, UBSAN` | `OFF` | Enable Clang sanitizers (tsan is mutually exclusive w.r.t. ubsan and asan as they don't play well together) | diff --git a/cmake/ToolchainOptions.cmake b/cmake/ToolchainOptions.cmake deleted file mode 100644 index 54f4086a..00000000 --- a/cmake/ToolchainOptions.cmake +++ /dev/null @@ -1,167 +0,0 @@ -include(CMakeDependentOption) -include(CMakePackageConfigHelpers) -include(GNUInstallDirs) -include(FeatureSummary) - -find_package(LLVM CONFIG HINTS "${LLVM_DIR}" NO_DEFAULT_PATH) -if(NOT LLVM_FOUND) - message(STATUS "LLVM not found at: ${LLVM_DIR}.") - find_package(LLVM 10 REQUIRED CONFIG) -endif() -set_package_properties(LLVM PROPERTIES - URL https://llvm.org/ - TYPE REQUIRED - PURPOSE - "LLVM framework installation required to compile (and apply) TypeART." -) - -message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") - -list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") - -find_package(OpenMP QUIET) -set_package_properties(OpenMP PROPERTIES - TYPE OPTIONAL - PURPOSE - "OpenMP is optionally used by the test suite to verify that the LLVM passes handle OpenMPk codes." -) - -set(LOG_LEVEL 0 CACHE STRING "Granularity of LLVM pass logger. 3 ist most verbose, 0 is least.") -set(LOG_LEVEL_RT 0 CACHE STRING "Granularity of runtime logger. 3 ist most verbose, 0 is least.") - -option(SHOW_STATS "Passes show the statistics vars." ON) -add_feature_info(SHOW_STATS SHOW_STATS "Show compile time statistics of TypeART's LLVM passes.") - -option(MPI_LOGGER "Whether the logger should use MPI." ON) -add_feature_info(MPI_LOGGER MPI_LOGGER "Logger supports MPI context.") - -option(MPI_INTERCEPT_LIB "Build MPI interceptor library for prototyping and testing." ON) -add_feature_info(MPI_INTERCEPT_LIB MPI_INTERCEPT_LIB "Build TypeART's MPI tool, which intercepts MPI calls and applies buffer checks.") - -option(SOFTCOUNTERS "Enable software tracking of #tracked addrs. / #distinct checks / etc." OFF) -add_feature_info(SOFTCOUNTER SOFTCOUNTERS "Runtime collects various counters of memory ops/check operations.") - -option(TEST_CONFIG "Set logging levels to appropriate levels for test runner to succeed" OFF) -add_feature_info(TEST_CONFIG TEST_CONFIG "Test config to support lit test suite with appropriate diagnostic logging levels.") - -option(ENABLE_CODE_COVERAGE "Enable code coverage statistics" OFF) -add_feature_info(CODE_COVERAGE ENABLE_CODE_COVERAGE "Enable code coverage with lcov.") - -option(ENABLE_LLVM_CODE_COVERAGE "Enable llvm-cov code coverage statistics" OFF) -add_feature_info(LLVM_CODE_COVERAGE ENABLE_LLVM_CODE_COVERAGE "Enable LLVM code coverage with llvm-cov.") - -option(ENABLE_SAFEPTR "Use external safe_ptr map wrapper instead of mutex" OFF) -add_feature_info(SAFEPTR ENABLE_SAFEPTR "External library object_threadsafe provides lock-free runtime pointer map wrapper.") - -cmake_dependent_option(DISABLE_THREAD_SAFETY "Explicitly make runtime *not* thread-safe." OFF - "NOT ENABLE_SAFEPTR" OFF -) -add_feature_info(DISABLE_THREAD_SAFETY DISABLE_THREAD_SAFETY "Thread-safety features of runtime disabled.") - -option(ENABLE_TSAN "Build runtime lib and tests with fsanitize=thread" OFF) -add_feature_info(TSAN ENABLE_TSAN "Build with sanitizer \"tsan\".") - -cmake_dependent_option(ENABLE_ASAN "Build runtime lib and tests with fsanitize=address." OFF - "NOT ENABLE_TSAN" OFF -) -add_feature_info(ASAN ENABLE_ASAN "Build with sanitizer \"asan\".") - -cmake_dependent_option(ENABLE_UBSAN "Build runtime lib and tests with fsanitize=undefined." OFF - "NOT ENABLE_TSAN" OFF -) -add_feature_info(UBSAN ENABLE_UBSAN "Build with sanitizer \"ubsan=undefined\".") - -option(ENABLE_MPI_WRAPPER "Generate mpicc and mpic++ wrapper for TypeART" ON) -add_feature_info(MPI_WRAPPER ENABLE_MPI_WRAPPER "Generate TypeART compiler wrapper for mpicc and mpic++.") - -option(USE_ABSL "Enable usage of abseil's btree-backed map instead of std::map for the runtime." ON) -add_feature_info(ABSL USE_ABSL "External library \"Abseil\" replaces runtime std::map with btree-backed map.") - -cmake_dependent_option(USE_BTREE "Enable usage of btree-backed map instead of std::map for the runtime." ON - "NOT USE_ABSL" OFF -) -add_feature_info(BTREE USE_BTREE "*Deprecated* External library replaces runtime std::map with btree-backed map.") - -option(INSTALL_UTIL_SCRIPTS "Install single file build and run scripts" OFF) -mark_as_advanced(INSTALL_UTIL_SCRIPTS) - -option(TEST_CONFIGURE_IDE "Add targets so the IDE (e.g., Clion) can interpret test files better" ON) -mark_as_advanced(TEST_CONFIGURE_IDE) - -include(AddLLVM) -include(llvm-lit) -include(clang-tidy) -include(clang-format) -include(llvm-util) -include(log-util) -include(coverage) -include(sanitizer-targets) -include(target-util) - -if(TEST_CONFIG) - set(LOG_LEVEL 2 CACHE STRING "" FORCE) - set(LOG_LEVEL_RT 3 CACHE STRING "" FORCE) -endif() - -set(THREADS_PREFER_PTHREAD_FLAG 1) -set(CMAKE_THREAD_PREFER_PTHREAD 1) -if(NOT DISABLE_THREAD_SAFETY) - find_package(Threads REQUIRED) -else() - find_package(Threads QUIET) -endif() -set_package_properties(Threads PROPERTIES - TYPE RECOMMENDED - PURPOSE - "Threads are needed to compile our thread-safe typeart::Runtime due to use of std::mutex etc." -) - -if(MPI_LOGGER - OR ENABLE_MPI_WRAPPER - OR MPI_INTERCEPT_LIB -) - find_package(MPI REQUIRED) -endif() -set_package_properties(MPI PROPERTIES - TYPE RECOMMENDED - PURPOSE - "The MPI library is needed for several TypeART components: MPI logging, MPI compiler wrapper, and the MPI interceptor tool." -) - -if(MPI_INTERCEPT_LIB) - find_package(Python3 REQUIRED) -endif() -set_package_properties(Python3 PROPERTIES - TYPE RECOMMENDED - PURPOSE - "The Python3 interpreter is used for lit-testing and the MPI interceptor tool code generation." -) - -typeart_find_llvm_progs(TYPEART_CLANG_EXEC "clang;clang-13;clang-12;clang-11;clang-10" "clang") -typeart_find_llvm_progs(TYPEART_CLANGCXX_EXEC "clang++;clang-13;clang-12;clang-11;clang++-10" "clang++") -typeart_find_llvm_progs(TYPEART_LLC_EXEC "llc;llc-13;llc-12;llc-11;llc-10" "llc") -typeart_find_llvm_progs(TYPEART_OPT_EXEC "opt;opt-13;opt-12;opt-11;opt-10" "opt") -typeart_find_llvm_progs(TYPEART_FILECHECK_EXEC "FileCheck;FileCheck-13;FileCheck-12;FileCheck-11;FileCheck-10" "FileCheck") - -if(NOT CMAKE_BUILD_TYPE) - # set default build type - set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) - message(STATUS "Building as debug (default)") -endif() - -if(NOT CMAKE_DEBUG_POSTFIX AND CMAKE_BUILD_TYPE STREQUAL "Debug") - set(CMAKE_DEBUG_POSTFIX "-d") -endif() - -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - # set default install path - set(CMAKE_INSTALL_PREFIX - "${typeart_SOURCE_DIR}/install/typeart" - CACHE PATH "Default install path" FORCE - ) - message(STATUS "Installing to (default): ${CMAKE_INSTALL_PREFIX}") -endif() - -set(TYPEART_PREFIX ${PROJECT_NAME}) -set(TARGETS_EXPORT_NAME ${TYPEART_PREFIX}Targets) -set(TYPEART_INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) diff --git a/cmake/modules/clang-format.cmake b/cmake/modules/clang-format.cmake index af6f2481..e70a8482 100644 --- a/cmake/modules/clang-format.cmake +++ b/cmake/modules/clang-format.cmake @@ -1,4 +1,4 @@ -function(add_format_target target comment) +function(typeart_add_format_target target comment) macro(filter_dir dir_name_) foreach (source_file ${ALL_CXX_FILES}) string(FIND ${source_file} ${dir_name_} EXCLUDE_FOUND) @@ -20,11 +20,12 @@ function(add_format_target target comment) filter_dir(${exclude}) endforeach() - find_program(FORMAT_COMMAND - NAMES clang-format clang-format-13 clang-format-12 clang-format-11 clang-format-10) - if(FORMAT_COMMAND) + typeart_find_llvm_progs(TYPEART_CLANG_FORMAT_EXEC + "clang-format-${LLVM_VERSION_MAJOR};clang-format" + ) + if(TYPEART_CLANG_FORMAT_EXEC) add_custom_target(${target} - COMMAND ${FORMAT_COMMAND} -i -style=file ${ARG_OTHER} ${ARG_UNPARSED_ARGUMENTS} + COMMAND ${TYPEART_CLANG_FORMAT_EXEC} -i -style=file ${ARG_OTHER} ${ARG_UNPARSED_ARGUMENTS} ${ALL_CXX_FILES} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMENT "${comment}" diff --git a/cmake/modules/clang-tidy.cmake b/cmake/modules/clang-tidy.cmake index 792f883c..9268d809 100644 --- a/cmake/modules/clang-tidy.cmake +++ b/cmake/modules/clang-tidy.cmake @@ -1,4 +1,4 @@ -function(add_tidy_target target comment) +function(typeart_add_tidy_target target comment) macro(filter_dir dir_name_) foreach(source_file ${ARG_SOURCES}) string(FIND ${source_file} ${dir_name_} EXCLUDE_FOUND) @@ -14,13 +14,13 @@ function(add_tidy_target target comment) filter_dir(${exclude}) endforeach() - find_program(TIDY_COMMAND - NAMES clang-tidy clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy-10 - HINTS ${LLVM_TOOLS_BINARY_DIR} + typeart_find_llvm_progs(TYPEART_CLANG_TIDY_EXEC + "clang-tidy-${LLVM_VERSION_MAJOR};clang-tidy" ) - if(TIDY_COMMAND) + + if(TYPEART_CLANG_TIDY_EXEC) add_custom_target(${target} - COMMAND ${TIDY_COMMAND} -p ${CMAKE_BINARY_DIR} + COMMAND ${TYPEART_CLANG_TIDY_EXEC} -p ${CMAKE_BINARY_DIR} ${ARG_OTHER} ${ARG_UNPARSED_ARGUMENTS} ${ARG_SOURCES} @@ -38,7 +38,7 @@ endfunction() function(add_tidy_fix_target target comment) cmake_parse_arguments(ARG "" "" "SOURCES;EXCLUDES;OTHER" ${ARGN}) - add_tidy_target(${target} "${comment}" + typeart_add_tidy_target(${target} "${comment}" SOURCES ${ARG_SOURCES} EXCLUDES ${ARG_EXCLUDES} OTHER ${ARG_OTHER} -fix @@ -46,7 +46,7 @@ function(add_tidy_fix_target target comment) endfunction() function(make_tidy_check name sources) - add_tidy_target(tidy-run-on-${name} + typeart_add_tidy_target(tidy-run-on-${name} "Clang-tidy run on ${name} translation units" SOURCES ${sources} OTHER --header-filter=${CMAKE_CURRENT_SOURCE_DIR} diff --git a/cmake/modules/coverage-gcovr.cmake b/cmake/modules/coverage-gcovr.cmake index 66c2f3c5..0fca125e 100644 --- a/cmake/modules/coverage-gcovr.cmake +++ b/cmake/modules/coverage-gcovr.cmake @@ -1,14 +1,14 @@ -if (ENABLE_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU") - find_program(GCOVR_COMMAND gcovr) - if(GCOVR_COMMAND) - add_custom_target(gcovr-report - COMMAND ${GCOVR_COMMAND} -r ${PROJECT_SOURCE_DIR} -e ${PROJECT_BINARY_DIR} -s -j 4 +if (TYPEART_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU") + find_program(TYPEART_GCOVR_EXEC gcovr) + if(TYPEART_GCOVR_EXEC) + add_custom_target(typeart-gcovr-report + COMMAND ${TYPEART_GCOVR_EXEC} -r ${PROJECT_SOURCE_DIR} -e ${PROJECT_BINARY_DIR} -s -j 4 WORKING_DIRECTORY ${PROJECT_BINARY_DIR} - COMMENT "Make coverage report" + COMMENT "Make coverage report with GCOVR tool." USES_TERMINAL ) else() - add_custom_target(gcovr-report + add_custom_target(typeart-gcovr-report COMMAND ${CMAKE_COMMAND} -E echo "gcovr-report does nothing, no gcovr executable found.") endif() endif() diff --git a/cmake/modules/coverage-lcov.cmake b/cmake/modules/coverage-lcov.cmake index 336941bf..ea1cb827 100644 --- a/cmake/modules/coverage-lcov.cmake +++ b/cmake/modules/coverage-lcov.cmake @@ -1,42 +1,44 @@ -find_program(LCOV_COMMAND lcov) -find_program(GENHTML_COMMAND genhtml) +find_program(TYPEART_LCOV_EXEC lcov) +find_program(TYPEART_GENHTML_EXEC genhtml) -if(LCOV_COMMAND-NOTFOUND OR GENHTML_COMMAND-NOTFOUND) +if(TYPEART_LCOV_EXEC-NOTFOUND OR TYPEART_GENHTML_EXEC-NOTFOUND) message(WARNING "lcov and genhtml command needed for coverage.") endif() add_custom_target( - lcov-clean - COMMAND ${LCOV_COMMAND} -d ${CMAKE_BINARY_DIR} -z + typeart-lcov-clean + COMMAND ${TYPEART_LCOV_EXEC} -d ${CMAKE_BINARY_DIR} -z ) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - find_program(LLVMCOV_COMMAND REQUIRED - NAMES llvm-cov-${LLVM_VERSION_MAJOR} llvm-cov - ) + typeart_find_llvm_progs(TYPEART_LLVMCOV_EXEC "llvm-cov-${LLVM_VERSION_MAJOR};llvm-cov") + if(NOT TYPEART_LLVMCOV_EXEC) + message(FATAL_ERROR "Did not find llvm-cov, which is required for Clang-based LCOV coverage.") + endif() # workaround lcov and clang --coverage have a version mismatch set(GCOV_TOOL --gcov-tool ${CMAKE_BINARY_DIR}/scripts/llvm-gcov.sh) - # this autogenerated file in build/* causes error when using llvm-cov gcov (should be fine with gcc) + # these autogenerated file in build/* causes error when using llvm-cov gcov (should be fine with gcc), + # finally, CallSite.h should not be measured (extracted from LLVM 10 code base) set(GCOV_WORKAROUND --exclude *mpi_interceptor_rt.c --exclude */Version.cpp --exclude */CallSite.h) else() - # CallSite is taken from Clang 10, no need for coverage + # CallSite is taken from LLVM 10, no need for coverage set(GCOV_WORKAROUND --exclude */CallSite.h) endif() add_custom_target( - lcov-make - COMMAND ${LCOV_COMMAND} ${GCOV_TOOL} ${GCOV_WORKAROUND} + typeart-lcov-make + COMMAND ${TYPEART_LCOV_EXEC} ${GCOV_TOOL} ${GCOV_WORKAROUND} --no-external -c -d ${CMAKE_BINARY_DIR} -b ${CMAKE_SOURCE_DIR} -o typeart.coverage - COMMAND ${LCOV_COMMAND} --remove typeart.coverage '${CMAKE_BINARY_DIR}/*' -o typeart.coverage + COMMAND ${TYPEART_LCOV_EXEC} --remove typeart.coverage '${CMAKE_BINARY_DIR}/*' -o typeart.coverage ) add_custom_target( - lcov-html - COMMAND ${GENHTML_COMMAND} -o ${TYPEART_PROFILE_DIR} typeart.coverage - DEPENDS lcov-make + typeart-lcov-html + COMMAND ${TYPEART_GENHTML_EXEC} -o ${TYPEART_PROFILE_DIR} typeart.coverage + DEPENDS typeart-lcov-make ) -function(make_lcov_target target) +function(typeart_target_lcov target) # add_custom_target( # lcov-clean-${target} # COMMAND lcov -d ${CMAKE_BINARY_DIR} -z @@ -46,19 +48,19 @@ function(make_lcov_target target) get_target_property(LCOV_TARGET_SOURCE_DIR ${target} SOURCE_DIR) add_custom_target( - lcov-make-${target} - COMMAND ${LCOV_COMMAND} ${GCOV_TOOL} ${GCOV_WORKAROUND} + typeart-lcov-make-${target} + COMMAND ${TYPEART_LCOV_EXEC} ${GCOV_TOOL} ${GCOV_WORKAROUND} --no-external -c -d ${CMAKE_BINARY_DIR} -b ${LCOV_TARGET_SOURCE_DIR} -o counter-${target}.pro - COMMAND ${LCOV_COMMAND} --remove counter-${target}.pro '${CMAKE_BINARY_DIR}/*' + COMMAND ${TYPEART_LCOV_EXEC} --remove counter-${target}.pro '${CMAKE_BINARY_DIR}/*' -o counter-${target}.pro WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) add_custom_target( - lcov-html-${target} - COMMAND ${GENHTML_COMMAND} -o ${TYPEART_PROFILE_DIR} counter-${target}.pro + typeart-lcov-html-${target} + COMMAND ${TYPEART_GENHTML_EXEC} -o ${TYPEART_PROFILE_DIR} counter-${target}.pro WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS lcov-make-${target} + DEPENDS typeart-lcov-make-${target} ) endfunction() diff --git a/cmake/modules/coverage-llvm-cov.cmake b/cmake/modules/coverage-llvm-cov.cmake index 51bacf78..5c9f7b52 100644 --- a/cmake/modules/coverage-llvm-cov.cmake +++ b/cmake/modules/coverage-llvm-cov.cmake @@ -1,66 +1,60 @@ -find_program(LLVM_PROFDATA_COMMAND - NAMES llvm-profdata-10 llvm-profdata - HINTS ${LLVM_TOOLS_BINARY_DIR} -) -find_program(LLVMCOV_COMMAND - NAMES llvm-cov-10 llvm-cov - HINTS ${LLVM_TOOLS_BINARY_DIR} -) +typeart_find_llvm_progs(TYPEART_LLVM_PROFDATA_EXEC "llvm-profdata-${LLVM_VERSION_MAJOR};llvm-profdata") +typeart_find_llvm_progs(TYPEART_LLVMCOV_EXEC "llvm-cov-${LLVM_VERSION_MAJOR};llvm-cov") -if(LLVM_PROFDATA_COMMAND-NOTFOUND OR LLVMCOV_COMMAND-NOTFOUND) - message(WARNING "llvm-cov program stack needed for coverage.") +if(NOT TYPEART_LLVM_PROFDATA_EXEC OR NOT TYPEART_LLVMCOV_EXEC) + message(WARNING "llvm-cov and llvm-profdata programs needed for coverage.") endif() add_custom_target( - cov-merge - COMMAND ${LLVM_PROFDATA_COMMAND} merge -sparse -o code.pro *.profraw + typeart-cov-merge + COMMAND ${TYPEART_LLVM_PROFDATA_EXEC} merge -sparse -o code.pro *.profraw DEPENDS ${target} WORKING_DIRECTORY ${TYPEART_PROFILE_DIR} ) add_custom_target( - cov-all-report - COMMAND ${LLVMCOV_COMMAND} report `cat -s ta-binaries.txt` + typeart-cov-all-report + COMMAND ${TYPEART_LLVMCOV_EXEC} report `cat -s typeart-binaries.txt` --instr-profile=code.pro -ignore-filename-regex=${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${TYPEART_PROFILE_DIR} - DEPENDS cov-merge + DEPENDS typeart-cov-merge ) add_custom_target( - cov-clean - COMMAND rm ta-binaries.txt + typeart-cov-clean + COMMAND rm typeart-binaries.txt COMMAND rm *.pro WORKING_DIRECTORY ${TYPEART_PROFILE_DIR} ) add_custom_target( - cov-all-clean + typeart-cov-all-clean COMMAND rm * WORKING_DIRECTORY ${TYPEART_PROFILE_DIR} ) -function(make_llvm_cov_target target) +function(typeart_target_llvm_cov target) add_custom_target( - cov-binary-list-${target} - COMMAND ${CMAKE_COMMAND} -E echo "-object $" >> ta-binaries.txt + typeart-cov-binary-list-${target} + COMMAND ${CMAKE_COMMAND} -E echo "-object $" >> typeart-binaries.txt WORKING_DIRECTORY ${TYPEART_PROFILE_DIR} DEPENDS ${target} ) add_custom_target( - cov-merge-${target} - COMMAND ${LLVM_PROFDATA_COMMAND} merge -sparse -o code-${target}.pro *.profraw + typeart-cov-merge-${target} + COMMAND ${TYPEART_LLVM_PROFDATA_EXEC} merge -sparse -o code-${target}.pro *.profraw DEPENDS ${target} WORKING_DIRECTORY ${TYPEART_PROFILE_DIR} ) add_custom_target( - cov-report-${target} - COMMAND ${LLVMCOV_COMMAND} report -object $ + typeart-cov-report-${target} + COMMAND ${TYPEART_LLVMCOV_EXEC} report -object $ --instr-profile=code-${target}.pro -ignore-filename-regex=${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${TYPEART_PROFILE_DIR} - DEPENDS ${target} cov-merge-${target} + DEPENDS ${target} typeart-cov-merge-${target} ) - add_dependencies(cov-all-report cov-binary-list-${target}) + add_dependencies(typeart-cov-all-report typeart-cov-binary-list-${target}) endfunction() diff --git a/cmake/modules/coverage.cmake b/cmake/modules/coverage.cmake index df19d60c..183e4191 100644 --- a/cmake/modules/coverage.cmake +++ b/cmake/modules/coverage.cmake @@ -1,19 +1,19 @@ set(TYPEART_PROFILE_DIR ${CMAKE_BINARY_DIR}/profiles) file(MAKE_DIRECTORY ${TYPEART_PROFILE_DIR}) -if(NOT ENABLE_LLVM_CODE_COVERAGE AND ENABLE_CODE_COVERAGE) - include(coverage-gcovr) - include(coverage-lcov) +if(NOT TYPEART_LLVM_CODE_COVERAGE AND TYPEART_CODE_COVERAGE) + include(modules/coverage-gcovr) + include(modules/coverage-lcov) endif() -if(ENABLE_LLVM_CODE_COVERAGE) - include(coverage-llvm-cov) +if(TYPEART_LLVM_CODE_COVERAGE) + include(modules/coverage-llvm-cov) endif() -function(target_project_coverage_options target) +function(typeart_target_coverage_options target) get_target_property(target_type ${target} TYPE) - if (NOT ENABLE_LLVM_CODE_COVERAGE AND ENABLE_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + if (NOT TYPEART_LLVM_CODE_COVERAGE AND TYPEART_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_compile_options(${target} PUBLIC -O0 -g @@ -25,10 +25,10 @@ function(target_project_coverage_options target) ) if(NOT target_type STREQUAL "OBJECT_LIBRARY") - make_lcov_target(${target}) + typeart_target_lcov(${target}) endif() endif () - if (ENABLE_LLVM_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if (TYPEART_LLVM_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_compile_options(${target} PUBLIC -O0 -g @@ -41,7 +41,7 @@ function(target_project_coverage_options target) ) if(NOT target_type STREQUAL "OBJECT_LIBRARY") - make_llvm_cov_target(${target}) + typeart_target_llvm_cov(${target}) endif() endif () endfunction() diff --git a/cmake/modules/llvm-lit.cmake b/cmake/modules/llvm-lit.cmake deleted file mode 100644 index 53f4c272..00000000 --- a/cmake/modules/llvm-lit.cmake +++ /dev/null @@ -1,35 +0,0 @@ -find_package(Python3 QUIET) - -if(LLVM_EXTERNAL_LIT) - message(STATUS "External lit path is used") - get_llvm_lit_path( - lit_base_dir - lit_file_name - ALLOW_EXTERNAL - ) - set(PATH_TO_LIT ${lit_file_name}) - if(lit_base_dir) - set(PATH_TO_LIT ${lit_base_dir}/${PATH_TO_LIT}) - endif() - set(LIT_COMMAND_I "${Python3_EXECUTABLE};${PATH_TO_LIT}") -endif() - -if(NOT LIT_COMMAND_I) - find_program(LLVM_LIT_PATH - NAME llvm-lit lit lit.py - HINTS ${LLVM_TOOLS_BINARY_DIR} - PATHS ${LLVM_ROOT_DIR}/bin /usr/bin /usr/local/bin /opt/local/bin /usr/lib - ) - - if(LLVM_LIT_PATH) - get_filename_component(path_to_llvm_lit ${LLVM_LIT_PATH} ABSOLUTE CACHE) - set(LIT_COMMAND_I ${path_to_llvm_lit}) - set(LLVM_EXTERNAL_LIT ${LLVM_LIT_PATH}) - else() - message(WARNING "No llvm lit is available") - endif() -endif() - -mark_as_advanced(path_to_llvm_lit) - -message(STATUS "llvm lit command is set to ${LIT_COMMAND_I}") diff --git a/cmake/modules/llvm-util.cmake b/cmake/modules/llvm-util.cmake index 0916b6a5..c4b848c5 100644 --- a/cmake/modules/llvm-util.cmake +++ b/cmake/modules/llvm-util.cmake @@ -1,4 +1,4 @@ -function(make_llvm_module name sources) +function(typeart_make_llvm_module name sources) # TODO default of include_dirs is private cmake_parse_arguments(ARG "" "" "INCLUDE_DIRS;DEPENDS;LINK_LIBS" ${ARGN}) @@ -32,13 +32,13 @@ function(make_llvm_module name sources) ) if(ARG_INCLUDE_DIRS) - target_include_directories(${name} + target_include_directories(${name} ${warning_guard} PRIVATE ${ARG_INCLUDE_DIRS} ) endif() - target_define_file_basename(${name}) + typeart_target_define_file_basename(${name}) target_compile_definitions(${name} PRIVATE @@ -50,28 +50,48 @@ function(make_llvm_module name sources) ) endfunction() -function(typeart_find_llvm_progs target names default) +function(typeart_find_llvm_progs target names) + cmake_parse_arguments(ARG "ABORT_IF_MISSING;SHOW_VAR" "DEFAULT_EXE" "HINTS" ${ARGN}) + set(TARGET_TMP ${target}) + find_program( - target-prog + ${target} NAMES ${names} - HINTS ${LLVM_TOOLS_BINARY_DIR} + PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) - - if(NOT target-prog) - set(${target} - ${default} - PARENT_SCOPE - ) - message( - STATUS - "Did not find clang program ${names} in ${LLVM_TOOLS_BINARY_DIR}. Using def. value: ${default}" + if(NOT ${target}) + find_program( + ${target} + NAMES ${names} + HINTS ${ARG_HINTS} ) + endif() + + if(NOT ${target}) + set(target_missing_message "Did not find LLVM program ${names} in ${LLVM_TOOLS_BINARY_DIR} " + ", in system path or hints ${ARG_HINTS}.") + if(ARG_DEFAULT_EXE) + unset(${target} CACHE) + set(${target} + ${ARG_DEFAULT_EXE} + CACHE + STRING + "Default value for ${TARGET_TMP}." + ) + set(target_missing_message "${target_missing_message} Using default: ${ARG_DEFAULT_EXE}") + endif() + if(ARG_ABORT_IF_MISSING AND NOT ARG_DEFAULT_EXE) + message(SEND_ERROR ${target_missing_message}) + else() + message(STATUS ${target_missing_message}) + endif() + + endif() + + if(ARG_SHOW_VAR) + mark_as_advanced(CLEAR ${target}) else() - set(${target} - ${target-prog} - PARENT_SCOPE - ) + mark_as_advanced(${target}) endif() - unset(target-prog CACHE) endfunction() diff --git a/cmake/modules/log-util.cmake b/cmake/modules/log-util.cmake index 7fdb3f2c..f6f482b0 100644 --- a/cmake/modules/log-util.cmake +++ b/cmake/modules/log-util.cmake @@ -1,4 +1,4 @@ -function(target_define_file_basename targetname) +function(typeart_target_define_file_basename targetname) get_target_property(source_files "${targetname}" SOURCES) foreach(sourcefile ${source_files}) diff --git a/cmake/modules/sanitizer-targets.cmake b/cmake/modules/sanitizer-targets.cmake index 34b7138a..c930eb63 100644 --- a/cmake/modules/sanitizer-targets.cmake +++ b/cmake/modules/sanitizer-targets.cmake @@ -1,4 +1,4 @@ -function(target_sanitizer_options target) +function(typeart_target_sanitizer_options target) cmake_parse_arguments(ARG "" "" "SAN_FLAGS;LINK_FLAGS" ${ARGN}) target_compile_options(${target} @@ -20,37 +20,37 @@ function(target_sanitizer_options target) endfunction() -function(target_tsan_flags flags) +function(typeart_target_tsan_flags flags) set(${flags} -fsanitize=thread PARENT_SCOPE) endfunction() -function(target_asan_flags flags) +function(typeart_target_asan_flags flags) set(${flags} -fsanitize=address -fno-omit-frame-pointer PARENT_SCOPE) endfunction() -function(target_ubsan_flags flags) +function(typeart_target_ubsan_flags flags) set(${flags} -fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=undefined,integer PARENT_SCOPE) endfunction() -function(target_asan_options target) - target_asan_flags(asan_f) - target_sanitizer_options(${target} +function(typeart_target_asan_options target) + typeart_target_asan_flags(asan_f) + typeart_target_sanitizer_options(${target} SAN_FLAGS ${asan_f} ) endfunction() -function(target_ubsan_options target) - target_ubsan_flags(ubsan_f) - target_sanitizer_options(${target} +function(typeart_target_ubsan_options target) + typeart_target_ubsan_flags(ubsan_f) + typeart_target_sanitizer_options(${target} SAN_FLAGS ${ubsan_f} ) endfunction() -function(target_tsan_options target) - target_tsan_flags(tsan_f) - target_sanitizer_options(${target} +function(typeart_target_tsan_options target) + typeart_target_tsan_flags(tsan_f) + typeart_target_sanitizer_options(${target} SAN_FLAGS "${tsan_f}" ) diff --git a/cmake/modules/target-util.cmake b/cmake/modules/target-util.cmake index af8fe728..ae97ebfe 100644 --- a/cmake/modules/target-util.cmake +++ b/cmake/modules/target-util.cmake @@ -1,14 +1,16 @@ -function(target_project_compile_options target) +function(typeart_target_compile_options target) cmake_parse_arguments(ARG "" "" "PRIVATE_FLAGS;PUBLIC_FLAGS" ${ARGN}) - target_compile_options(${target} PRIVATE - -Wall -Wextra -pedantic - -Wunreachable-code -Wwrite-strings - -Wpointer-arith -Wcast-align - -Wcast-qual -Wno-unused-parameter - -Wunused -Wshadow - -Wformat=2 -Wundef -Werror=float-equal - ) + if (TYPEART_IS_TOP_LEVEL) + target_compile_options(${target} PRIVATE + -Wall -Wextra -pedantic + -Wunreachable-code -Wwrite-strings + -Wpointer-arith -Wcast-align + -Wcast-qual -Wno-unused-parameter + -Wunused -Wshadow + -Wformat=2 -Wundef -Werror=float-equal + ) + endif() target_compile_definitions(${target} PRIVATE "LLVM_VERSION_MAJOR=${LLVM_VERSION_MAJOR}") @@ -25,7 +27,7 @@ function(target_project_compile_options target) endif () endfunction() -function(target_project_compile_definitions target) +function(typeart_target_compile_definitions target) cmake_parse_arguments(ARG "" "" "PRIVATE_DEFS;PUBLIC_DEFS" ${ARGN}) if (ARG_PRIVATE_DEFS) @@ -41,7 +43,7 @@ function(target_project_compile_definitions target) endif () endfunction() -function (target_generate_file input output) +function (typeart_target_generate_file input output) file(READ ${input} contents) string(CONFIGURE "${contents}" contents @ONLY) file(GENERATE diff --git a/cmake/modules/version-helper.cmake b/cmake/modules/version-helper.cmake index 95c69993..f2cb8a4c 100644 --- a/cmake/modules/version-helper.cmake +++ b/cmake/modules/version-helper.cmake @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.14) + find_package(Git QUIET) if(EXISTS ${ROOT_DIR}/.git AND GIT_FOUND) diff --git a/cmake/Config.cmake.in b/cmake/typeartConfig.cmake.in similarity index 51% rename from cmake/Config.cmake.in rename to cmake/typeartConfig.cmake.in index 0eaba2e6..02d02675 100644 --- a/cmake/Config.cmake.in +++ b/cmake/typeartConfig.cmake.in @@ -4,12 +4,13 @@ set_and_check(TYPEART_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check(TYPEART_LIBRARY_DIR "@PACKAGE_LIBRARY_INSTALL_DIR@") set_and_check(TYPEART_BINARY_DIR "@PACKAGE_BINARY_INSTALL_DIR@") set_and_check(TYPEART_CMAKE_DIR "@PACKAGE_CMAKE_INSTALL_DIR@") +set(TYPEART_LLVM_VERSION @LLVM_PACKAGE_VERSION@) macro (check_components comps_list) set(@PROJECT_NAME@_FOUND true) foreach(component ${comps_list}) - if(NOT TARGET @PROJECT_NAME@::${component} AND NOT TARGET typeart::${component}Static) + if(NOT TARGET @PROJECT_NAME@::${component} AND NOT TARGET @PROJECT_NAME@::${component}Static) set(@PROJECT_NAME@_${component}_FOUND false) if(@PROJECT_NAME@_FIND_REQUIRED_${component}) message(WARNING "Could not find component ${component}") @@ -30,11 +31,32 @@ if (@PROJECT_NAME@_FIND_COMPONENTS) check_components("${@PROJECT_NAME@_FIND_COMPONENTS}") else() file(GLOB - target-file + @PROJECT_NAME@-target-file LIST_DIRECTORIES false "${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@*Targets.cmake" ) - foreach(component ${target-file}) - include(${component}) + foreach(component_file ${@PROJECT_NAME@-target-file}) + include(${component_file}) + string(REGEX MATCH "${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@(.*)Targets.cmake" COMP_NAME ${component_file}) + list(APPEND @PROJECT_NAME@_FIND_COMPONENTS "${CMAKE_MATCH_1}") endforeach() + check_components("${@PROJECT_NAME@_FIND_COMPONENTS}") endif() + +macro(find_@PROJECT_NAME@_script _prog_name _name) + if(NOT ${_prog_name}) + find_program(${_prog_name} ${_name} + PATHS @PACKAGE_BINARY_INSTALL_DIR@ + DOC "TypeART wrapper script \"${_name}\"" + NO_DEFAULT_PATH + ) + mark_as_advanced(${_prog_name}) + endif() +endmacro() + +foreach(script_file @TYPEART_INSTALL_SCRIPT_CANDIDATE@) + string(REPLACE "-" "_" script_file_name ${script_file}) + string(TOUPPER "${script_file_name}" script_file_name) + find_typeart_script(${script_file_name}_CMD ${script_file}) + find_typeart_script(${script_file_name}_CMD_DEBUG ${script_file}@TYPEART_DEBUG_POSTFIX@) +endforeach() diff --git a/cmake/typeartToolchainOptions.cmake b/cmake/typeartToolchainOptions.cmake new file mode 100644 index 00000000..acf99383 --- /dev/null +++ b/cmake/typeartToolchainOptions.cmake @@ -0,0 +1,201 @@ +include(CMakeDependentOption) +include(CMakePackageConfigHelpers) +include(FeatureSummary) +include(CheckCSourceCompiles) + +find_package(LLVM CONFIG HINTS "${LLVM_DIR}") +if(NOT LLVM_FOUND) + message(STATUS "LLVM not found at: ${LLVM_DIR}.") + find_package(LLVM REQUIRED CONFIG) +endif() +set_package_properties(LLVM PROPERTIES + URL https://llvm.org/ + TYPE REQUIRED + PURPOSE + "LLVM framework installation required to compile (and apply) TypeART." +) + +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") + +list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") + +find_package(OpenMP QUIET) +set_package_properties(OpenMP PROPERTIES + TYPE OPTIONAL + PURPOSE + "OpenMP is optionally used by the test suite to verify that the LLVM passes handle OpenMPk codes." +) + +set(TYPEART_LOG_LEVEL 0 CACHE STRING "Granularity of LLVM pass logger. 3 is most verbose, 0 is least.") +set(TYPEART_LOG_LEVEL_RT 0 CACHE STRING "Granularity of runtime logger. 3 is most verbose, 0 is least.") + +option(TYPEART_SHOW_STATS "Passes show the statistics vars." ON) +add_feature_info(SHOW_STATS TYPEART_SHOW_STATS "Show compile time statistics of TypeART's LLVM passes.") + +option(TYPEART_MPI_LOGGER "Whether the logger should use MPI." ON) +add_feature_info(MPI_LOGGER TYPEART_MPI_LOGGER "Logger supports MPI context.") + +option(TYPEART_MPI_INTERCEPT_LIB "Build MPI interceptor library for prototyping and testing." ON) +add_feature_info(MPI_INTERCEPT_LIB TYPEART_MPI_INTERCEPT_LIB "Build TypeART's MPI tool, which intercepts MPI calls and applies buffer checks.") + +option(TYPEART_SOFTCOUNTERS "Enable software tracking of #tracked addrs. / #distinct checks / etc." OFF) +add_feature_info(SOFTCOUNTER TYPEART_SOFTCOUNTERS "Runtime collects various counters of memory ops/check operations.") + +option(TYPEART_TEST_CONFIG "Set logging levels to appropriate levels for test runner to succeed" OFF) +add_feature_info(TEST_CONFIG TYPEART_TEST_CONFIG "Test config to support lit test suite with appropriate diagnostic logging levels.") + +option(TYPEART_CODE_COVERAGE "Enable code coverage statistics" OFF) +add_feature_info(CODE_COVERAGE TYPEART_CODE_COVERAGE "Enable code coverage with lcov.") + +option(TYPEART_LLVM_CODE_COVERAGE "Enable llvm-cov code coverage statistics" OFF) +add_feature_info(LLVM_CODE_COVERAGE TYPEART_LLVM_CODE_COVERAGE "Enable LLVM code coverage with llvm-cov.") + +option(TYPEART_SAFEPTR "Use external safe_ptr map wrapper instead of mutex" OFF) +add_feature_info(SAFEPTR TYPEART_SAFEPTR "External library object_threadsafe provides lock-free runtime pointer map wrapper.") + +cmake_dependent_option(TYPEART_DISABLE_THREAD_SAFETY "Explicitly make runtime *not* thread-safe." OFF + "NOT TYPEART_SAFEPTR" OFF +) +add_feature_info(DISABLE_THREAD_SAFETY TYPEART_DISABLE_THREAD_SAFETY "Thread-safety features of runtime disabled.") + +option(TYPEART_TSAN "Build runtime lib and tests with fsanitize=thread" OFF) +add_feature_info(TSAN TYPEART_TSAN "Build with sanitizer \"tsan\".") + +cmake_dependent_option(TYPEART_ASAN "Build runtime lib and tests with fsanitize=address." OFF + "NOT TYPEART_TSAN" OFF +) +add_feature_info(ASAN TYPEART_ASAN "Build with sanitizer \"asan\".") + +cmake_dependent_option(TYPEART_UBSAN "Build runtime lib and tests with fsanitize=undefined." OFF + "NOT TYPEART_TSAN" OFF +) +add_feature_info(UBSAN TYPEART_UBSAN "Build with sanitizer \"ubsan=undefined\".") + +option(TYPEART_MPI_WRAPPER "Generate mpicc and mpic++ wrapper for TypeART" ON) +add_feature_info(MPI_WRAPPER TYPEART_MPI_WRAPPER "Generate TypeART compiler wrapper for mpicc and mpic++.") + +option(TYPEART_ABSEIL "Enable usage of Abseil's btree-backed map instead of std::map for the runtime." ON) +add_feature_info(ABSEIL TYPEART_ABSEIL "External library \"Abseil\" replaces runtime std::map with btree-backed map.") + +cmake_dependent_option(TYPEART_PHMAP "Enable usage of project \"phmap\" btree-backed map for the runtime." ON + "NOT TYPEART_ABSEIL" OFF +) +add_feature_info(PHMAP TYPEART_PHMAP "External library \"parallel-hashmap\" replaces runtime std::map with btree-backed map.") + +option(TYPEART_INSTALL_UTIL_SCRIPTS "Install single file build and run scripts" OFF) +mark_as_advanced(TYPEART_INSTALL_UTIL_SCRIPTS) + +option(TYPEART_TEST_CONFIGURE_IDE "Add targets so the IDE (e.g., Clion) can interpret test files better" ON) +mark_as_advanced(TYPEART_TEST_CONFIGURE_IDE) + +option(TYPEART_CONFIG_DIR_IS_SHARE "Install to \"share/cmake/\" instead of \"lib/cmake/\"" OFF) +mark_as_advanced(TYPEART_CONFIG_DIR_IS_SHARE) + +set(warning_guard "") +if(NOT TYPEART_IS_TOP_LEVEL) + option( + TYPEART_INCLUDES_WITH_SYSTEM + "Use SYSTEM modifier for TypeART includes to disable warnings." + ON + ) + mark_as_advanced(TYPEART_INCLUDES_WITH_SYSTEM) + + if(TYPEART_INCLUDES_WITH_SYSTEM) + set(warning_guard SYSTEM) + endif() +endif() + +include(AddLLVM) +include(modules/clang-tidy) +include(modules/clang-format) +include(modules/llvm-util) +include(modules/log-util) +include(modules/coverage) +include(modules/sanitizer-targets) +include(modules/target-util) + +if(TYPEART_TEST_CONFIG) + set(TYPEART_LOG_LEVEL 2 CACHE STRING "" FORCE) + set(TYPEART_LOG_LEVEL_RT 3 CACHE STRING "" FORCE) +endif() + +set(THREADS_PREFER_PTHREAD_FLAG 1) +set(CMAKE_THREAD_PREFER_PTHREAD 1) +if(NOT TYPEART_DISABLE_THREAD_SAFETY) + find_package(Threads REQUIRED) +else() + find_package(Threads QUIET) +endif() +set_package_properties(Threads PROPERTIES + TYPE RECOMMENDED + PURPOSE + "Threads are needed to compile our thread-safe typeart::Runtime due to use of std::mutex etc." +) + +if(TYPEART_MPI_LOGGER + OR TYPEART_MPI_WRAPPER + OR TYPEART_MPI_INTERCEPT_LIB +) + find_package(MPI REQUIRED) +endif() +set_package_properties(MPI PROPERTIES + TYPE RECOMMENDED + PURPOSE + "The MPI library is needed for several TypeART components: MPI logging, MPI compiler wrapper, and the MPI interceptor tool." +) + +if(TYPEART_MPI_INTERCEPT_LIB) + find_package(Python3 REQUIRED) +endif() +set_package_properties(Python3 PROPERTIES + TYPE RECOMMENDED + PURPOSE + "The Python3 interpreter is used for lit-testing and the MPI interceptor tool code generation." +) + +typeart_find_llvm_progs(TYPEART_CLANG_EXEC "clang-${LLVM_VERSION_MAJOR};clang" DEFAULT_EXE "clang") +typeart_find_llvm_progs(TYPEART_CLANGCXX_EXEC "clang++-${LLVM_VERSION_MAJOR};clang++" DEFAULT_EXE "clang++") +typeart_find_llvm_progs(TYPEART_LLC_EXEC "llc-${LLVM_VERSION_MAJOR};llc" DEFAULT_EXE "llc") +typeart_find_llvm_progs(TYPEART_OPT_EXEC "opt-${LLVM_VERSION_MAJOR};opt" DEFAULT_EXE "opt") + +if(TYPEART_IS_TOP_LEVEL) + if(NOT CMAKE_BUILD_TYPE) + # set default build type + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) + message(STATUS "Building as debug (default)") + endif() + + if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + # set default install path + set(CMAKE_INSTALL_PREFIX + "${typeart_SOURCE_DIR}/install/typeart" + CACHE PATH "Default install path" FORCE + ) + message(STATUS "Installing to (default): ${CMAKE_INSTALL_PREFIX}") + endif() + + # TYPEART_DEBUG_POSTFIX is only used for Config + if(CMAKE_DEBUG_POSTFIX) + set(TYPEART_DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) + else() + set(TYPEART_DEBUG_POSTFIX "-d") + endif() + + # CMAKE_DEBUG_POSTFIX is used for targets + if(NOT CMAKE_DEBUG_POSTFIX AND CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CMAKE_DEBUG_POSTFIX ${TYPEART_DEBUG_POSTFIX}) + endif() +else() + set(TYPEART_DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) +endif() + +include(GNUInstallDirs) + +set(TYPEART_PREFIX ${PROJECT_NAME}) +set(TARGETS_EXPORT_NAME ${TYPEART_PREFIX}Targets) + +if(TYPEART_CONFIG_DIR_IS_SHARE) + set(TYPEART_INSTALL_CONFIGDIR ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}) +else() + set(TYPEART_INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) +endif() diff --git a/demo/01_struct_example.c b/demo/01_struct_example.c index 5fb06ce2..f7b01d57 100644 --- a/demo/01_struct_example.c +++ b/demo/01_struct_example.c @@ -3,7 +3,7 @@ #include #define MSG_TAG 666 -#define COUNT 5 +#define COUNT 5 // Comment out for heap allocation #define USE_STACK @@ -58,7 +58,7 @@ int main(int argc, char** argv) { MPI_Status status; MPI_Request request; - /* Get process and neighbour info. */ + /* Get process and neighbor info. */ MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); diff --git a/demo/02_broken_struct_example.c b/demo/02_broken_struct_example.c index f7de6505..7a9d5cd1 100644 --- a/demo/02_broken_struct_example.c +++ b/demo/02_broken_struct_example.c @@ -3,7 +3,7 @@ #include #define MSG_TAG 666 -#define COUNT 5 +#define COUNT 5 // Comment out for heap allocation //#define USE_STACK @@ -58,7 +58,7 @@ int main(int argc, char** argv) { MPI_Status status; MPI_Request request; - /* Get process and neighbour info. */ + /* Get process and neighbor info. */ MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 2b6f8887..cff9686f 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -7,11 +7,11 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(MPI REQUIRED) -function(make_mpi_target target) +function(demo_make_mpi_target target) target_link_libraries(${target} PUBLIC MPI::MPI_C) endfunction() -function(make_run_target target comment) +function(demo_make_run_target target comment) add_custom_target( run-${target} COMMAND env LD_PRELOAD=${CMAKE_BINARY_DIR}/libtool.so ${MPIEXEC} @@ -26,12 +26,12 @@ function(make_run_target target comment) endfunction() add_library(tool SHARED tool.c) -make_mpi_target(tool) +demo_make_mpi_target(tool) add_executable(demo 01_struct_example.c) -make_mpi_target(demo) -make_run_target(demo "Working demo") +demo_make_mpi_target(demo) +demo_make_run_target(demo "Working demo") add_executable(demo_broken 02_broken_struct_example.c) -make_mpi_target(demo_broken) -make_run_target(demo_broken "Broken demo") +demo_make_mpi_target(demo_broken) +demo_make_run_target(demo_broken "Broken demo") diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 1e3d005d..55cf82c2 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -8,14 +8,16 @@ mark_as_advanced( FETCHCONTENT_UPDATES_DISCONNECTED ) -if(USE_BTREE) - add_subdirectory(btree) +if(TYPEART_PHMAP) + #set(CMAKE_POLICY_DEFAULT_CMP0076 NEW) + add_subdirectory(phmap) endif() -if(USE_ABSL) +if(TYPEART_ABSEIL) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) add_subdirectory(abseil) endif() -if (ENABLE_SAFEPTR) +if (TYPEART_SAFEPTR) add_subdirectory(safe_ptr) endif() diff --git a/externals/abseil/CMakeLists.txt b/externals/abseil/CMakeLists.txt index 8527ca57..1ba151a6 100644 --- a/externals/abseil/CMakeLists.txt +++ b/externals/abseil/CMakeLists.txt @@ -3,6 +3,7 @@ set(ABSL_PROPAGATE_CXX_STD ON) FetchContent_Declare( cpp-abseil GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git + GIT_TAG 215105818dfde3174fe799600bb0f3cae233d0bf # LTS Nov. 2021 GIT_SHALLOW 1 ) diff --git a/externals/btree/CMakeLists.txt b/externals/btree/CMakeLists.txt deleted file mode 100644 index 70ec87a1..00000000 --- a/externals/btree/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -FetchContent_Declare( - cpp-btree - GIT_REPOSITORY https://github.com/ahueck/cpp-btree.git - GIT_SHALLOW 1 -) - -FetchContent_GetProperties(cpp-btree) - -if(NOT cpp-btree_POPULATED) - FetchContent_Populate(cpp-btree) - - add_library(cppbtree INTERFACE IMPORTED GLOBAL) - target_include_directories(cppbtree SYSTEM INTERFACE ${cpp-btree_SOURCE_DIR}) - #target_compile_features(cppbtree INTERFACE cxx_std_11 ) - add_library(google::btree ALIAS cppbtree) -endif() - -mark_as_advanced( - FETCHCONTENT_SOURCE_DIR_CPP-BTREE - FETCHCONTENT_UPDATES_DISCONNECTED_CPP-BTREE -) diff --git a/externals/phmap/CMakeLists.txt b/externals/phmap/CMakeLists.txt new file mode 100644 index 00000000..a0ab76ff --- /dev/null +++ b/externals/phmap/CMakeLists.txt @@ -0,0 +1,21 @@ +FetchContent_Declare( + phmap_phmap + GIT_REPOSITORY https://github.com/greg7mdp/parallel-hashmap.git + GIT_SHALLOW 1 + GIT_TAG 48e86db1f4ebc85145d384ba061c4f615cb3106f +) + +FetchContent_GetProperties(phmap_phmap) + +if(NOT phmap_phmap_POPULATED) + FetchContent_Populate(phmap_phmap) + + add_library(phmap_phmap INTERFACE IMPORTED GLOBAL) + target_include_directories(phmap_phmap SYSTEM INTERFACE ${phmap_phmap_SOURCE_DIR}) + add_library(phpmap::phpmap ALIAS phmap_phmap) +endif() + +mark_as_advanced( + FETCHCONTENT_SOURCE_DIR_PHMAP_PHMAP + FETCHCONTENT_UPDATES_DISCONNECTED_PHMAP_PHMAP +) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 997d59c2..4e0fb62e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -3,6 +3,6 @@ add_subdirectory(passes) add_subdirectory(typelib) add_subdirectory(runtime) -if(${MPI_INTERCEPT_LIB}) +if(${TYPEART_MPI_INTERCEPT_LIB}) add_subdirectory(mpi_interceptor) endif() diff --git a/lib/mpi_interceptor/CMakeLists.txt b/lib/mpi_interceptor/CMakeLists.txt index 7fe9588a..dafa153e 100644 --- a/lib/mpi_interceptor/CMakeLists.txt +++ b/lib/mpi_interceptor/CMakeLists.txt @@ -9,40 +9,40 @@ add_custom_command( COMMENT "Generate PMPI wrapper" ) -add_library(MPITool SHARED ${LIB_SOURCE}) -set_property(TARGET MPITool PROPERTY OUTPUT_NAME "${PROJECT_NAME}MPITool") -add_library(typeart::MPITool ALIAS MPITool) +add_library(${TYPEART_PREFIX}_MPITool SHARED ${LIB_SOURCE}) +set_property(TARGET ${TYPEART_PREFIX}_MPITool PROPERTY OUTPUT_NAME "${PROJECT_NAME}MPITool") +add_library(typeart::MPITool ALIAS ${TYPEART_PREFIX}_MPITool) -set_property(TARGET MPITool PROPERTY C_STANDARD 11) -set_property(TARGET MPITool PROPERTY C_STANDARD_REQUIRED TRUE) +set_property(TARGET ${TYPEART_PREFIX}_MPITool PROPERTY C_STANDARD 11) +set_property(TARGET ${TYPEART_PREFIX}_MPITool PROPERTY C_STANDARD_REQUIRED TRUE) -target_define_file_basename(MPITool) +typeart_target_define_file_basename(${TYPEART_PREFIX}_MPITool) -target_include_directories(MPITool +target_include_directories(${TYPEART_PREFIX}_MPITool ${warning_guard} PUBLIC $ $ - $ + $ ) -target_include_directories(MPITool +target_include_directories(${TYPEART_PREFIX}_MPITool SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS} ) -if(ENABLE_TSAN) - target_tsan_options(MPITool) +if(TYPEART_TSAN) + typeart_target_tsan_options(${TYPEART_PREFIX}_MPITool) endif() -target_link_libraries(MPITool +target_link_libraries(${TYPEART_PREFIX}_MPITool PRIVATE typeart::Runtime MPI::MPI_C ) -set(CONFIG_NAME ${PROJECT_NAME}MPITool) +set(CONFIG_NAME ${PROJECT_NAME}${TYPEART_PREFIX}_MPITool) set(TARGETS_EXPORT_NAME ${CONFIG_NAME}Targets) install( - TARGETS MPITool + TARGETS ${TYPEART_PREFIX}_MPITool EXPORT ${TARGETS_EXPORT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/lib/passes/CMakeLists.txt b/lib/passes/CMakeLists.txt index 11a9ceae..9b04fc37 100644 --- a/lib/passes/CMakeLists.txt +++ b/lib/passes/CMakeLists.txt @@ -12,7 +12,7 @@ set(PASS_SOURCES instrumentation/Instrumentation.cpp ) -make_llvm_module( +typeart_make_llvm_module( ${TYPEART_PREFIX}_TransformPass "${PASS_SOURCES}" LINK_LIBS typeart::MemInstFinder typeart::TypesStatic @@ -33,12 +33,12 @@ set_target_properties( add_library(typeart::TransformPass ALIAS ${TYPEART_PREFIX}_TransformPass) target_compile_definitions( - ${TYPEART_PREFIX}_TransformPass PRIVATE LOG_LEVEL=${LOG_LEVEL} - $<$:LLVM_FORCE_ENABLE_STATS=1> + ${TYPEART_PREFIX}_TransformPass PRIVATE TYPEART_LOG_LEVEL=${TYPEART_LOG_LEVEL} + $<$:LLVM_FORCE_ENABLE_STATS=1> ) -target_project_compile_options(${TYPEART_PREFIX}_TransformPass) -target_project_coverage_options(${TYPEART_PREFIX}_TransformPass) +typeart_target_compile_options(${TYPEART_PREFIX}_TransformPass) +typeart_target_coverage_options(${TYPEART_PREFIX}_TransformPass) set(CONFIG_NAME ${PROJECT_NAME}TransformPass) set(TARGETS_EXPORT_NAME ${CONFIG_NAME}Targets) diff --git a/lib/passes/TypeARTPass.cpp b/lib/passes/TypeARTPass.cpp index 4c11cc0c..e78486eb 100644 --- a/lib/passes/TypeARTPass.cpp +++ b/lib/passes/TypeARTPass.cpp @@ -46,53 +46,81 @@ using namespace llvm; #define DEBUG_TYPE "typeart" -namespace { -static llvm::RegisterPass msp("typeart", "TypeArt type information", false, false); -} // namespace +static llvm::RegisterPass msp("typeart", "TypeArt type instrumentation sanitizer", false, + false); -static cl::opt ClTypeArtStats("typeart-stats", cl::desc("Show statistics for TypeArt type pass."), cl::Hidden, - cl::init(false)); +static cl::OptionCategory typeart_category("TypeART instrumentation pass", "These control the instrumentation."); -static cl::opt ClTypeFile("typeart-outfile", cl::desc("Location of the generated type file."), cl::Hidden, - cl::init("types.yaml")); +static cl::opt cl_typeart_type_file("typeart-types", cl::desc("Location of the generated type file."), + cl::cat(typeart_category)); -cl::opt ClIgnoreHeap("typeart-no-heap", cl::desc("Ignore heap allocation/free instruction."), cl::Hidden, - cl::init(false)); -cl::opt ClTypeArtAlloca("typeart-alloca", cl::desc("Track alloca instructions."), cl::Hidden, cl::init(false)); +static cl::opt cl_typeart_stats("typeart-stats", cl::desc("Show statistics for TypeArt type pass."), cl::Hidden, + cl::init(false), cl::cat(typeart_category)); -// MemInstFinderPass: -cl::opt ClFilterNonArrayAlloca("alloca-array-only", cl::desc("Only use alloca instructions of arrays."), - cl::Hidden, cl::init(false)); +static cl::opt cl_typeart_instrument_heap("typeart-heap", + cl::desc("Instrument heap allocation/free instructions."), + cl::init(true), cl::cat(typeart_category)); -cl::opt ClFilterMallocAllocPair("malloc-store-filter", - cl::desc("Filter allocs that get a store from a heap alloc."), cl::Hidden, - cl::init(false)); +static cl::opt cl_typeart_instrument_global("typeart-global", cl::desc("Instrument global allocations."), + cl::init(false), cl::cat(typeart_category)); -cl::opt ClFilterGlobal("filter-globals", cl::desc("Filter globals of a module."), cl::Hidden, cl::init(true)); - -cl::opt ClUseCallFilter("call-filter", cl::desc("Filter alloca instructions that are passed to specific calls."), - cl::Hidden, cl::init(false)); - -cl::opt ClCallFilterImpl("call-filter-impl", cl::desc("Select the filter implementation."), cl::Hidden, - cl::init("default")); - -cl::opt ClCallFilterGlob("call-filter-str", cl::desc("Filter values based on string."), cl::Hidden, - cl::init("*MPI_*")); - -cl::opt ClCallFilterDeepGlob("call-filter-deep-str", - cl::desc("Filter values based on API, i.e., passed as void*."), cl::Hidden, - cl::init("MPI_*")); - -cl::opt ClCallFilterCGFile("call-filter-cg-file", cl::desc("Location of CG to use."), cl::Hidden, - cl::init("")); - -// Deprecated, only used with the old std filter: -cl::opt ClCallFilterDeep("call-filter-deep", - cl::desc("If the CallFilter matches, we look if the value is passed as a void*."), - cl::Hidden, cl::init(false)); - -cl::opt ClFilterPointerStack("typeart-filter-pointer-alloca", cl::desc("Filter allocas of pointers."), cl::Hidden, - cl::init(true)); +static cl::opt cl_typeart_instrument_stack( + "typeart-stack", cl::desc("Instrument stack (alloca) allocations. Turns on global instrumentation."), + cl::init(false), cl::cat(typeart_category), cl::callback([](const bool& opt) { + if (opt) { + ::cl_typeart_instrument_global = true; + } + })); + +static cl::opt cl_typeart_instrument_stack_lifetime( + "typeart-stack-lifetime", cl::desc("Instrument lifetime.start intrinsic instead of alloca."), cl::init(true), + cl::cat(typeart_category)); + +static cl::OptionCategory typeart_meminstfinder_category( + "TypeART memory instruction finder", "These options control which memory instructions are collected/filtered."); + +static cl::opt cl_typeart_filter_stack_non_array("typeart-stack-array-only", + cl::desc("Only find stack (alloca) instructions of arrays."), + cl::Hidden, cl::init(false), + cl::cat(typeart_meminstfinder_category)); + +static cl::opt cl_typeart_filter_heap_alloc( + "typeart-malloc-store-filter", cl::desc("Filter alloca instructions that have a store from a heap allocation."), + cl::Hidden, cl::init(false), cl::cat(typeart_meminstfinder_category)); + +static cl::opt cl_typeart_filter_global("typeart-filter-globals", cl::desc("Filter globals of a module."), + cl::Hidden, cl::init(true), cl::cat(typeart_meminstfinder_category)); + +static cl::opt cl_typeart_call_filter( + "typeart-call-filter", + cl::desc("Filter (stack/global) alloca instructions that are passed to specific function calls."), cl::Hidden, + cl::init(false), cl::cat(typeart_meminstfinder_category)); + +static cl::opt cl_typeart_call_filter_implementation( + "typeart-call-filter-impl", cl::desc("Select the call filter implementation."), + cl::values(clEnumValN(typeart::analysis::FilterImplementation::none, "none", "No filter"), + clEnumValN(typeart::analysis::FilterImplementation::standard, "std", + "Standard forward filter (default)"), + clEnumValN(typeart::analysis::FilterImplementation::cg, "cg", "Call-graph-based filter")), + cl::Hidden, cl::init(typeart::analysis::FilterImplementation::standard), cl::cat(typeart_meminstfinder_category)); + +static cl::opt cl_typeart_call_filter_glob( + "typeart-call-filter-str", cl::desc("Filter allocas based on the function name (glob) ."), cl::Hidden, + cl::init("*MPI_*"), cl::cat(typeart_meminstfinder_category)); + +static cl::opt cl_typeart_call_filter_glob_deep( + "typeart-call-filter-deep-str", + cl::desc("Filter allocas based on specific API, i.e., value passed as void* are correlated when string matched and " + "possibly kept."), + cl::Hidden, cl::init("MPI_*"), cl::cat(typeart_meminstfinder_category)); + +static cl::opt cl_typeart_call_filter_cg_file("typeart-call-filter-cg-file", + cl::desc("Location of call-graph file to use."), cl::Hidden, + cl::init(""), cl::cat(typeart_meminstfinder_category)); + +static cl::opt cl_typeart_filter_pointer_alloca("typeart-filter-pointer-alloca", + cl::desc("Filter allocas of pointer types."), cl::Hidden, + cl::init(true), cl::cat(typeart_meminstfinder_category)); ALWAYS_ENABLED_STATISTIC(NumInstrumentedMallocs, "Number of instrumented mallocs"); ALWAYS_ENABLED_STATISTIC(NumInstrumentedFrees, "Number of instrumented frees"); @@ -105,44 +133,57 @@ namespace typeart::pass { char TypeArtPass::ID = 0; TypeArtPass::TypeArtPass() : llvm::ModulePass(ID) { - assert(!ClTypeFile.empty() && "Default type file not set"); - analysis::MemInstFinderConfig conf{ClIgnoreHeap, // - ClTypeArtAlloca, // - analysis::MemInstFinderConfig::Filter{ClFilterNonArrayAlloca, // - ClFilterMallocAllocPair, // - ClFilterGlobal, // - ClUseCallFilter, // - ClCallFilterDeep, // - ClFilterPointerStack, // - ClCallFilterImpl, // - ClCallFilterGlob, // - ClCallFilterDeepGlob, // - ClCallFilterCGFile}}; + analysis::MemInstFinderConfig conf{cl_typeart_instrument_heap, // + cl_typeart_instrument_stack, // + cl_typeart_instrument_global, // + analysis::MemInstFinderConfig::Filter{cl_typeart_filter_stack_non_array, // + cl_typeart_filter_heap_alloc, // + cl_typeart_filter_global, // + cl_typeart_call_filter, // + cl_typeart_filter_pointer_alloca, // + cl_typeart_call_filter_implementation, // + cl_typeart_call_filter_glob, // + cl_typeart_call_filter_glob_deep, // + cl_typeart_call_filter_cg_file}}; meminst_finder = analysis::create_finder(conf); EnableStatistics(false); } void TypeArtPass::getAnalysisUsage(llvm::AnalysisUsage& info) const { - // info.addRequired(); } bool TypeArtPass::doInitialization(Module& m) { - typeManager = make_typegen(ClTypeFile.getValue()); + const auto types_file = [&]() -> std::string { + if (!cl_typeart_type_file.empty()) { + LOG_DEBUG("Using cl::opt for types file " << cl_typeart_type_file.getValue()) + return cl_typeart_type_file.getValue(); + } + const char* type_file = std::getenv("TYPEART_TYPE_FILE"); + if (type_file != nullptr) { + LOG_DEBUG("Using env var for types file " << type_file) + return std::string{type_file}; + } + LOG_DEBUG("Loading default types file " << default_types_file) + return default_types_file; + }(); + + typeManager = make_typegen(types_file); LOG_DEBUG("Propagating type infos."); const auto [loaded, error] = typeManager->load(); if (loaded) { - LOG_DEBUG("Existing type configuration successfully loaded from " << ClTypeFile.getValue()); + LOG_DEBUG("Existing type configuration successfully loaded from " << cl_typeart_type_file.getValue()); } else { - LOG_DEBUG("No valid existing type configuration found: " << ClTypeFile.getValue() + LOG_DEBUG("No valid existing type configuration found: " << cl_typeart_type_file.getValue() << ". Reason: " << error.message()); } instrumentation_helper.setModule(m); - auto arg_collector = std::make_unique(typeManager.get(), instrumentation_helper); - auto mem_instrument = std::make_unique(functions, instrumentation_helper); + auto arg_collector = std::make_unique(typeManager.get(), instrumentation_helper); + auto mem_instrument = + std::make_unique(functions, instrumentation_helper, cl_typeart_instrument_stack_lifetime); instrumentation_context = std::make_unique(std::move(arg_collector), std::move(mem_instrument)); @@ -153,7 +194,7 @@ bool TypeArtPass::runOnModule(Module& m) { meminst_finder->runOnModule(m); bool instrumented_global{false}; - if (ClTypeArtAlloca) { + if (cl_typeart_instrument_global) { declareInstrumentationFunctions(m); const auto& globalsList = meminst_finder->getModuleGlobals(); @@ -197,7 +238,7 @@ bool TypeArtPass::runOnFunc(Function& f) { const auto& allocas = fData.allocas; const auto& frees = fData.frees; - if (!ClIgnoreHeap) { + if (cl_typeart_instrument_heap) { // instrument collected calls of bb: const auto heap_count = instrumentation_context->handleHeap(mallocs); const auto free_count = instrumentation_context->handleFree(frees); @@ -207,7 +248,8 @@ bool TypeArtPass::runOnFunc(Function& f) { mod |= heap_count > 0 || free_count > 0; } - if (ClTypeArtAlloca) { + + if (cl_typeart_instrument_stack) { const auto stack_count = instrumentation_context->handleStack(allocas); NumInstrumentedAlloca += stack_count; mod |= stack_count > 0; @@ -220,15 +262,15 @@ bool TypeArtPass::doFinalization(Module&) { /* * Persist the accumulated type definition information for this module. */ - LOG_DEBUG("Writing type file to " << ClTypeFile.getValue()); + LOG_DEBUG("Writing type file to " << cl_typeart_type_file.getValue()); const auto [stored, error] = typeManager->store(); if (stored) { LOG_DEBUG("Success!"); } else { - LOG_FATAL("Failed writing type config to " << ClTypeFile.getValue() << ". Reason: " << error.message()); + LOG_FATAL("Failed writing type config to " << cl_typeart_type_file.getValue() << ". Reason: " << error.message()); } - if (ClTypeArtStats) { + if (cl_typeart_stats) { auto& out = llvm::errs(); printStats(out); } @@ -266,8 +308,8 @@ void TypeArtPass::printStats(llvm::raw_ostream& out) { meminst_finder->printStats(out); const auto get_ta_mode = [&]() { - const bool heap = !ClIgnoreHeap.getValue(); - const bool stack = ClTypeArtAlloca.getValue(); + const bool heap = cl_typeart_instrument_heap.getValue(); + const bool stack = cl_typeart_instrument_stack.getValue(); if (heap) { if (stack) { diff --git a/lib/passes/TypeARTPass.h b/lib/passes/TypeARTPass.h index bbc83f5e..d7ad7f0b 100644 --- a/lib/passes/TypeARTPass.h +++ b/lib/passes/TypeARTPass.h @@ -43,6 +43,8 @@ namespace typeart::pass { class TypeArtPass : public llvm::ModulePass { private: + const std::string default_types_file{"types.yaml"}; + struct TypeArtFunc { const std::string name; llvm::Value* f{nullptr}; diff --git a/lib/passes/analysis/CMakeLists.txt b/lib/passes/analysis/CMakeLists.txt index 3b79acdc..20255891 100644 --- a/lib/passes/analysis/CMakeLists.txt +++ b/lib/passes/analysis/CMakeLists.txt @@ -19,15 +19,15 @@ target_link_libraries(${TYPEART_PREFIX}_MemInstFinder PUBLIC typeart::MemOpFilte target_compile_options(${TYPEART_PREFIX}_MemInstFinder PRIVATE "-fno-rtti") target_compile_definitions( - ${TYPEART_PREFIX}_MemInstFinder PRIVATE LOG_LEVEL=${LOG_LEVEL} - $<$:LLVM_FORCE_ENABLE_STATS=1> + ${TYPEART_PREFIX}_MemInstFinder PRIVATE TYPEART_LOG_LEVEL=${TYPEART_LOG_LEVEL} + $<$:LLVM_FORCE_ENABLE_STATS=1> ) set_target_properties(${TYPEART_PREFIX}_MemInstFinder PROPERTIES POSITION_INDEPENDENT_CODE ON) target_include_directories( - ${TYPEART_PREFIX}_MemInstFinder - PUBLIC $ + ${TYPEART_PREFIX}_MemInstFinder ${warning_guard} + PUBLIC $ $ $ $ @@ -37,6 +37,6 @@ target_include_directories(${TYPEART_PREFIX}_MemInstFinder SYSTEM PRIVATE ${LLVM make_tidy_check(${TYPEART_PREFIX}_MemInstFinder "${MEM_PASS_SOURCES}") -target_project_compile_options(${TYPEART_PREFIX}_MemInstFinder) -target_define_file_basename(${TYPEART_PREFIX}_MemInstFinder) -target_project_coverage_options(${TYPEART_PREFIX}_MemInstFinder) \ No newline at end of file +typeart_target_compile_options(${TYPEART_PREFIX}_MemInstFinder) +typeart_target_define_file_basename(${TYPEART_PREFIX}_MemInstFinder) +typeart_target_coverage_options(${TYPEART_PREFIX}_MemInstFinder) diff --git a/lib/passes/analysis/MemInstFinder.cpp b/lib/passes/analysis/MemInstFinder.cpp index 55d5603a..9ba06193 100644 --- a/lib/passes/analysis/MemInstFinder.cpp +++ b/lib/passes/analysis/MemInstFinder.cpp @@ -18,7 +18,6 @@ #include "filter/CGInterface.h" #include "filter/Filter.h" #include "filter/Matcher.h" -#include "filter/StandardFilter.h" #include "filter/StdForwardFilter.h" #include "support/Logger.h" #include "support/Table.h" @@ -81,18 +80,13 @@ namespace filter { namespace detail { static std::unique_ptr make_filter(const MemInstFinderConfig& config) { using namespace typeart::filter; - const bool deep = config.filter.ClCallFilterDeep; - const std::string id = config.filter.ClCallFilterImpl; + const auto filter_id = config.filter.implementation; const std::string glob = config.filter.ClCallFilterGlob; - if (id == "empty" || !config.filter.ClUseCallFilter) { + if (filter_id == FilterImplementation::none || !config.filter.ClUseCallFilter) { LOG_DEBUG("Return no-op filter") return std::make_unique(); - } else if (id == "deprecated::default") { - // default - LOG_DEBUG("Return deprecated default filter") - return std::make_unique(glob, deep); - } else if (id == "cg" || id == "experimental::cg") { + } else if (filter_id == FilterImplementation::cg) { if (config.filter.ClCallFilterCGFile.empty()) { LOG_FATAL("CG File not set!"); std::exit(1); @@ -168,11 +162,11 @@ class MemInstFinderPass : public MemInstFinder { }; MemInstFinderPass::MemInstFinderPass(const MemInstFinderConfig& config) - : mOpsCollector(config.ClTypeArtAlloca, !config.ClIgnoreHeap), filter(config), config(config) { + : mOpsCollector(config.collect_alloca, config.collect_heap), filter(config), config(config) { } bool MemInstFinderPass::runOnModule(Module& module) { - mOpsCollector.visitModuleGlobals(module); + mOpsCollector.collectGlobals(module); auto& globals = mOpsCollector.globals; NumDetectedGlobals += globals.size(); if (config.filter.ClFilterGlobal) { @@ -270,7 +264,7 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) { LOG_DEBUG("Running on function: " << function.getName()) - mOpsCollector.visit(function); + mOpsCollector.collect(function); const auto checkAmbigiousMalloc = [&function](const MallocData& mallocData) { using namespace typeart::util::type; @@ -294,7 +288,6 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) { NumDetectedAllocs += mOpsCollector.allocas.size(); - LOG_DEBUG(config.filter.ClFilterNonArrayAlloca); if (config.filter.ClFilterNonArrayAlloca) { auto& allocs = mOpsCollector.allocas; allocs.erase(llvm::remove_if(allocs, diff --git a/lib/passes/analysis/MemInstFinder.h b/lib/passes/analysis/MemInstFinder.h index 6f3016ee..7cff67ce 100644 --- a/lib/passes/analysis/MemInstFinder.h +++ b/lib/passes/analysis/MemInstFinder.h @@ -26,23 +26,26 @@ class raw_ostream; namespace typeart::analysis { +enum class FilterImplementation { none, standard, cg }; + struct MemInstFinderConfig { struct Filter { bool ClFilterNonArrayAlloca{false}; bool ClFilterMallocAllocPair{false}; bool ClFilterGlobal{true}; bool ClUseCallFilter{false}; - bool ClCallFilterDeep{false}; bool ClFilterPointerAlloca{false}; - std::string ClCallFilterImpl{"default"}; + // std::string ClCallFilterImpl{"default"}; + FilterImplementation implementation{FilterImplementation::standard}; std::string ClCallFilterGlob{"*MPI_*"}; std::string ClCallFilterDeepGlob{"MPI_*"}; std::string ClCallFilterCGFile{}; }; - bool ClIgnoreHeap{false}; - bool ClTypeArtAlloca{false}; + bool collect_heap{false}; + bool collect_alloca{false}; + bool collect_global{false}; Filter filter; }; diff --git a/lib/passes/analysis/MemOpData.h b/lib/passes/analysis/MemOpData.h index c0399c66..ddd75809 100644 --- a/lib/passes/analysis/MemOpData.h +++ b/lib/passes/analysis/MemOpData.h @@ -13,6 +13,7 @@ #ifndef TYPEART_MEMOPDATA_H #define TYPEART_MEMOPDATA_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" @@ -25,6 +26,7 @@ class GlobalVariable; class StoreInst; class Value; class GetElementPtrInst; +class IntrinsicInst; } // namespace llvm namespace typeart { @@ -145,6 +147,7 @@ struct AllocaData { llvm::AllocaInst* alloca{nullptr}; size_t array_size; bool is_vla{false}; + llvm::SmallPtrSet lifetime_start{}; }; struct GlobalData { diff --git a/lib/passes/analysis/MemOpVisitor.cpp b/lib/passes/analysis/MemOpVisitor.cpp index bc20deac..3103aeab 100644 --- a/lib/passes/analysis/MemOpVisitor.cpp +++ b/lib/passes/analysis/MemOpVisitor.cpp @@ -23,6 +23,11 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringRef.h" +#if LLVM_VERSION_MAJOR >= 12 +#include "llvm/Analysis/ValueTracking.h" // llvm::findAllocaForValue +#else +#include "llvm/Transforms/Utils/Local.h" // llvm::findAllocaForValue +#endif #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -41,18 +46,40 @@ using namespace llvm; MemOpVisitor::MemOpVisitor() : MemOpVisitor(true, true) { } -MemOpVisitor::MemOpVisitor(bool collectAllocas, bool collectHeap) - : collectAllocas(collectAllocas), collectHeap(collectHeap) { +MemOpVisitor::MemOpVisitor(bool collect_allocas, bool collect_heap) + : collect_allocas(collect_allocas), collect_heap(collect_heap) { } -void MemOpVisitor::visitModuleGlobals(Module& m) { - for (auto& g : m.globals()) { +void MemOpVisitor::collect(llvm::Function& function) { + visit(function); + + for (auto& [lifetime, alloc] : lifetime_starts) { + auto* data = + llvm::find_if(allocas, [alloc = std::ref(alloc)](const AllocaData& data) { return data.alloca == alloc; }); + if (data != std::end(allocas)) { + data->lifetime_start.insert(lifetime); + } + } + + for (const auto& alloc : allocas) { + if (alloc.lifetime_start.size() > 1) { + LOG_DEBUG("Lifetime: " << alloc.lifetime_start.size()); + LOG_DEBUG(*alloc.alloca); + for (auto* lifetime : alloc.lifetime_start) { + LOG_DEBUG(*lifetime); + } + } + } +} + +void MemOpVisitor::collectGlobals(Module& module) { + for (auto& g : module.globals()) { globals.emplace_back(GlobalData{&g}); } } void MemOpVisitor::visitCallBase(llvm::CallBase& cb) { - if (!collectHeap) { + if (!collect_heap) { return; } const auto isInSet = [&](const auto& fMap) -> llvm::Optional { @@ -240,7 +267,7 @@ void MemOpVisitor::visitFreeLike(llvm::CallBase& ci, MemOpKind k) { //} void MemOpVisitor::visitAllocaInst(llvm::AllocaInst& ai) { - if (!collectAllocas) { + if (!collect_allocas) { return; } // LOG_DEBUG("Found alloca " << ai); @@ -255,7 +282,21 @@ void MemOpVisitor::visitAllocaInst(llvm::AllocaInst& ai) { allocas.push_back({&ai, arraySize, is_vla}); // LOG_DEBUG("Alloca: " << util::dump(ai) << " -> lifetime marker: " << util::dump(lifetimes)); -} // namespace typeart +} + +void MemOpVisitor::visitIntrinsicInst(llvm::IntrinsicInst& inst) { + if (inst.getIntrinsicID() == Intrinsic::lifetime_start) { +#if LLVM_VERSION_MAJOR >= 12 + auto alloca = llvm::findAllocaForValue(inst.getOperand(1)); +#else + DenseMap alloca_for_value; + auto* alloca = llvm::findAllocaForValue(inst.getOperand(1), alloca_for_value); +#endif + if (alloca != nullptr) { + lifetime_starts.emplace_back(&inst, alloca); + } + } +} void MemOpVisitor::clear() { allocas.clear(); diff --git a/lib/passes/analysis/MemOpVisitor.h b/lib/passes/analysis/MemOpVisitor.h index 57236c32..be2f6d0b 100644 --- a/lib/passes/analysis/MemOpVisitor.h +++ b/lib/passes/analysis/MemOpVisitor.h @@ -21,6 +21,8 @@ namespace llvm { class AllocaInst; class CallBase; class Module; +class InstrinsicInst; +class Function; } // namespace llvm namespace typeart::analysis { @@ -30,23 +32,25 @@ struct MemOpVisitor : public llvm::InstVisitor { MallocDataList mallocs; FreeDataList frees; AllocaDataList allocas; + llvm::SmallVector, 16> lifetime_starts; private: MemOps mem_operations{}; - bool collectAllocas; - bool collectHeap; + bool collect_allocas; + bool collect_heap; public: MemOpVisitor(); - MemOpVisitor(bool collectAllocas, bool collectHeap); - - public: + MemOpVisitor(bool collect_allocas, bool collect_heap); + void collect(llvm::Function& function); + void collectGlobals(llvm::Module& module); void clear(); - void visitModuleGlobals(llvm::Module& m); + void visitCallBase(llvm::CallBase& cb); void visitMallocLike(llvm::CallBase& ci, MemOpKind k); void visitFreeLike(llvm::CallBase& ci, MemOpKind k); void visitAllocaInst(llvm::AllocaInst& ai); + void visitIntrinsicInst(llvm::IntrinsicInst& inst); }; } // namespace typeart::analysis diff --git a/lib/passes/compat/CallSite.h b/lib/passes/compat/CallSite.h index aa5d1ebe..3ce9ac21 100644 --- a/lib/passes/compat/CallSite.h +++ b/lib/passes/compat/CallSite.h @@ -157,8 +157,16 @@ class CallSiteBase { /// Set the callee to the specified value. Unlike the function of the same /// name on CallBase, does not modify the type! void setCalledFunction(Value* V) { + const auto elem_type = [&V]() { +#if LLVM_VERSION_MAJOR > 13 + return V->getType()->getPointerElementType(); +#else + return cast(V->getType())->getElementType(); +#endif + }; assert(getInstruction() && "Not a call, callbr, or invoke instruction!"); - assert(cast(V->getType())->getElementType() == cast(getInstruction())->getFunctionType() && + + assert(elem_type() == cast(getInstruction())->getFunctionType() && "New callee type does not match FunctionType on call"); *getCallee() = V; } diff --git a/lib/passes/filter/CMakeLists.txt b/lib/passes/filter/CMakeLists.txt index d12db578..bf7e3af2 100644 --- a/lib/passes/filter/CMakeLists.txt +++ b/lib/passes/filter/CMakeLists.txt @@ -1,6 +1,4 @@ set(FILTER_SOURCES - StandardFilter.cpp - StandardFilter.h CGInterface.cpp CGInterface.h Filter.h @@ -27,13 +25,13 @@ add_library(typeart::MemOpFilter ALIAS ${TYPEART_PREFIX}_MemOpFilter) # https://lists.llvm.org/pipermail/llvm-dev/2018-July/124534.html # target_link_libraries(${TYPEART_PREFIX}_MemOpFilter PUBLIC LLVMCore LLVMSupport ) -target_compile_definitions(${TYPEART_PREFIX}_MemOpFilter PRIVATE LOG_LEVEL=${LOG_LEVEL}) +target_compile_definitions(${TYPEART_PREFIX}_MemOpFilter PRIVATE TYPEART_LOG_LEVEL=${TYPEART_LOG_LEVEL}) set_target_properties(${TYPEART_PREFIX}_MemOpFilter PROPERTIES POSITION_INDEPENDENT_CODE ON) target_include_directories( - ${TYPEART_PREFIX}_MemOpFilter - PUBLIC $ + ${TYPEART_PREFIX}_MemOpFilter ${warning_guard} + PUBLIC $ $ $ $ @@ -43,9 +41,9 @@ target_include_directories(${TYPEART_PREFIX}_MemOpFilter SYSTEM PRIVATE ${LLVM_I make_tidy_check(${TYPEART_PREFIX}_MemOpFilter "${FILTER_SOURCES}") -target_project_compile_options(${TYPEART_PREFIX}_MemOpFilter) -target_define_file_basename(${TYPEART_PREFIX}_MemOpFilter) -target_project_coverage_options(${TYPEART_PREFIX}_MemOpFilter) +typeart_target_compile_options(${TYPEART_PREFIX}_MemOpFilter) +typeart_target_define_file_basename(${TYPEART_PREFIX}_MemOpFilter) +typeart_target_coverage_options(${TYPEART_PREFIX}_MemOpFilter) # For now, non-consumable filter: #install( diff --git a/lib/passes/filter/StandardFilter.cpp b/lib/passes/filter/StandardFilter.cpp deleted file mode 100644 index 042b375e..00000000 --- a/lib/passes/filter/StandardFilter.cpp +++ /dev/null @@ -1,247 +0,0 @@ -// TypeART library -// -// Copyright (c) 2017-2022 TypeART Authors -// Distributed under the BSD 3-Clause license. -// (See accompanying file LICENSE.txt or copy at -// https://opensource.org/licenses/BSD-3-Clause) -// -// Project home: https://github.com/tudasc/TypeART -// -// SPDX-License-Identifier: BSD-3-Clause -// - -#include "StandardFilter.h" - -#include "compat/CallSite.h" -#include "support/Logger.h" -#include "support/Util.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/Argument.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Use.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/raw_ostream.h" - -#include -#include - -namespace typeart::filter::deprecated { - -StandardFilter::StandardFilter(const std::string& glob, bool CallFilterDeep) - : call_regex(util::glob2regex(glob)), ClCallFilterDeep(CallFilterDeep) { -} - -void StandardFilter::setMode(bool search_malloc) { - malloc_mode = search_malloc; -} - -void StandardFilter::setStartingFunction(llvm::Function* start) { - start_f = start; - depth = 0; -} - -bool StandardFilter::filter(Value* in) { - if (in == nullptr) { - LOG_DEBUG("Called with nullptr"); - return false; - } - - if (depth == 15) { - return false; - } - - const auto match = [&](auto callee) -> bool { - const auto name = StandardFilter::getName(callee); - return util::regex_matches(call_regex, name); - }; - - llvm::SmallPtrSet visited_set; - llvm::SmallVector working_set; - llvm::SmallVector working_set_calls; - - const auto addToWork = [&visited_set, &working_set](auto vals) { - for (auto v : vals) { - if (visited_set.find(v) == visited_set.end()) { - working_set.push_back(v); - visited_set.insert(v); - } - } - }; - - const auto peek = [&working_set]() -> Value* { - auto user_iter = working_set.end() - 1; - working_set.erase(user_iter); - return *user_iter; - }; - - // Seed working set with users of value (e.g., our AllocaInst) - addToWork(in->users()); - - // Search through all users of users of .... (e.g., our AllocaInst) - while (!working_set.empty()) { - auto val = peek(); - - // If we encounter a callsite, we want to analyze later, or quit in case we have a regex match - CallSite c(val); - if (c.isCall() || c.isInvoke()) { - const auto callee = c.getCalledFunction(); - const bool indirect_call = callee == nullptr; - - if (indirect_call) { - LOG_DEBUG("Found an indirect call, not filtering alloca: " << util::dump(*val)); - return false; // Indirect calls might contain critical function calls. - } - - const bool is_decl = callee->isDeclaration(); - // FIXME the MPI calls are all hitting this branch (obviously) - if (is_decl) { - LOG_DEBUG("Found call with declaration only. Call: " << util::dump(*c.getInstruction())); - if (c.getIntrinsicID() == Intrinsic::not_intrinsic /*Intrinsic::ID::not_intrinsic*/) { - LOG_DEBUG("Not intrinsic " << ClCallFilterDeep); - if (ClCallFilterDeep && match(callee)) { - const bool can_cont = shouldContinue(c, in); - LOG_DEBUG("Matched, void* analysis " << can_cont); - if (can_cont) { - continue; - } - } - return false; - } else { - LOG_DEBUG("Call is an intrinsic. Continue analyzing...") - continue; - } - } - - if (match(callee)) { - LOG_DEBUG("Found a call. Call: " << util::dump(*c.getInstruction())); - if (ClCallFilterDeep && shouldContinue(c, in)) { - continue; - } - return false; - } - - working_set_calls.push_back(c); - // Caveat: below at the end of the loop, we add users of the function call to the search even though it might be - // a simple "sink" for the alloca we analyse - } else if (auto store = llvm::dyn_cast(val)) { - // If we encounter a store, we follow the store target pointer. - // More inclusive than strictly necessary in some cases. - LOG_DEBUG("Store found: " << util::dump(*store) - << " Store target has users: " << util::dump(store->getPointerOperand()->users())); - auto store_target = store->getPointerOperand(); - // FIXME here we check store operand, if target is another alloca, we already track that?: - // Note: if we apply this to malloc filtering, this might become problematic? - if (!malloc_mode && llvm::isa(store_target)) { - LOG_DEBUG("Target is alloca, skipping!"); - } else { - addToWork(store_target->users()); - } - continue; - } - // cont. our search - addToWork(val->users()); - } - ++depth; - return std::all_of(working_set_calls.begin(), working_set_calls.end(), [&](CallSite c) { return filter(c, in); }); -} - -bool StandardFilter::filter(CallSite& csite, Value* in) { - const auto analyse_arg = [&](auto& csite, auto argNum) -> bool { - Argument& the_arg = *(csite.getCalledFunction()->arg_begin() + argNum); - LOG_DEBUG("Calling filter with inst of argument: " << util::dump(the_arg)); - const bool filter_arg = filter(&the_arg); - LOG_DEBUG("Should filter? : " << filter_arg); - return filter_arg; - }; - - LOG_DEBUG("Analyzing function call " << csite.getCalledFunction()->getName()); - - if (csite.getCalledFunction() == start_f) { - return true; - } - - // this only works if we can correlate alloca with argument: - const auto pos = std::find_if(csite.arg_begin(), csite.arg_end(), - [&in](const Use& arg_use) -> bool { return arg_use.get() == in; }); - // auto pos = csite.arg_end(); - if (pos != csite.arg_end()) { - const auto argNum = std::distance(csite.arg_begin(), pos); - LOG_DEBUG("Found exact position: " << argNum); - return analyse_arg(csite, argNum); - } else { - LOG_DEBUG("Analyze all args, cannot correlate alloca with arg."); - return std::all_of(csite.arg_begin(), csite.arg_end(), [&csite, &analyse_arg](const Use& arg_use) { - auto argNum = csite.getArgumentNo(&arg_use); - return analyse_arg(csite, argNum); - }); - } - - return true; -} - -bool StandardFilter::filter(Argument* arg) { - for (auto* user : arg->users()) { - LOG_DEBUG("Looking at arg user " << util::dump(*user)); - // This code is for non mem2reg code (i.e., where the argument is stored to a local alloca): - if (auto store = llvm::dyn_cast(user)) { - // if (auto* alloca = llvm::dyn_cast(store->getPointerOperand())) { - // LOG_DEBUG("Argument is a store inst and the operand is alloca"); - return filter(store->getPointerOperand()); - // } - } - } - return filter(llvm::dyn_cast(arg)); -} - -bool StandardFilter::shouldContinue(CallSite c, Value* in) const { - LOG_DEBUG("Found a name match, analyzing closer..."); - const auto is_void_ptr = [](Type* type) { - return type->isPointerTy() && type->getPointerElementType()->isIntegerTy(8); - }; - const auto arg_pos = llvm::find_if(c.args(), [&in](const Use& arg_use) -> bool { return arg_use.get() == in; }); - if (arg_pos == c.arg_end()) { - // we had no direct correlation for the arg position - // Now checking if void* is passed, if not we can potentially filter! - auto count_void_ptr = llvm::count_if(c.args(), [&is_void_ptr](const auto& arg) { - const auto type = arg->getType(); - return is_void_ptr(type); - }); - if (count_void_ptr > 0) { - LOG_DEBUG("Call takes a void*, filtering."); - return false; - } - LOG_DEBUG("Call has no void* argument"); - } else { - // We have an arg_pos match - const auto argNum = std::distance(c.arg_begin(), arg_pos); - Argument& the_arg = *(c.getCalledFunction()->arg_begin() + argNum); - auto type = the_arg.getType(); - if (is_void_ptr(type)) { - LOG_DEBUG("Call arg is a void*, filtering."); - return false; - } - LOG_DEBUG("Value* in is not passed as void ptr"); - } - LOG_DEBUG("No filter necessary for this call, continue."); - return true; -} -std::string StandardFilter::getName(const Function* f) { - auto name = f->getName(); - // FIXME figure out if we need to demangle, i.e., source is .c or .cpp - const auto f_name = util::demangle(name); - if (f_name != "") { - name = f_name; - } - - return std::string{name}; -} -} // namespace typeart::filter::deprecated diff --git a/lib/passes/filter/StandardFilter.h b/lib/passes/filter/StandardFilter.h deleted file mode 100644 index 89e6b7d3..00000000 --- a/lib/passes/filter/StandardFilter.h +++ /dev/null @@ -1,67 +0,0 @@ -// TypeART library -// -// Copyright (c) 2017-2022 TypeART Authors -// Distributed under the BSD 3-Clause license. -// (See accompanying file LICENSE.txt or copy at -// https://opensource.org/licenses/BSD-3-Clause) -// -// Project home: https://github.com/tudasc/TypeART -// -// SPDX-License-Identifier: BSD-3-Clause -// - -#ifndef TYPEART_STANDARDFILTER_H -#define TYPEART_STANDARDFILTER_H - -#include "Filter.h" -#include "compat/CallSite.h" -#include "support/Logger.h" -#include "support/Util.h" - -#include "llvm/ADT/Statistic.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Format.h" - -#include - -namespace llvm { -class Argument; -class Function; -class Value; -} // namespace llvm - -namespace typeart::filter::deprecated { - -using namespace llvm; - -class StandardFilter final : public Filter { - const std::string call_regex; - bool malloc_mode{false}; - llvm::Function* start_f{nullptr}; - int depth{0}; - bool ClCallFilterDeep{true}; - - public: - explicit StandardFilter(const std::string& glob, bool CallFilterDeep); - - void setMode(bool search_malloc) override; - - void setStartingFunction(llvm::Function* start) override; - - bool filter(Value* in) override; - - private: - bool filter(CallSite& csite, Value* in); - - bool filter(Argument* arg); - - bool shouldContinue(CallSite c, Value* in) const; - - static inline std::string getName(const Function* f); -}; - -} // namespace typeart::filter::deprecated - -#endif // TYPEART_STANDARDFILTER_H diff --git a/lib/passes/instrumentation/MemOpInstrumentation.cpp b/lib/passes/instrumentation/MemOpInstrumentation.cpp index 61fbc09b..e83ffeed 100644 --- a/lib/passes/instrumentation/MemOpInstrumentation.cpp +++ b/lib/passes/instrumentation/MemOpInstrumentation.cpp @@ -30,6 +30,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Type.h" #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" @@ -45,8 +46,9 @@ using namespace llvm; namespace typeart { -MemOpInstrumentation::MemOpInstrumentation(TAFunctionQuery& fquery, InstrumentationHelper& instr) - : MemoryInstrument(), fquery(&fquery), instr_helper(&instr) { +MemOpInstrumentation::MemOpInstrumentation(TAFunctionQuery& fquery, InstrumentationHelper& instr, + bool lifetime_instrument) + : MemoryInstrument(), fquery(&fquery), instr_helper(&instr), instrument_lifetime(lifetime_instrument) { } InstrCount MemOpInstrumentation::instrumentHeap(const HeapArgList& heap) { @@ -166,32 +168,39 @@ InstrCount MemOpInstrumentation::instrumentStack(const StackArgList& stack) { using namespace transform; InstrCount counter{0}; StackCounter::StackOpCounter allocCounts; - Function* f{nullptr}; + Function* function{nullptr}; for (const auto& [sdata, args] : stack) { - // auto alloca = sdata.alloca; - auto* alloca = args.get_as(ArgMap::ID::pointer); + auto* alloca = args.get_as(ArgMap::ID::pointer); + auto* typeIdConst = args.get_value(ArgMap::ID::type_id); + auto* numElementsVal = args.get_value(ArgMap::ID::element_count); - IRBuilder<> IRB(alloca->getNextNode()); - - auto typeIdConst = args.get_value(ArgMap::ID::type_id); - auto numElementsVal = args.get_value(ArgMap::ID::element_count); - auto arrayPtr = IRB.CreateBitOrPointerCast(alloca, instr_helper->getTypeFor(IType::ptr)); - - auto parent_f = sdata.alloca->getFunction(); - const auto callback_id = util::omp::isOmpContext(parent_f) ? IFunc::stack_omp : IFunc::stack; + const auto instrument_stack = [&](IRBuilder<>& IRB, Value* data_ptr, Instruction* anchor) { + const auto callback_id = util::omp::isOmpContext(anchor->getFunction()) ? IFunc::stack_omp : IFunc::stack; + IRB.CreateCall(fquery->getFunctionFor(callback_id), ArrayRef{data_ptr, typeIdConst, numElementsVal}); + ++counter; - IRB.CreateCall(fquery->getFunctionFor(callback_id), ArrayRef{arrayPtr, typeIdConst, numElementsVal}); - ++counter; + auto* bblock = anchor->getParent(); + allocCounts[bblock]++; + if (function == nullptr) { + function = bblock->getParent(); + } + }; - auto bb = alloca->getParent(); - allocCounts[bb]++; - if (!f) { - f = bb->getParent(); + const auto& lifetime_starts = sdata.lifetime_start; + if (lifetime_starts.empty() || !instrument_lifetime) { + IRBuilder<> IRB(alloca->getNextNode()); + auto* data_ptr = IRB.CreateBitOrPointerCast(alloca, instr_helper->getTypeFor(IType::ptr)); + instrument_stack(IRB, data_ptr, alloca); + } else { + for (auto* lifetime_s : lifetime_starts) { + IRBuilder<> IRB(lifetime_s->getNextNode()); + instrument_stack(IRB, lifetime_s->getOperand(1), lifetime_s->getNextNode()); + } } } - if (f) { - StackCounter scount(f, instr_helper, fquery); + if (function != nullptr) { + StackCounter scount(function, instr_helper, fquery); scount.addStackHandling(allocCounts); } diff --git a/lib/passes/instrumentation/MemOpInstrumentation.h b/lib/passes/instrumentation/MemOpInstrumentation.h index ae8e0454..f986d16e 100644 --- a/lib/passes/instrumentation/MemOpInstrumentation.h +++ b/lib/passes/instrumentation/MemOpInstrumentation.h @@ -23,9 +23,10 @@ class InstrumentationHelper; class MemOpInstrumentation final : public MemoryInstrument { TAFunctionQuery* fquery; InstrumentationHelper* instr_helper; + bool instrument_lifetime{false}; public: - MemOpInstrumentation(TAFunctionQuery& fquery, InstrumentationHelper& instr); + MemOpInstrumentation(TAFunctionQuery& fquery, InstrumentationHelper& instr, bool lifetime_instrument = false); InstrCount instrumentHeap(const HeapArgList& heap) override; InstrCount instrumentFree(const FreeArgList& frees) override; InstrCount instrumentStack(const StackArgList& stack) override; diff --git a/lib/passes/instrumentation/TransformUtil.h b/lib/passes/instrumentation/TransformUtil.h index 04079f20..a5bb31bc 100644 --- a/lib/passes/instrumentation/TransformUtil.h +++ b/lib/passes/instrumentation/TransformUtil.h @@ -57,12 +57,16 @@ struct StackCounter { EscapeEnumerator ee(*f); while (IRBuilder<>* irb = ee.Next()) { - auto* I = &(*irb->GetInsertPoint()); - + auto* I = &(*irb->GetInsertPoint()); auto* counter_load = irb->CreateLoad(instr_helper->getTypeFor(IType::stack_count), counter, "__ta_counter_load"); - auto* cond = irb->CreateICmpNE(counter_load, instr_helper->getConstantFor(IType::stack_count), "__ta_cond"); - auto* then_term = SplitBlockAndInsertIfThen(cond, I, false); - irb->SetInsertPoint(then_term); + + const auto all_preds_have_counter = llvm::all_of( + llvm::predecessors(I->getParent()), [&allocCounts](const auto* bb) { return allocCounts.count(bb) > 0; }); + if (all_preds_have_counter) { + auto* cond = irb->CreateICmpNE(counter_load, instr_helper->getConstantFor(IType::stack_count), "__ta_cond"); + auto* then_term = SplitBlockAndInsertIfThen(cond, I, false); + irb->SetInsertPoint(then_term); + } irb->CreateCall(fquery->getFunctionFor(callback_id), ArrayRef{counter_load}); } diff --git a/lib/passes/instrumentation/TypeARTFunctions.cpp b/lib/passes/instrumentation/TypeARTFunctions.cpp index ba71fff3..ba62e1a8 100644 --- a/lib/passes/instrumentation/TypeARTFunctions.cpp +++ b/lib/passes/instrumentation/TypeARTFunctions.cpp @@ -65,32 +65,40 @@ llvm::Function* TAFunctionDeclarator::make_function(IFunc id, llvm::StringRef ba } auto& c = m.getContext(); - const auto addOptimizerAttributes = [&](llvm::Function* f) { - for (Argument& arg : f->args()) { + const auto addOptimizerAttributes = [&](llvm::Function* function) { + function->setDoesNotThrow(); + function->setDoesNotFreeMemory(); + function->setDoesNotRecurse(); +#if LLVM_VERSION_MAJOR >= 12 + function->setWillReturn(); +#endif + for (Argument& arg : function->args()) { if (arg.getType()->isPointerTy()) { arg.addAttr(Attribute::NoCapture); arg.addAttr(Attribute::ReadOnly); + arg.addAttr(Attribute::NoFree); } } }; - const auto setFunctionLinkageExternal = [](llvm::Function* f) { - f->setLinkage(GlobalValue::ExternalLinkage); + const auto setFunctionLinkageExternal = [](llvm::Function* function) { + function->setLinkage(GlobalValue::ExternalLinkage); // f->setLinkage(GlobalValue::ExternalWeakLinkage); }; const auto do_make = [&](auto& name, auto f_type) { - const bool has_f = m.getFunction(name) != nullptr; - auto fc = m.getOrInsertFunction(name, f_type); + const bool has_func_declared = m.getFunction(name) != nullptr; + auto func_in_module = m.getOrInsertFunction(name, f_type); - Function* f{nullptr}; - if (has_f) { + Function* function{nullptr}; + if (has_func_declared) { LOG_WARNING("Function " << name << " is already declared in the module.") - f = dyn_cast(fc.getCallee()->stripPointerCasts()); + function = dyn_cast(func_in_module.getCallee()->stripPointerCasts()); } else { - f = dyn_cast(fc.getCallee()); - setFunctionLinkageExternal(f); + function = dyn_cast(func_in_module.getCallee()); + setFunctionLinkageExternal(function); } - addOptimizerAttributes(f); - return f; + + addOptimizerAttributes(function); + return function; }; auto f = do_make(name, FunctionType::get(Type::getVoidTy(c), args, false)); diff --git a/lib/passes/instrumentation/TypeARTFunctions.h b/lib/passes/instrumentation/TypeARTFunctions.h index 9942608f..a816b6b0 100644 --- a/lib/passes/instrumentation/TypeARTFunctions.h +++ b/lib/passes/instrumentation/TypeARTFunctions.h @@ -68,7 +68,7 @@ class TAFunctionDeclarator { public: TAFunctionDeclarator(llvm::Module& m, InstrumentationHelper& instr, TAFunctions& tafunc); - llvm::Function* make_function(IFunc id, llvm::StringRef basename, llvm::ArrayRef args, + llvm::Function* make_function(IFunc function, llvm::StringRef basename, llvm::ArrayRef args, bool with_omp = false, bool fixed_name = true); const llvm::StringMap& getFunctionMap() const; virtual ~TAFunctionDeclarator() = default; diff --git a/lib/passes/support/DefUseChain.h b/lib/passes/support/DefUseChain.h index 2e4f63c1..93fb89b4 100644 --- a/lib/passes/support/DefUseChain.h +++ b/lib/passes/support/DefUseChain.h @@ -16,6 +16,7 @@ #include "support/Logger.h" #include "support/Util.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Instructions.h" #include diff --git a/lib/passes/typegen/CMakeLists.txt b/lib/passes/typegen/CMakeLists.txt index 365b91ac..0617434f 100644 --- a/lib/passes/typegen/CMakeLists.txt +++ b/lib/passes/typegen/CMakeLists.txt @@ -11,12 +11,12 @@ set(TYPEGEN_SOURCES add_library(${TYPEART_PREFIX}_TypeGenObj OBJECT ${TYPEGEN_SOURCES}) -target_compile_definitions(${TYPEART_PREFIX}_TypeGenObj PRIVATE LOG_LEVEL=${LOG_LEVEL}) +target_compile_definitions(${TYPEART_PREFIX}_TypeGenObj PRIVATE TYPEART_LOG_LEVEL=${TYPEART_LOG_LEVEL}) set_target_properties(${TYPEART_PREFIX}_TypeGenObj PROPERTIES POSITION_INDEPENDENT_CODE ON) target_include_directories( - ${TYPEART_PREFIX}_TypeGenObj + ${TYPEART_PREFIX}_TypeGenObj ${warning_guard} PUBLIC $ $ $ @@ -27,9 +27,9 @@ target_include_directories(${TYPEART_PREFIX}_TypeGenObj SYSTEM PRIVATE ${LLVM_IN make_tidy_check(${TYPEART_PREFIX}_TypeGenObj "${TypeGen_SOURCES}") -target_project_compile_options(${TYPEART_PREFIX}_TypeGenObj) -target_define_file_basename(${TYPEART_PREFIX}_TypeGenObj) -target_project_coverage_options(${TYPEART_PREFIX}_TypeGenObj) +typeart_target_compile_options(${TYPEART_PREFIX}_TypeGenObj) +typeart_target_define_file_basename(${TYPEART_PREFIX}_TypeGenObj) +typeart_target_coverage_options(${TYPEART_PREFIX}_TypeGenObj) # Need to link LLVMCore to work for consumer add_library(${TYPEART_PREFIX}_TypeGenStatic STATIC $) @@ -42,13 +42,13 @@ set_target_properties( EXPORT_NAME "TypeGenStatic" ) -target_project_coverage_options(${TYPEART_PREFIX}_TypeGenStatic) +typeart_target_coverage_options(${TYPEART_PREFIX}_TypeGenStatic) target_link_libraries(${TYPEART_PREFIX}_TypeGenStatic typeart::TypesStatic) target_include_directories( - ${TYPEART_PREFIX}_TypeGenStatic - PUBLIC $ + ${TYPEART_PREFIX}_TypeGenStatic ${warning_guard} + PUBLIC $ $ $ $ diff --git a/lib/passes/typegen/StructTypeHandler.h b/lib/passes/typegen/StructTypeHandler.h index ec3eb4d1..31d46186 100644 --- a/lib/passes/typegen/StructTypeHandler.h +++ b/lib/passes/typegen/StructTypeHandler.h @@ -14,6 +14,7 @@ #define TYPEART_STRUCTTYPEHANDLER_H #include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include diff --git a/lib/passes/typegen/VectorTypeHandler.h b/lib/passes/typegen/VectorTypeHandler.h index c8a637ea..71459491 100644 --- a/lib/passes/typegen/VectorTypeHandler.h +++ b/lib/passes/typegen/VectorTypeHandler.h @@ -14,6 +14,7 @@ #define TYPEART_VECTORTYPEHANDLER_H #include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include diff --git a/lib/runtime/AccessCountPrinter.h b/lib/runtime/AccessCountPrinter.h index 12c5f947..cfcd426e 100644 --- a/lib/runtime/AccessCountPrinter.h +++ b/lib/runtime/AccessCountPrinter.h @@ -50,7 +50,7 @@ inline MemOverhead estimate(Counter stack_max, Counter heap_max, Counter global_ } // namespace memory template -void serialise(const Recorder& r, std::ostringstream& buf) { +void serialize(const Recorder& r, std::ostringstream& buf) { if constexpr (std::is_same_v) { return; } else { diff --git a/lib/runtime/AllocMapWrapper.h b/lib/runtime/AllocMapWrapper.h index bc867b6c..35dd5f62 100644 --- a/lib/runtime/AllocMapWrapper.h +++ b/lib/runtime/AllocMapWrapper.h @@ -193,7 +193,7 @@ struct SafePtrdMap : protected BaseOp { #ifdef USE_SAFEPTR using PointerMap = mixin::SafePtrdMap; #else -#ifdef DISABLE_THREAD_SAFETY +#ifdef TYPEART_DISABLE_THREAD_SAFETY using PointerMap = mixin::StandardMapBase; #else using PointerMap = mixin::SharedMutexMap>; diff --git a/lib/runtime/AllocationTracking.cpp b/lib/runtime/AllocationTracking.cpp index 76ba4420..0d3255d3 100644 --- a/lib/runtime/AllocationTracking.cpp +++ b/lib/runtime/AllocationTracking.cpp @@ -28,16 +28,16 @@ #include #include -#ifdef USE_BTREE +#ifdef TYPEART_BTREE using namespace btree; #endif -#define likely(x) __builtin_expect(!!(x), 1) +#define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #define CONCAT_(x, y) x##y -#define CONCAT(x, y) CONCAT_(x, y) -#define GUARDNAME CONCAT(typeart_guard_, __LINE__) +#define CONCAT(x, y) CONCAT_(x, y) +#define GUARDNAME CONCAT(typeart_guard_, __LINE__) #define TYPEART_RUNTIME_GUARD \ typeart::RTGuard GUARDNAME; \ diff --git a/lib/runtime/CMakeLists.txt b/lib/runtime/CMakeLists.txt index cf23810a..0e030c5f 100644 --- a/lib/runtime/CMakeLists.txt +++ b/lib/runtime/CMakeLists.txt @@ -27,7 +27,7 @@ set(RUNTIME_LIB_SOURCES Runtime.cpp Runtime.h ${TYPEART_META_SOURCE} - $<$:../support/MPILogger.cpp> + $<$:../support/MPILogger.cpp> ) add_library(${TYPEART_PREFIX}_Runtime SHARED ${RUNTIME_LIB_SOURCES}) @@ -45,16 +45,16 @@ target_link_libraries( typeart::SystemStatic LLVMCore LLVMSupport - $<$:MPI::MPI_CXX> - $<$:google::btree> - $<$:absl::btree> - $<$:sf::pointer> - $<$>:Threads::Threads> + $<$:MPI::MPI_CXX> + $<$:phpmap::phpmap> + $<$:absl::btree> + $<$:sf::pointer> + $<$>:Threads::Threads> ) target_include_directories( - ${TYPEART_PREFIX}_Runtime - PUBLIC $ + ${TYPEART_PREFIX}_Runtime ${warning_guard} + PUBLIC $ $ $ PRIVATE $ @@ -65,29 +65,29 @@ target_include_directories(${TYPEART_PREFIX}_Runtime SYSTEM PRIVATE ${LLVM_INCLU target_compile_definitions( ${TYPEART_PREFIX}_Runtime - PRIVATE LOG_LEVEL=${LOG_LEVEL_RT} - $<$:MPI_LOGGER=1> - $<$:ENABLE_SOFTCOUNTER=1> - $<$:USE_BTREE> - $<$:USE_ABSL> - $<$:USE_SAFEPTR> - $<$:DISABLE_THREAD_SAFETY> + PRIVATE TYPEART_LOG_LEVEL=${TYPEART_LOG_LEVEL_RT} + $<$:TYPEART_MPI_LOGGER=1> + $<$:ENABLE_SOFTCOUNTER=1> + $<$:TYPEART_PHMAP> + $<$:TYPEART_ABSEIL> + $<$:USE_SAFEPTR> + $<$:TYPEART_DISABLE_THREAD_SAFETY> ) -target_project_compile_options(${TYPEART_PREFIX}_Runtime) -target_define_file_basename(${TYPEART_PREFIX}_Runtime) -target_project_coverage_options(${TYPEART_PREFIX}_Runtime) +typeart_target_compile_options(${TYPEART_PREFIX}_Runtime) +typeart_target_define_file_basename(${TYPEART_PREFIX}_Runtime) +typeart_target_coverage_options(${TYPEART_PREFIX}_Runtime) -if(ENABLE_TSAN) - target_tsan_options(${TYPEART_PREFIX}_Runtime) +if(TYPEART_TSAN) + typeart_target_tsan_options(${TYPEART_PREFIX}_Runtime) endif() -if(ENABLE_ASAN) - target_asan_options(${TYPEART_PREFIX}_Runtime) +if(TYPEART_ASAN) + typeart_target_asan_options(${TYPEART_PREFIX}_Runtime) endif() -if(ENABLE_UBSAN) - target_ubsan_options(${TYPEART_PREFIX}_Runtime) +if(TYPEART_UBSAN) + typeart_target_ubsan_options(${TYPEART_PREFIX}_Runtime) endif() make_tidy_check(${TYPEART_PREFIX}_Runtime "${RUNTIME_LIB_SOURCES}") diff --git a/lib/runtime/Runtime.cpp b/lib/runtime/Runtime.cpp index d912730a..5b3df2fa 100644 --- a/lib/runtime/Runtime.cpp +++ b/lib/runtime/Runtime.cpp @@ -113,7 +113,7 @@ RuntimeSystem::~RuntimeSystem() { // llvm::raw_string_ostream stream(stats); std::ostringstream stream; - softcounter::serialise(recorder, stream); + softcounter::serialize(recorder, stream); if (!stream.str().empty()) { // llvm::errs/LOG will crash with virtual call error std::cerr << stream.str(); diff --git a/lib/runtime/RuntimeData.h b/lib/runtime/RuntimeData.h index 16c063c6..692bc01d 100644 --- a/lib/runtime/RuntimeData.h +++ b/lib/runtime/RuntimeData.h @@ -13,16 +13,13 @@ #ifndef TYPEART_RUNTIMEDATA_H #define TYPEART_RUNTIMEDATA_H -#ifdef USE_BTREE -#ifdef USE_ABSL -#error TypeART-RT: Set BTREE and ABSL, mutually exclusive. -#endif -#include "btree_map.h" +#ifdef TYPEART_BTREE +#error TypeART-RT: TYPART_BTREE is deprecated. #endif -#ifdef USE_ABSL -#ifdef USE_BTREE -#error TypeART-RT: Set ABSL and BTREE, mutually exclusive. +#ifdef TYPEART_ABSEIL +#ifdef TYPEART_PHMAP +#error TypeART-RT: Set ABSL and PHMAP, mutually exclusive. #endif #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" @@ -30,12 +27,19 @@ #pragma GCC diagnostic pop #endif -#if !defined(USE_BTREE) && !defined(USE_ABSL) +#ifdef TYPEART_PHMAP +#ifdef TYPEART_ABSEIL +#error TypeART-RT: Set ABSL and PHMAP, mutually exclusive. +#endif +#include "parallel_hashmap/btree.h" +#endif + +#if !defined(TYPEART_PHMAP) && !defined(TYPEART_ABSEIL) #include #endif #ifdef USE_SAFEPTR -#ifdef DISABLE_THREAD_SAFETY +#ifdef TYPEART_DISABLE_THREAD_SAFETY #error TypeART-RT: Safe_ptr and disabled thread safety illegal #endif #include "safe_ptr.h" @@ -58,15 +62,15 @@ struct RuntimeT { using Stack = std::vector; static constexpr auto StackReserve{512U}; static constexpr char StackName[] = "std::vector"; -#ifdef USE_BTREE - using PointerMapBaseT = btree::btree_map; - static constexpr char MapName[] = "btree::btree_map"; +#ifdef TYPEART_PHMAP + using PointerMapBaseT = phmap::btree_map; + static constexpr char MapName[] = "phmap::btree_map"; #endif -#ifdef USE_ABSL +#ifdef TYPEART_ABSEIL using PointerMapBaseT = absl::btree_map; static constexpr char MapName[] = "absl::btree_map"; #endif -#if !defined(USE_BTREE) && !defined(USE_ABSL) +#if !defined(TYPEART_PHMAP) && !defined(TYPEART_ABSEIL) using PointerMapBaseT = std::map; static constexpr char MapName[] = "std::map"; #endif diff --git a/lib/runtime/RuntimeInterface.h b/lib/runtime/RuntimeInterface.h index efa0852d..35bef7c5 100644 --- a/lib/runtime/RuntimeInterface.h +++ b/lib/runtime/RuntimeInterface.h @@ -56,6 +56,17 @@ typedef struct typeart_struct_layout_t { // NOLINT * Given a pointer to the start of a struct, the returned type will therefore be that of the struct, not of the first * member. * + * Code example: + * { + * struct DataStruct { int a; double b; float c[2]; }; // sizeof(DataStruct) == 24 byte + * DataStruct data[5]; + * We pass the address of the first element of the float array inside the struct: + * typeart_get_type(&data[1].c[0], &type_id, &count); + * returns: + * -> type_id: 5 (i.e., TYPEART_FLOAT) + * -> count: 2 (c[0] to end(c)) + * } + * * \param[in] addr The address. * \param[out] type_id Type ID * \param[out] count Allocation size @@ -78,38 +89,89 @@ typeart_status typeart_get_type_id(const void* addr, int* type_id); * Instead, additional information about the position of the address within the containing type is returned. * * The starting address of the referenced array element can be deduced by computing `(size_t) addr - offset`. + * Note: The addr may point to an illegal memory location inside the containing type. This is not automatically + * resolved, see code example below. + * + * Code example: + * { + * Struct with implicit padding for correct alignment: + * struct DataStruct { int a; {4xbyte pad}; double b; float c[2]; }; // sizeof(DataStruct) == 24 byte + * DataStruct data[5]; + * We pass the address of the first element of the float array inside the struct (containing type): + * typeart_get_containing_type(&data[1].c[0], &type_id, &count, base_address, &byte_offset); + * returns: + * -> type_id: 257 (or higher for struct types) + * -> count: 4 (including data[1] to data[4]) + * -> base_addr: &data[0] + * -> byte_offset: 16 (counted from the containing type &data[1].c[0] to &data[1]) + * Hence: + * ((addr - offset) - base_addr) == number of bytes to start of allocation "data" from data[1] + * + * Example 2, illegal memory address is not explicitly caught by return state: + * typeart_get_containing_type(&data[0].a + sizeof(int), ...); + * returns: + * -> type_id: 257 (or higher for struct types) + * -> count: 5 (including data[0] to data[4]) + * -> base_addr: &data[0] + * -> byte_offset: 4 (points to padding, counted from the containing type (&data[0].a + sizeof(int)) + * to &data[0]) + * } * * \param[in] addr The address. + * \param[out] type_id Type ID of the containing type * \param[out] count Number of elements in the containing buffer, not counting elements before the given address. * \param[out] base_address Address of the containing buffer. - * \param[out] offset The byte offset within that buffer element. - * - * \return A status code. For an explanation of errors, refer to typeart_get_type(). + * \param[out] byte_offset The byte offset within that buffer element. * + * \return A status code. + * - TYPEART_OK: The query was successful. + * - TYPEART_UNKNOWN_ADDRESS: The given address is either not allocated, or was not correctly recorded by the runtime. */ typeart_status typeart_get_containing_type(const void* addr, int* type_id, size_t* count, const void** base_address, - size_t* offset); + size_t* byte_offset); /** * Determines the subtype at the given offset w.r.t. a base address and a corresponding containing type. * Note that if the subtype is itself a struct, you may have to call this function again. * If it returns with *subTypeOffset == 0, the address has been fully resolved. * + * Code example: + * { + * struct DataStruct { int a; double b; float c[2]; }; // sizeof(DataStruct) == 24 byte + * DataStruct data[5]; + * typeart_struct_layout layout_data; + * Determine layout of data: + * { + * int type_id; + * typeart_get_type_id(&data[0], &type_id); + * typeart_resolve_type_id(type_id, &layout_data); + * } + * We pass the address of the first element of the data array: + * status = typeart_get_subtype(&data[1], 20, &layout_data, &subtype_id, &subtype_base_addr, &subtype_byte_offset, + * &subtype_count); + * returns: + * -> subtype_id: 5 (TYPEART_FLOAT) + * -> subtype_base_addr: &data[1].c[0] + * -> subtype_byte_offset: 0 + * -> subtype_count: 1 (length of member float[2] at offset 20) + * } + * * \param[in] baseAddr Pointer to the start of the containing type. * \param[in] offset Byte offset within the containing type. * \param[in] container_layout typeart_struct_layout corresponding to the containing type * \param[out] subtype_id The type ID corresponding to the subtype. * \param[out] subtype_base_addr Pointer to the start of the subtype. - * \param[out] subtype_offset Byte offset within the subtype. + * \param[out] subtype_byte_offset Byte offset within the subtype. * \param[out] subtype_count Number of elements in subarray. * * \return One of the following status codes: * - TYPEART_OK: Success. * - TYPEART_BAD_ALIGNMENT: Address corresponds to location inside an atomic type or padding. * - TYPEART_BAD_OFFSET: The provided offset is invalid. + * - TYPEART_ERROR: The typeart_struct_layout is invalid. */ -typeart_status typeart_get_subtype(const void* base_addr, size_t offset, typeart_struct_layout container_layout, - int* subtype_id, const void** subtype_base_addr, size_t* subtype_offset, +typeart_status typeart_get_subtype(const void* base_addr, size_t offset, const typeart_struct_layout* container_layout, + int* subtype_id, const void** subtype_base_addr, size_t* subtype_byte_offset, size_t* subtype_count); /** diff --git a/lib/runtime/TypeResolution.cpp b/lib/runtime/TypeResolution.cpp index 1870eca6..b9745431 100644 --- a/lib/runtime/TypeResolution.cpp +++ b/lib/runtime/TypeResolution.cpp @@ -30,47 +30,67 @@ namespace typeart { -template -inline const void* addByteOffset(const void* addr, T offset) { - return static_cast(static_cast(addr) + offset); +namespace detail { + +template +inline const void* add_byte_offset(const P* addr, T offset) { + assert(addr != nullptr); + return static_cast(static_cast(addr) + offset); } -TypeResolution::TypeResolution(const TypeDB& db, Recorder& recorder) : typeDB{db}, recorder{recorder} { +template +inline std::ptrdiff_t substract_pointer(const T* addr_a, const T* addr_b) { + assert(addr_a != nullptr); + assert(addr_b != nullptr); + return static_cast(addr_a) - static_cast(addr_b); } -size_t TypeResolution::getMemberIndex(typeart_struct_layout structInfo, size_t offset) const { - size_t n = structInfo.num_members; - if (offset > structInfo.offsets[n - 1]) { - return n - 1; +inline size_t get_member_index_at(const typeart_struct_layout& structInfo, size_t offset) { + const size_t num_members = structInfo.num_members; + + if (num_members == 0) { + return 0; } - size_t i = 0; - while (i < n - 1 && offset >= structInfo.offsets[i + 1]) { - ++i; + const auto* struct_offsets = structInfo.offsets; + + if (offset > struct_offsets[num_members - 1]) { + return num_members - 1; + } + + size_t member_index{0}; + while (member_index < (num_members - 1) && offset >= struct_offsets[member_index + 1]) { + ++member_index; } - return i; + return member_index; +} + +} // namespace detail + +TypeResolution::TypeResolution(const TypeDB& type_db, Recorder& recorder) : typeDB{type_db}, recorder{recorder} { } TypeResolution::TypeArtStatus TypeResolution::getSubTypeInfo(const void* baseAddr, size_t offset, - typeart_struct_layout containerInfo, int* subType, + const typeart_struct_layout& containerInfo, int* subType, const void** subTypeBaseAddr, size_t* subTypeOffset, size_t* subTypeCount) const { + if (containerInfo.type_id < 0) { + return TYPEART_ERROR; + } + if (offset >= containerInfo.extent) { return TYPEART_BAD_OFFSET; } // Get index of the struct member at the address - size_t memberIndex = getMemberIndex(containerInfo, offset); - - int memberType = containerInfo.member_types[memberIndex]; + const size_t memberIndex = detail::get_member_index_at(containerInfo, offset); + const int memberType = containerInfo.member_types[memberIndex]; + const size_t baseOffset = containerInfo.offsets[memberIndex]; - size_t baseOffset = containerInfo.offsets[memberIndex]; - assert(offset >= baseOffset && "Invalid offset values"); - - size_t internalOffset = offset - baseOffset; - size_t typeSize = typeDB.getTypeSize(memberType); - size_t offsetInTypeSize = internalOffset / typeSize; - size_t newOffset = internalOffset % typeSize; + const size_t internalOffset = offset - baseOffset; + const size_t typeSize = typeDB.getTypeSize(memberType); + const size_t offsetInTypeSize = internalOffset / typeSize; + const size_t newOffset = internalOffset % typeSize; // If newOffset != 0, the subtype cannot be atomic, i.e. must be a struct if (newOffset != 0) { @@ -86,48 +106,45 @@ TypeResolution::TypeArtStatus TypeResolution::getSubTypeInfo(const void* baseAdd } *subType = memberType; - *subTypeBaseAddr = addByteOffset(baseAddr, baseOffset); + *subTypeBaseAddr = detail::add_byte_offset(baseAddr, baseOffset); *subTypeOffset = newOffset; *subTypeCount = containerInfo.count[memberIndex] - offsetInTypeSize; return TYPEART_OK; } -TypeResolution::TypeArtStatus TypeResolution::getSubTypeInfo(const void* baseAddr, size_t offset, - const StructTypeInfo& containerInfo, int* subType, - const void** subTypeBaseAddr, size_t* subTypeOffset, - size_t* subTypeCount) const { - typeart_struct_layout structLayout; - structLayout.type_id = containerInfo.type_id; - structLayout.name = containerInfo.name.c_str(); - structLayout.num_members = containerInfo.num_members; - structLayout.extent = containerInfo.extent; - structLayout.offsets = &containerInfo.offsets[0]; - structLayout.member_types = &containerInfo.member_types[0]; - structLayout.count = &containerInfo.array_sizes[0]; - return getSubTypeInfo(baseAddr, offset, structLayout, subType, subTypeBaseAddr, subTypeOffset, subTypeCount); -} - TypeResolution::TypeArtStatus TypeResolution::getTypeInfoInternal(const void* baseAddr, size_t offset, const StructTypeInfo& containerInfo, int* type, size_t* count) const { assert(offset < containerInfo.extent && "Something went wrong with the base address computation"); - TypeArtStatus status; int subType{-1}; const void* subTypeBaseAddr; size_t subTypeOffset{0}; size_t subTypeCount{0}; + const StructTypeInfo* structInfo = &containerInfo; - bool resolve{true}; + const auto to_struct_layout_info = [](const auto& struct_type_info) { + typeart_struct_layout struct_layout; + struct_layout.type_id = struct_type_info.type_id; + struct_layout.name = struct_type_info.name.c_str(); + struct_layout.num_members = struct_type_info.num_members; + struct_layout.extent = struct_type_info.extent; + struct_layout.offsets = &struct_type_info.offsets[0]; + struct_layout.member_types = &struct_type_info.member_types[0]; + struct_layout.count = &struct_type_info.array_sizes[0]; + return struct_layout; + }; // Resolve type recursively, until the address matches exactly + bool resolve{true}; while (resolve) { - status = getSubTypeInfo(baseAddr, offset, *structInfo, &subType, &subTypeBaseAddr, &subTypeOffset, &subTypeCount); + const auto status_subtype_info = getSubTypeInfo(baseAddr, offset, to_struct_layout_info(*structInfo), &subType, + &subTypeBaseAddr, &subTypeOffset, &subTypeCount); - if (status != TYPEART_OK) { - return status; + if (status_subtype_info != TYPEART_OK) { + return status_subtype_info; } baseAddr = subTypeBaseAddr; @@ -138,9 +155,9 @@ TypeResolution::TypeArtStatus TypeResolution::getTypeInfoInternal(const void* ba // Get layout of the nested struct if (resolve) { - status = getStructInfo(subType, &structInfo); - if (status != TYPEART_OK) { - return status; + const auto status_struct_info = getStructInfo(subType, &structInfo); + if (status_struct_info != TYPEART_OK) { + return status_struct_info; } } } @@ -151,12 +168,12 @@ TypeResolution::TypeArtStatus TypeResolution::getTypeInfoInternal(const void* ba TypeResolution::TypeArtStatus TypeResolution::getTypeInfo(const void* addr, const void* basePtr, const PointerInfo& ptrInfo, int* type, size_t* count) const { - int containingType = ptrInfo.typeId; - size_t containingTypeCount{0}; - size_t internalOffset{0}; + const int containing_type = ptrInfo.typeId; + size_t containing_type_count{0}; + size_t internal_byte_offset{0}; // First, retrieve the containing type - TypeArtStatus status = getContainingTypeInfo(addr, basePtr, ptrInfo, &containingTypeCount, &internalOffset); + TypeArtStatus status = getContainingTypeInfo(addr, basePtr, ptrInfo, &containing_type_count, &internal_byte_offset); if (status != TYPEART_OK) { if (status == TYPEART_UNKNOWN_ADDRESS) { recorder.incAddrMissing(addr); @@ -165,23 +182,24 @@ TypeResolution::TypeArtStatus TypeResolution::getTypeInfo(const void* addr, cons } // Check for exact address match - if (internalOffset == 0) { - *type = containingType; - *count = containingTypeCount; + if (internal_byte_offset == 0) { + *type = containing_type; + *count = containing_type_count; return TYPEART_OK; } - if (typeDB.isBuiltinType(containingType)) { + if (typeDB.isBuiltinType(containing_type)) { // Address points to the middle of a builtin type return TYPEART_BAD_ALIGNMENT; } // Resolve struct recursively - const auto* structInfo = typeDB.getStructInfo(containingType); + const auto* structInfo = typeDB.getStructInfo(containing_type); if (structInfo != nullptr) { - const void* containingTypeAddr = addByteOffset(addr, -std::ptrdiff_t(internalOffset)); - return getTypeInfoInternal(containingTypeAddr, internalOffset, *structInfo, type, count); + const void* containingTypeAddr = detail::add_byte_offset(addr, -std::ptrdiff_t(internal_byte_offset)); + return getTypeInfoInternal(containingTypeAddr, internal_byte_offset, *structInfo, type, count); } + return TYPEART_INVALID_ID; } @@ -199,26 +217,29 @@ TypeResolution::TypeArtStatus TypeResolution::getContainingTypeInfo(const void* } // The address points inside a known array - const void* blockEnd = addByteOffset(basePtr, basePtrInfo.count * typeSize); + const void* blockEnd = detail::add_byte_offset(basePtr, basePtrInfo.count * typeSize); // Ensure that the given address is in bounds and points to the start of an element if (addr >= blockEnd) { - const std::ptrdiff_t offset2base = static_cast(addr) - static_cast(basePtr); - const auto oob_index = (offset2base / typeSize) - basePtrInfo.count + 1; + const std::ptrdiff_t byte_offset_to_base = detail::substract_pointer(addr, basePtr); + + const auto elements = byte_offset_to_base / typeSize; + const auto oob_index = elements - basePtrInfo.count + 1; LOG_WARNING("Out of bounds for the lookup: (" << debug::toString(addr, basePtrInfo) << ") #Elements too far: " << oob_index); return TYPEART_UNKNOWN_ADDRESS; } assert(addr >= basePtr && "Error in base address computation"); - size_t addrDif = reinterpret_cast(addr) - reinterpret_cast(basePtr); + + const std::ptrdiff_t addrDif = detail::substract_pointer(addr, basePtr); // Offset of the pointer w.r.t. the start of the containing type - size_t internalOffset = addrDif % typeSize; + const size_t internalOffset = addrDif % typeSize; // Array index - size_t typeOffset = addrDif / typeSize; - size_t typeCount = basePtrInfo.count - typeOffset; + const size_t typeOffset = addrDif / typeSize; + const size_t typeCount = basePtrInfo.count - typeOffset; // Retrieve and return type information *count = typeCount; @@ -226,22 +247,13 @@ TypeResolution::TypeArtStatus TypeResolution::getContainingTypeInfo(const void* return TYPEART_OK; } -TypeResolution::TypeArtStatus TypeResolution::getBuiltinInfo(const void* addr, const PointerInfo& ptrInfo, - BuiltinType* type) const { - if (typeDB.isReservedType(ptrInfo.typeId)) { - *type = static_cast(ptrInfo.typeId); - return TYPEART_OK; - } - return TYPEART_WRONG_KIND; -} - -TypeResolution::TypeArtStatus TypeResolution::getStructInfo(int id, const StructTypeInfo** structInfo) const { +TypeResolution::TypeArtStatus TypeResolution::getStructInfo(int type_id, const StructTypeInfo** structInfo) const { // Requested ID must correspond to a struct - if (!typeDB.isStructType(id)) { + if (!typeDB.isStructType(type_id)) { return TYPEART_WRONG_KIND; } - const auto* result = typeDB.getStructInfo(id); + const auto* result = typeDB.getStructInfo(type_id); if (result != nullptr) { *structInfo = result; @@ -264,9 +276,9 @@ inline typeart_status query_type(const void* addr, int* type, size_t* count) { return TYPEART_UNKNOWN_ADDRESS; } -inline typeart_status query_struct_layout(int id, typeart_struct_layout* struct_layout) { +inline typeart_status query_struct_layout(int type_id, typeart_struct_layout* struct_layout) { const typeart::StructTypeInfo* struct_info; - typeart_status status = typeart::RuntimeSystem::get().typeResolution.getStructInfo(id, &struct_info); + typeart_status status = typeart::RuntimeSystem::get().typeResolution.getStructInfo(type_id, &struct_info); if (status == TYPEART_OK) { struct_layout->type_id = struct_info->type_id; struct_layout->name = struct_info->name.c_str(); @@ -275,6 +287,14 @@ inline typeart_status query_struct_layout(int id, typeart_struct_layout* struct_ struct_layout->offsets = &struct_info->offsets[0]; struct_layout->member_types = &struct_info->member_types[0]; struct_layout->count = &struct_info->array_sizes[0]; + } else { + struct_layout->type_id = std::numeric_limits::min(); + struct_layout->name = ""; + struct_layout->num_members = 0; + struct_layout->extent = 0; + struct_layout->offsets = nullptr; + struct_layout->member_types = nullptr; + struct_layout->count = nullptr; } return status; } @@ -293,7 +313,7 @@ char* string2char(std::string_view src) { memcpy(string_copy, src.data(), source_length); return string_copy; -}; +} } // namespace detail } // namespace typeart @@ -303,18 +323,9 @@ char* string2char(std::string_view src) { * */ -typeart_status typeart_get_builtin_type(const void* addr, typeart::BuiltinType* type) { - typeart::RTGuard guard; - auto alloc = typeart::RuntimeSystem::get().allocTracker.findBaseAlloc(addr); - if (alloc) { - return typeart::RuntimeSystem::get().typeResolution.getBuiltinInfo(addr, alloc->second, type); - } - return TYPEART_UNKNOWN_ADDRESS; -} - -typeart_status typeart_get_type(const void* addr, int* type, size_t* count) { +typeart_status typeart_get_type(const void* addr, int* type_id, size_t* count) { typeart::RTGuard guard; - return typeart::detail::query_type(addr, type, count); + return typeart::detail::query_type(addr, type_id, count); } typeart_status typeart_get_type_length(const void* addr, size_t* count) { @@ -329,26 +340,27 @@ typeart_status typeart_get_type_id(const void* addr, int* type_id) { return typeart::detail::query_type(addr, type_id, &count); } -typeart_status typeart_get_containing_type(const void* addr, int* type, size_t* count, const void** base_address, - size_t* offset) { +typeart_status typeart_get_containing_type(const void* addr, int* type_id, size_t* count, const void** base_address, + size_t* byte_offset) { typeart::RTGuard guard; auto alloc = typeart::RuntimeSystem::get().allocTracker.findBaseAlloc(addr); if (alloc) { // auto& allocVal = alloc.getValue(); - *type = alloc->second.typeId; + *type_id = alloc->second.typeId; *base_address = alloc->first; return typeart::RuntimeSystem::get().typeResolution.getContainingTypeInfo(addr, alloc->first, alloc->second, count, - offset); + byte_offset); } return TYPEART_UNKNOWN_ADDRESS; } -typeart_status typeart_get_subtype(const void* base_addr, size_t offset, typeart_struct_layout container_layout, - int* subtype_id, const void** subtype_base_addr, size_t* subtype_offset, +typeart_status typeart_get_subtype(const void* base_addr, size_t offset, const typeart_struct_layout* container_layout, + int* subtype_id, const void** subtype_base_addr, size_t* subtype_byte_offset, size_t* subtype_count) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.getSubTypeInfo(base_addr, offset, container_layout, subtype_id, - subtype_base_addr, subtype_offset, subtype_count); + auto status = typeart::RuntimeSystem::get().typeResolution.getSubTypeInfo( + base_addr, offset, *container_layout, subtype_id, subtype_base_addr, subtype_byte_offset, subtype_count); + return status; } typeart_status typeart_resolve_type_addr(const void* addr, typeart_struct_layout* struct_layout) { diff --git a/lib/runtime/TypeResolution.h b/lib/runtime/TypeResolution.h index 5160435f..598121ee 100644 --- a/lib/runtime/TypeResolution.h +++ b/lib/runtime/TypeResolution.h @@ -24,8 +24,6 @@ namespace typeart { -using BuiltinType = typeart_builtin_type; - struct PointerInfo; class TypeResolution { @@ -35,18 +33,14 @@ class TypeResolution { public: using TypeArtStatus = typeart_status; - TypeResolution(const TypeDB& db, Recorder& recorder); - - [[nodiscard]] size_t getMemberIndex(typeart_struct_layout structInfo, size_t offset) const; + TypeResolution(const TypeDB& type_db, Recorder& recorder); - TypeArtStatus getSubTypeInfo(const void* baseAddr, size_t offset, typeart_struct_layout containerInfo, int* subType, - const void** subTypeBaseAddr, size_t* subTypeOffset, size_t* subTypeCount) const; + TypeArtStatus getSubTypeInfo(const void* baseAddr, size_t offset, const typeart_struct_layout& containerInfo, + int* subType, const void** subTypeBaseAddr, size_t* subTypeOffset, + size_t* subTypeCount) const; - TypeArtStatus getSubTypeInfo(const void* baseAddr, size_t offset, const StructTypeInfo& containerInfo, int* subType, - const void** subTypeBaseAddr, size_t* subTypeOffset, size_t* subTypeCount) const; - - TypeArtStatus getTypeInfoInternal(const void* baseAddr, size_t offset, const StructTypeInfo& containerInfo, int* type, - size_t* count) const; + TypeArtStatus getTypeInfoInternal(const void* struct_type_info, size_t offset, const StructTypeInfo& containerInfo, + int* type, size_t* count) const; TypeArtStatus getTypeInfo(const void* addr, const void* basePtr, const PointerInfo& ptrInfo, int* type, size_t* count) const; @@ -54,9 +48,7 @@ class TypeResolution { TypeArtStatus getContainingTypeInfo(const void* addr, const void* basePtr, const PointerInfo& ptrInfo, size_t* count, size_t* offset) const; - TypeArtStatus getBuiltinInfo(const void* addr, const PointerInfo& ptrInfo, typeart::BuiltinType* type) const; - - TypeArtStatus getStructInfo(int id, const StructTypeInfo** structInfo) const; + TypeArtStatus getStructInfo(int type_id, const StructTypeInfo** structInfo) const; [[nodiscard]] const TypeDB& db() const; }; diff --git a/lib/support/CMakeLists.txt b/lib/support/CMakeLists.txt index 1e086089..61d53d10 100644 --- a/lib/support/CMakeLists.txt +++ b/lib/support/CMakeLists.txt @@ -11,25 +11,25 @@ set_target_properties( ) target_include_directories( - ${TYPEART_PREFIX}_SystemStatic + ${TYPEART_PREFIX}_SystemStatic ${warning_guard} PUBLIC $ - $ + $ ) -target_project_compile_options(${TYPEART_PREFIX}_SystemStatic) -target_define_file_basename(${TYPEART_PREFIX}_SystemStatic) -target_project_coverage_options(${TYPEART_PREFIX}_SystemStatic) +typeart_target_compile_options(${TYPEART_PREFIX}_SystemStatic) +typeart_target_define_file_basename(${TYPEART_PREFIX}_SystemStatic) +typeart_target_coverage_options(${TYPEART_PREFIX}_SystemStatic) -if(ENABLE_TSAN) - target_tsan_options(${TYPEART_PREFIX}_SystemStatic) +if(TYPEART_TSAN) + typeart_target_tsan_options(${TYPEART_PREFIX}_SystemStatic) endif() -if(ENABLE_ASAN) - target_asan_options(${TYPEART_PREFIX}_SystemStatic) +if(TYPEART_ASAN) + typeart_target_asan_options(${TYPEART_PREFIX}_SystemStatic) endif() -if(ENABLE_UBSAN) - target_ubsan_options(${TYPEART_PREFIX}_SystemStatic) +if(TYPEART_UBSAN) + typeart_target_ubsan_options(${TYPEART_PREFIX}_SystemStatic) endif() set(CONFIG_NAME ${PROJECT_NAME}System) diff --git a/lib/support/Logger.h b/lib/support/Logger.h index 94d588e4..6d7d3c69 100644 --- a/lib/support/Logger.h +++ b/lib/support/Logger.h @@ -15,24 +15,24 @@ #include "llvm/Support/raw_ostream.h" -#ifndef LOG_LEVEL +#ifndef TYPEART_LOG_LEVEL /* - * Usually set at compile time: -DLOG_LEVEL=, N in [0, 3] for output + * Usually set at compile time: -DTYPEART_LOG_LEVEL=, N in [0, 3] for output * 3 being most verbose */ -#define LOG_LEVEL 3 +#define TYPEART_LOG_LEVEL 3 #endif #ifndef LOG_BASENAME_FILE #define LOG_BASENAME_FILE __FILE__ #endif -#ifndef MPI_LOGGER -#define MPI_LOGGER 0 +#ifndef TYPEART_MPI_LOGGER +#define TYPEART_MPI_LOGGER 0 #endif namespace typeart::detail { -#if MPI_LOGGER +#if TYPEART_MPI_LOGGER void typeart_log(const std::string& rank); #else inline void typeart_log(const std::string& msg) { @@ -43,7 +43,7 @@ inline void typeart_log(const std::string& msg) { // clang-format off #define OO_LOG_LEVEL_MSG(LEVEL_NUM, LEVEL, MSG) \ - if ((LEVEL_NUM) <= LOG_LEVEL) { \ + if ((LEVEL_NUM) <= TYPEART_LOG_LEVEL) { \ std::string logging_message; \ llvm::raw_string_ostream rso(logging_message); \ rso << (LEVEL) << LOG_BASENAME_FILE << ":" << __func__ << ":" << __LINE__ << ":" << MSG << "\n"; /* NOLINT */ \ @@ -51,7 +51,7 @@ inline void typeart_log(const std::string& msg) { } #define OO_LOG_LEVEL_MSG_BARE(LEVEL_NUM, LEVEL, MSG) \ - if ((LEVEL_NUM) <= LOG_LEVEL) { \ + if ((LEVEL_NUM) <= TYPEART_LOG_LEVEL) { \ std::string logging_message; \ llvm::raw_string_ostream rso(logging_message); \ rso << (LEVEL) << " " << MSG << "\n"; /* NOLINT */ \ @@ -59,12 +59,12 @@ inline void typeart_log(const std::string& msg) { } // clang-format on -#define LOG_TRACE(MSG) OO_LOG_LEVEL_MSG_BARE(3, "[Trace]", MSG) -#define LOG_DEBUG(MSG) OO_LOG_LEVEL_MSG(3, "[Debug]", MSG) -#define LOG_INFO(MSG) OO_LOG_LEVEL_MSG(2, "[Info]", MSG) +#define LOG_TRACE(MSG) OO_LOG_LEVEL_MSG_BARE(3, "[Trace]", MSG) +#define LOG_DEBUG(MSG) OO_LOG_LEVEL_MSG(3, "[Debug]", MSG) +#define LOG_INFO(MSG) OO_LOG_LEVEL_MSG(2, "[Info]", MSG) #define LOG_WARNING(MSG) OO_LOG_LEVEL_MSG(1, "[Warning]", MSG) -#define LOG_ERROR(MSG) OO_LOG_LEVEL_MSG(1, "[Error]", MSG) -#define LOG_FATAL(MSG) OO_LOG_LEVEL_MSG(0, "[Fatal]", MSG) -#define LOG_MSG(MSG) llvm::errs() << MSG << "\n"; /* NOLINT */ +#define LOG_ERROR(MSG) OO_LOG_LEVEL_MSG(1, "[Error]", MSG) +#define LOG_FATAL(MSG) OO_LOG_LEVEL_MSG(0, "[Fatal]", MSG) +#define LOG_MSG(MSG) llvm::errs() << MSG << "\n"; /* NOLINT */ #endif /* LIB_LOGGER_H_ */ diff --git a/lib/typelib/CMakeLists.txt b/lib/typelib/CMakeLists.txt index aa264073..3a926fa1 100644 --- a/lib/typelib/CMakeLists.txt +++ b/lib/typelib/CMakeLists.txt @@ -7,16 +7,16 @@ set_target_properties(${TYPEART_PREFIX}_TypesObj PROPERTIES POSITION_INDEPENDENT target_include_directories(${TYPEART_PREFIX}_TypesObj SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS}) target_include_directories( - ${TYPEART_PREFIX}_TypesObj + ${TYPEART_PREFIX}_TypesObj ${warning_guard} PUBLIC $ PRIVATE $ ) -target_compile_definitions(${TYPEART_PREFIX}_TypesObj PRIVATE LOG_LEVEL=${LOG_LEVEL}) +target_compile_definitions(${TYPEART_PREFIX}_TypesObj PRIVATE TYPEART_LOG_LEVEL=${TYPEART_LOG_LEVEL}) -target_project_compile_options(${TYPEART_PREFIX}_TypesObj) +typeart_target_compile_options(${TYPEART_PREFIX}_TypesObj) -target_project_coverage_options(${TYPEART_PREFIX}_TypesObj) +typeart_target_coverage_options(${TYPEART_PREFIX}_TypesObj) make_tidy_check(${TYPEART_PREFIX}_TypesObj "${TYPE_LIB_SOURCES}") @@ -29,15 +29,15 @@ set_target_properties( EXPORT_NAME "Types" ) target_include_directories( - ${TYPEART_PREFIX}_Types + ${TYPEART_PREFIX}_Types ${warning_guard} PUBLIC $ - $ + $ PRIVATE $ ) target_link_libraries(${TYPEART_PREFIX}_Types PRIVATE LLVMCore LLVMSupport) -target_project_coverage_options(${TYPEART_PREFIX}_Types) +typeart_target_coverage_options(${TYPEART_PREFIX}_Types) add_library(${TYPEART_PREFIX}_TypesStatic STATIC $) add_library(typeart::TypesStatic ALIAS ${TYPEART_PREFIX}_TypesStatic) @@ -48,13 +48,13 @@ set_target_properties( EXPORT_NAME "TypesStatic" ) target_include_directories( - ${TYPEART_PREFIX}_TypesStatic + ${TYPEART_PREFIX}_TypesStatic ${warning_guard} PUBLIC $ - $ + $ PRIVATE $ ) -target_project_coverage_options(${TYPEART_PREFIX}_TypesStatic) +typeart_target_coverage_options(${TYPEART_PREFIX}_TypesStatic) set(CONFIG_NAME ${PROJECT_NAME}Types) set(TARGETS_EXPORT_NAME ${CONFIG_NAME}Targets) diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index bb7dd3c1..12ce06f1 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -1,4 +1,4 @@ -function(configure_typeart_script input output) +function(typeart_configure_script input output) cmake_parse_arguments( ARG "" "" "INSTALL_MODE;COMPILER;WITH_FILTER;APPLY_MODE" ${ARGN} ) @@ -7,13 +7,9 @@ function(configure_typeart_script input output) set(TYPEART_PROJECT_DIR ${PROJECT_SOURCE_DIR}) set(TYPEART_SCRIPT_DIR ${PROJECT_SOURCE_DIR}/scripts) - set(TYPEART_MPI_INTERCEPT_LIB libinterceptor-rt.so) - set(TYPEART_ANALYSIS_PLUGIN meminstfinderpass.so) - set(TYPEART_PLUGIN typeartpass.so) - if(ARG_INSTALL_MODE) set(TYPEART_INCLUDE_DIRS - -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR} + "-I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}" ) set(TYPEART_MPI_INTERCEPT_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} @@ -29,11 +25,24 @@ function(configure_typeart_script input output) set(TYPEART_INCLUDE_DIRS "-I${PROJECT_SOURCE_DIR}/lib/typelib -I${PROJECT_SOURCE_DIR}/lib/runtime -I${PROJECT_SOURCE_DIR}/lib/passes/typegen" ) - set(TYPEART_MPI_INTERCEPT_DIR ${CMAKE_BINARY_DIR}/lib/mpi_interceptor) - set(TYPEART_RT_DIR ${CMAKE_BINARY_DIR}/lib/runtime) - set(TYPEART_PASS_DIR ${CMAKE_BINARY_DIR}/lib/passes) - set(TYPEART_ANALYSIS_PASS_DIR ${TYPEART_PASS_DIR}/analysis) - set(TYPEART_BINARY_DIR ${CMAKE_BINARY_DIR}) + if(LIBRARY_OUTPUT_PATH) + set(TYPEART_MPI_INTERCEPT_DIR ${LIBRARY_OUTPUT_PATH}) + set(TYPEART_RT_DIR ${LIBRARY_OUTPUT_PATH}) + set(TYPEART_PASS_DIR ${LIBRARY_OUTPUT_PATH}) + set(TYPEART_ANALYSIS_PASS_DIR ${LIBRARY_OUTPUT_PATH}) + else() + set(TYPEART_MPI_INTERCEPT_DIR ${CMAKE_BINARY_DIR}/lib/mpi_interceptor) + set(TYPEART_RT_DIR ${CMAKE_BINARY_DIR}/lib/runtime) + set(TYPEART_PASS_DIR ${CMAKE_BINARY_DIR}/lib/passes) + set(TYPEART_ANALYSIS_PASS_DIR ${TYPEART_PASS_DIR}/analysis) + endif() + + if(EXECUTABLE_OUTPUT_PATH) + set(TYPEART_BINARY_DIR ${EXECUTABLE_OUTPUT_PATH}) + else() + set(TYPEART_BINARY_DIR ${CMAKE_BINARY_DIR}) + endif() + set(TYPEART_RELOCATABLE 0) endif() @@ -63,39 +72,35 @@ function(configure_typeart_script input output) endif() if(ARG_WITH_FILTER) - set(TYPEART_CALLFILTER "-call-filter") + set(TYPEART_CALLFILTER "-typeart-call-filter") endif() - if(ENABLE_TSAN) - target_tsan_flags(TYPEART_SAN_FLAGS) + if(TYPEART_TSAN) + typeart_target_tsan_flags(TYPEART_SAN_FLAGS) endif() - if(ENABLE_ASAN) - target_asan_flags(asan_flags) + if(TYPEART_ASAN) + typeart_target_asan_flags(asan_flags) set(TYPEART_SAN_FLAGS ${TYPEART_SAN_FLAGS} ${asan_flags}) endif() - if(ENABLE_UBSAN) - target_ubsan_flags(ubsan_flags) + if(TYPEART_UBSAN) + typeart_target_ubsan_flags(ubsan_flags) set(TYPEART_SAN_FLAGS ${TYPEART_SAN_FLAGS} ${ubsan_flags}) endif() list(JOIN TYPEART_SAN_FLAGS " " TYPEART_SAN_FLAGS) - target_generate_file(${input} ${output}) + typeart_target_generate_file(${input} ${output}) endfunction() -function(configure_typeart_coverage_script input output) - find_program( - LLVMCOV_COMMAND - NAMES llvm-cov-10 llvm-cov - HINTS ${LLVM_TOOLS_BINARY_DIR} - ) - if(LLVMCOV_COMMAND) +function(typeart_configure_coverage_script input output) + typeart_find_llvm_progs(TYPEART_LLVMCOV_COMMAND "llvm-cov-${LLVM_VERSION_MAJOR};llvm-cov") + if(TYPEART_LLVMCOV_COMMAND) file( GENERATE OUTPUT ${output} - CONTENT "#!/usr/bin/env bash\n\n${LLVMCOV_COMMAND} gcov \"$@\"\n" + CONTENT "#!/usr/bin/env bash\n\n${TYPEART_LLVMCOV_COMMAND} gcov \"$@\"\n" FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ @@ -106,78 +111,148 @@ function(configure_typeart_coverage_script input output) endif() endfunction() -configure_typeart_coverage_script(llvm-gcov.sh.in llvm-gcov.sh) +function(typeart_find_mpi_vendor_helper symbol ret_value) + find_package(MPI) + + if(NOT MPI_FOUND) + set(${ret_value} false) + return() + endif() + + set(MPI_TEST_CODE + "#include + int main(void) { + #if !defined(${symbol}) + an_illegal_stmt + #endif + return 0; + }") + + set(CMAKE_REQUIRED_INCLUDES ${MPI_C_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_FLAGS "${MPI_C_COMPILE_FLAGS}") + set(CMAKE_REQUIRED_DEFINITIONS "") + set(CMAKE_REQUIRED_LIBRARIES "${MPI_C_LIBRARIES}") + + check_c_source_compiles("${MPI_TEST_CODE}" ${ret_value}) +endfunction() + +function(set_typeart_mpi_compiler) + # Note on mpich & Intel: Intel may also define \"MPICH_NAME\" + # in mpi.h, so check MPICH last + list(APPEND l_vendor OPEN_MPI INTEL_MPI MPICH) + list(APPEND l_symbol OPEN_MPI I_MPI_VERSION MPICH_NAME) + list(APPEND l_env_c OMPI_CC I_MPI_CC MPICH_CC) + list(APPEND l_env_cxx OMPI_CXX I_MPI_CXX MPICH_CXX) + + foreach(vendor symbol env_c env_cxx IN ZIP_LISTS l_vendor l_symbol l_env_c l_env_cxx) + typeart_find_mpi_vendor_helper(${symbol} TYPEART_HAVE_${vendor}) + if(TYPEART_HAVE_${vendor}) + if(MPI_C_FOUND) + set(TYPEART_MPICC + "env ${env_c}=${TYPEART_CLANG_EXEC} ${MPI_C_COMPILER}" + CACHE STRING "TypeART MPICC compiler command for scripts" + ) + mark_as_advanced(TYPEART_MPICC) + endif() + if(MPI_CXX_FOUND) + set(TYPEART_MPICXX + "env ${env_cxx}=${TYPEART_CLANGCXX_EXEC} ${MPI_CXX_COMPILER}" + CACHE STRING "TypeART MPICXX compiler command for scripts" + ) + mark_as_advanced(TYPEART_MPICXX) + endif() + break() + endif() + endforeach() +endfunction() + +typeart_configure_coverage_script(llvm-gcov.sh.in llvm-gcov.sh) -configure_typeart_script(typeart-tmpl.sh.in run.sh) -configure_typeart_script(typeart-tmpl.sh.in apply.sh +typeart_configure_script(typeart-tmpl.sh.in run.sh) +typeart_configure_script(typeart-tmpl.sh.in apply.sh APPLY_MODE ON ) -configure_typeart_script( +typeart_configure_script( typeart-tmpl.sh.in typeart-run${CMAKE_DEBUG_POSTFIX}.sh INSTALL_MODE ON ) -configure_typeart_script( +typeart_configure_script( typeart-tmpl.sh.in typeart-apply${CMAKE_DEBUG_POSTFIX}.sh INSTALL_MODE ON APPLY_MODE ON ) -configure_typeart_script( +typeart_configure_script( typeart-wrapper.in typeart-clang${CMAKE_DEBUG_POSTFIX} INSTALL_MODE ON COMPILER ${TYPEART_CLANG_EXEC} ) -configure_typeart_script( +typeart_configure_script( typeart-wrapper.in typeart-clang++${CMAKE_DEBUG_POSTFIX} INSTALL_MODE ON COMPILER ${TYPEART_CLANGCXX_EXEC} ) -configure_typeart_script( +typeart_configure_script( typeart-wrapper.in typeart-clang-test COMPILER ${TYPEART_CLANG_EXEC} ) -configure_typeart_script( +typeart_configure_script( typeart-wrapper.in typeart-clang++-test COMPILER ${TYPEART_CLANGCXX_EXEC} ) -if(${MPI_C_FOUND}) - configure_typeart_script( +if(MPI_FOUND) + set_typeart_mpi_compiler() +endif() + +if(MPI_C_FOUND) + typeart_configure_script( typeart-wrapper.in typeart-mpicc${CMAKE_DEBUG_POSTFIX} INSTALL_MODE ON WITH_FILTER ON - COMPILER "env OMPI_CC=${TYPEART_CLANG_EXEC} ${MPI_C_COMPILER}" + COMPILER "${TYPEART_MPICC}" ) - configure_typeart_script( + typeart_configure_script( typeart-wrapper.in typeart-mpicc-test WITH_FILTER ON - COMPILER "env OMPI_CC=${TYPEART_CLANG_EXEC} ${MPI_C_COMPILER}" + COMPILER "${TYPEART_MPICC}" ) endif() -if(${MPI_CXX_FOUND}) - configure_typeart_script( +if(MPI_CXX_FOUND) + typeart_configure_script( typeart-wrapper.in typeart-mpic++${CMAKE_DEBUG_POSTFIX} INSTALL_MODE ON WITH_FILTER ON - COMPILER "env OMPI_CXX=${TYPEART_CLANGCXX_EXEC} ${MPI_CXX_COMPILER}" + COMPILER "${TYPEART_MPICXX}" ) - configure_typeart_script( + typeart_configure_script( typeart-wrapper.in typeart-mpic++-test WITH_FILTER ON - COMPILER "env OMPI_CXX=${TYPEART_CLANGCXX_EXEC} ${MPI_CXX_COMPILER}" + COMPILER "${TYPEART_MPICXX}" ) endif() +set(TYPEART_INSTALL_SCRIPT_CANDIDATE + typeart-mpicc + typeart-mpic++ + typeart-clang++ + typeart-clang + typeart-run + typeart-apply + CACHE INTERNAL + "Names of TypeART scripts which can be installed." +) + install( PROGRAMS - $<$:${CMAKE_CURRENT_BINARY_DIR}/typeart-run${CMAKE_DEBUG_POSTFIX}.sh> - $<$:${CMAKE_CURRENT_BINARY_DIR}/typeart-apply${CMAKE_DEBUG_POSTFIX}.sh> + $<$:${CMAKE_CURRENT_BINARY_DIR}/typeart-run${CMAKE_DEBUG_POSTFIX}.sh> + $<$:${CMAKE_CURRENT_BINARY_DIR}/typeart-apply${CMAKE_DEBUG_POSTFIX}.sh> ${CMAKE_CURRENT_BINARY_DIR}/typeart-clang++${CMAKE_DEBUG_POSTFIX} ${CMAKE_CURRENT_BINARY_DIR}/typeart-clang${CMAKE_DEBUG_POSTFIX} - $<$,$>:${CMAKE_CURRENT_BINARY_DIR}/typeart-mpicc${CMAKE_DEBUG_POSTFIX}> - $<$,$>:${CMAKE_CURRENT_BINARY_DIR}/typeart-mpic++${CMAKE_DEBUG_POSTFIX}> + $<$,$>:${CMAKE_CURRENT_BINARY_DIR}/typeart-mpicc${CMAKE_DEBUG_POSTFIX}> + $<$,$>:${CMAKE_CURRENT_BINARY_DIR}/typeart-mpic++${CMAKE_DEBUG_POSTFIX}> DESTINATION ${CMAKE_INSTALL_BINDIR} ) diff --git a/scripts/typeart-tmpl.sh.in b/scripts/typeart-tmpl.sh.in index 91969750..ce675368 100644 --- a/scripts/typeart-tmpl.sh.in +++ b/scripts/typeart-tmpl.sh.in @@ -127,7 +127,7 @@ function global_init() { # shellcheck disable=SC2155 local -r typeart_install_dir="$(dirname "${typeart_bin_dir}")" local -r typeart_lib_dir="${typeart_install_dir}/@CMAKE_INSTALL_LIBDIR@" - local -r typeart_include_dir="-I${typeart_install_dir}/@CMAKE_INSTALL_INCLUDEDIR@" + local -r typeart_include_dir="-I${typeart_install_dir}/@CMAKE_INSTALL_INCLUDEDIR@/@PROJECT_NAME@" local -r typeart_pass="${typeart_lib_dir}/$" readonly typeart_interceptor="@TYPEART_MPI_INTERCEPT_DIR@/@TYPEART_MPI_TOOL@" fi @@ -144,9 +144,9 @@ function global_init() { # shellcheck disable=SC2027 readonly typeart_plugin="-load "${typeart_pass}" -typeart" - readonly typeart_stack_mode_args="-typeart-no-heap -typeart-alloca -typeart-stats" - readonly typeart_heap_mode_args="-typeart-no-heap=false -typeart-stats" - readonly typeart_combined_mode_args="${typeart_heap_mode_args} -typeart-alloca" + readonly typeart_stack_mode_args="-typeart-heap=false -typeart-stack -typeart-stats" + readonly typeart_heap_mode_args="-typeart-heap=true -typeart-stats" + readonly typeart_combined_mode_args="${typeart_heap_mode_args} -typeart-stack" } function toolchain_init() { diff --git a/scripts/typeart-wrapper.in b/scripts/typeart-wrapper.in index 4e5d5fd0..4abcec25 100755 --- a/scripts/typeart-wrapper.in +++ b/scripts/typeart-wrapper.in @@ -25,7 +25,7 @@ function global_init() { # shellcheck disable=SC2155 local -r typeart_install_dir="$(dirname "${typeart_bin_dir}")" local -r typeart_lib_dir="${typeart_install_dir}/@CMAKE_INSTALL_LIBDIR@" - local -r typeart_include_dir="-I${typeart_install_dir}/@CMAKE_INSTALL_INCLUDEDIR@" + local -r typeart_include_dir="-I${typeart_install_dir}/@CMAKE_INSTALL_INCLUDEDIR@/@PROJECT_NAME@" local -r typeart_pass="${typeart_lib_dir}/$" fi @@ -41,8 +41,8 @@ function global_init() { # shellcheck disable=SC2027 readonly typeart_plugin="-load "${typeart_pass}" -typeart" - readonly typeart_stack_mode_args="-typeart-no-heap -typeart-alloca -typeart-stats @TYPEART_CALLFILTER@" - readonly typeart_heap_mode_args="-typeart-no-heap=false -typeart-stats" + readonly typeart_stack_mode_args="-typeart-heap=false -typeart-stack -typeart-stats @TYPEART_CALLFILTER@" + readonly typeart_heap_mode_args="-typeart-heap=true -typeart-stats" } function is_wrapper_disabled() { @@ -58,21 +58,33 @@ function is_wrapper_disabled() { function is_linking() { for arg in "$@"; do case "$arg" in - -c | -S | -E | -M | -MM | -MMD) + -c | -S | -E) return 0 - ;; + ;; esac done return 1 } +function has_source() { + for arg in "$@"; do + local extension_of_arg="${arg##*.}" + case "$extension_of_arg" in + cpp | cxx | cc | c) + return 1 + ;; + esac + done + return 0 +} + function skip_typeart_compile() { # -E inline header; -M list (all) headers; -MM list file deps for arg in "$@"; do case "$arg" in -E | -M | -MM) return 1 - ;; + ;; esac done return 0 @@ -159,9 +171,17 @@ function parse_cmd_line() { optimize=$1 shift ;; - -c | -MMD | -S) + -MT) + if [ -n "$2" ]; then + ta_more_args+=" $1 $2" + shift 2 + else + ta_more_args+=" $1" + shift 1 + fi + ;; + -c | -S) # -S compile to asm - # -MMD list file dep and compile if [ "$1" == "-S" ]; then typeart_to_asm=1 fi @@ -265,7 +285,21 @@ function main_in() { fi is_linking "$@" - if [ "$?" == 1 ]; then + local -r linking=$? + has_source "$@" + local -r with_source=$? + + if [ "$linking" == 1 ] && [ "$with_source" == 1 ]; then + parse_cmd_line "$@" + main_compile "$@" + if [ "$found_exe_file" == 1 ]; then + ta_more_args+=" -o ${exe_file}" + fi + main_link "$ta_more_args" "${object_file}" + if [ -f "${object_file}" ]; then + rm "${object_file}" + fi + elif [ "$linking" == 1 ]; then main_link "$@" else parse_cmd_line "$@" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c9c9e445..10c363fa 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,15 @@ +typeart_find_llvm_progs(TYPEART_FILECHECK_EXEC "FileCheck-${LLVM_VERSION_MAJOR};FileCheck" ABORT_IF_MISSING) + +if(LLVM_EXTERNAL_LIT) + cmake_path(GET LLVM_EXTERNAL_LIT PARENT_PATH LLVM_EXTERNAL_LIT_DIR) +endif() + +typeart_find_llvm_progs(TYPEART_LIT_EXEC + "llvm-lit;lit;lit.py" + HINTS ${LLVM_EXTERNAL_LIT_DIR} /usr/lib/llvm-${LLVM_VERSION_MAJOR} /usr/lib/llvm /usr/bin /usr/local/bin /opt/local/bin + ABORT_IF_MISSING +) + macro(pythonize_bool truth_var var) if(${truth_var}) set(${var} True) @@ -6,7 +18,7 @@ macro(pythonize_bool truth_var var) endif() endmacro() -function(configure_typeart_lit_site_cfg input output) +function(typeart_configure_lit_site input output) # This function provides an automatic way to 'configure'-like generate a file # based on a set of common and custom variables, specifically targeting the # variables needed for the 'lit.site.cfg' files. This function bundles the @@ -21,21 +33,21 @@ function(configure_typeart_lit_site_cfg input output) set(TYPEARTPASS_RT_DIR ${CMAKE_BINARY_DIR}/lib/runtime) set(TYPEARTPASS_PROFILE_FILE ${TYPEART_PROFILE_DIR}/lit-code-%p.profraw) - pythonize_bool(SOFTCOUNTERS TYPEARTPASS_SOFTCOUNTER) + pythonize_bool(TYPEART_SOFTCOUNTERS TYPEARTPASS_SOFTCOUNTER) pythonize_bool(OPENMP_FOUND TYPEARTPASS_OPENMP) - pythonize_bool(CMAKE_THREAD_LIBS_INIT TYPEARTPASS_THREADS) - pythonize_bool(DISABLE_THREAD_SAFETY TYPEARTPASS_THREAD_UNSAFE) + pythonize_bool(Threads_FOUND TYPEARTPASS_THREADS) + pythonize_bool(TYPEART_DISABLE_THREAD_SAFETY TYPEARTPASS_THREAD_UNSAFE) pythonize_bool(MPI_C_FOUND TYPEARTPASS_MPI_C) pythonize_bool(MPI_CXX_FOUND TYPEARTPASS_MPI_CXX) - pythonize_bool(ENABLE_TSAN TYPEARTPASS_TSAN) - pythonize_bool(ENABLE_ASAN TYPEARTPASS_ASAN) - pythonize_bool(ENABLE_UBSAN TYPEARTPASS_UBSAN) + pythonize_bool(TYPEART_TSAN TYPEARTPASS_TSAN) + pythonize_bool(TYPEART_ASAN TYPEARTPASS_ASAN) + pythonize_bool(TYPEART_UBSAN TYPEARTPASS_UBSAN) set(TYPEART_COVERAGE False) - if(ENABLE_CODE_COVERAGE OR ENABLE_LLVM_CODE_COVERAGE) + if(TYPEART_CODE_COVERAGE OR TYPEART_LLVM_CODE_COVERAGE) set(TYPEART_COVERAGE True) endif() @@ -47,46 +59,93 @@ function(configure_typeart_lit_site_cfg input output) "## Autogenerated by TypeART generation from ${input}\n## Do not edit!" ) - target_generate_file(${input} ${output}) + typeart_target_generate_file(${input} ${output}) endfunction() -add_format_target(format-tests +typeart_add_format_target(typeart-format-tests "Formats project test source files" TARGETS *.c *.cpp *.h ) -configure_typeart_lit_site_cfg( +typeart_configure_lit_site( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg ) -set(TYPEARTPASS_TEST_DEPENDS typeart::TransformPass typeart::Runtime) +function(typeart_add_lit_testsuite target comment) + cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN}) -add_lit_testsuite(lit-pass-test - "Running the TYPEART support pass tests" - ${CMAKE_CURRENT_SOURCE_DIR} - ARGS -v -j 1 - PARAMS typeartpass_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg - DEPENDS ${TYPEARTPASS_TEST_DEPENDS} + foreach(param ${ARG_PARAMS}) + list(APPEND TEST_PARAMS --param ${param}) + endforeach() + + add_custom_target(${target} + COMMAND ${TYPEART_LIT_EXEC} ${ARG_ARGS} ${TEST_PARAMS} ${ARG_UNPARSED_ARGUMENTS} + COMMENT "${comment}" + USES_TERMINAL + ) + + if (ARG_DEPENDS) + add_dependencies(${target} ${ARG_DEPENDS}) + endif() +endfunction() + +function(typeart_add_lit_target) + cmake_parse_arguments(ARG "" "" "SUITES" ${ARGN}) + + foreach(suite IN LISTS ARG_SUITES) + if("${suite}" STREQUAL "all") + set(SUITE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + set(TARGET_NAME check-typeart) + else() + set(SUITE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${suite}) + set(TARGET_NAME check-typeart-${suite}) + endif() + + if(NOT EXISTS ${SUITE_PATH}) + message(WARNING "Could not find suitable lit test target at ${SUITE_PATH}") + continue() + endif() + + typeart_add_lit_testsuite(${TARGET_NAME} + "Running the lit suite TypeART::${suite}" + ${SUITE_PATH} + ARGS -v -j 1 + PARAMS typeartpass_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg + DEPENDS ${TYPEART_TEST_DEPENDS} + ) + endforeach() +endfunction() + +set(TYPEART_TEST_DEPENDS + typeart::TransformPass + typeart::Runtime + typeart::Types ) +set(TYPEART_SUITES + all + pass + runtime + script + typemapping +) + +typeart_add_lit_target(SUITES ${TYPEART_SUITES}) + add_test( - NAME ctest_lit_suite + NAME typeart-lit-suite COMMAND - ${LIT_COMMAND_I} -j 1 --param + ${TYPEART_LIT_EXEC} -j 1 --param typeartpass_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg ${CMAKE_CURRENT_SOURCE_DIR} ) -if(MPI_INTERCEPT_LIB) - add_subdirectory(lulesh) -endif() - -if(TEST_CONFIGURE_IDE) - function(add_test_target_ide target header sources) +if(TYPEART_TEST_CONFIGURE_IDE) + function(typeart_add_test_target_ide target header sources) add_executable(${target} EXCLUDE_FROM_ALL ${header} ${sources}) - add_dependencies(${target} ${TYPEARTPASS_TEST_DEPENDS}) + add_dependencies(${target} ${TYPEART_TEST_DEPENDS}) target_include_directories( ${target} PRIVATE ${PROJECT_SOURCE_DIR}/lib/typelib @@ -99,12 +158,12 @@ if(TEST_CONFIGURE_IDE) file(GLOB_RECURSE TYPEART_CC_TESTS CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.c) file(GLOB_RECURSE TYPEART_TEST_HEADER CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) - add_test_target_ide( + typeart_add_test_target_ide( typeart_cxx_test_objects "${TYPEART_TEST_HEADER}" "${TYPEART_CXX_TESTS}" ) set_target_properties(typeart_cxx_test_objects PROPERTIES LINKER_LANGUAGE CXX) target_compile_features(typeart_cxx_test_objects PUBLIC cxx_std_17) - add_test_target_ide( + typeart_add_test_target_ide( typeart_cc_test_objects "${TYPEART_TEST_HEADER}" "${TYPEART_CC_TESTS}" ) set_target_properties(typeart_cc_test_objects PROPERTIES LINKER_LANGUAGE C) diff --git a/test/lit.cfg b/test/lit.cfg index 9a8561a6..2a96e750 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -80,6 +80,7 @@ config.substitutions.append(('%clang-cpp', clang_cpp)) config.substitutions.append(('%clang-cc', clang_cc)) config.substitutions.append(('%opt', opt)) config.substitutions.append(('%filecheck', filecheck)) +config.substitutions.append(('%llc', llc)) # Substitutions: executables use "-" separator, variables use underscore config.substitutions.append(('%base_lib_path', typeart_base_lib_dir)) @@ -102,8 +103,8 @@ config.substitutions.append(('%omp_c_flags', openmp_c_flags)) config.substitutions.append(('%omp_cpp_flags', openmp_cxx_flags)) # TODO refactor typeart arguments (and add args for enabling heap/stack/globals etc.) -# config.substitutions.append(('%arg_stack', '-typeart-alloca')) -# config.substitutions.append(('%arg_heap', '-typeart-no-heap')) +# config.substitutions.append(('%arg_stack', '-typeart-stack')) +# config.substitutions.append(('%arg_heap', '-typeart-heap')) config.substitutions.append(('%apply-typeart', '{} -load {} {}'.format(opt, transform_pass, std_plugin_args))) config.substitutions.append(('%c-to-llvm', '{} {}'.format(clang_cc, to_llvm_args))) diff --git a/test/lulesh/CMakeLists.txt b/test/lulesh/CMakeLists.txt index 59148d8d..b7f7e28c 100644 --- a/test/lulesh/CMakeLists.txt +++ b/test/lulesh/CMakeLists.txt @@ -48,7 +48,7 @@ function(add_integration_test name dir exe_dir np args) set_tests_properties(${name} PROPERTIES ENVIRONMENT LLVM_PROFILE_FILE=${TYPEART_PROFILE_DIR}/code-%p-lulesh.profraw) endfunction() -if(ENABLE_TSAN) +if(TYPEART_TSAN) message(STATUS "TSAN with lulesh is currently unsupported") else() add_integration_test("lulesh2.0" "${WORK_DIR}" "${WORK_DIR}" ${LULESH_NP} "-s 12 -i 200") diff --git a/test/lulesh/Makefile b/test/lulesh/Makefile index f6b69c62..37eff8bd 100644 --- a/test/lulesh/Makefile +++ b/test/lulesh/Makefile @@ -25,7 +25,7 @@ CXXFLAGS = -g -I. -Wall LDFLAGS = -g -O3 PASSES=-load ${TYPEART_LIBPATH}/passes/analysis/meminstfinderpass.so -load ${TYPEART_LIBPATH}/passes/typeartpass.so -typeart-stats -CALL_FILTER=-call-filter -call-filter-impl=default +CALL_FILTER=-typeart-call-filter -typeart-call-filter-impl=default ifeq ($(TSAN), yes) CXXFLAGS += -fsanitize=thread @@ -34,7 +34,7 @@ endif .cc.o: lulesh.h ifeq ($(TYPEART), yes) - $(CXX) ${CXXFLAGS} -O1 -Xclang -disable-llvm-passes -S -emit-llvm $< -o - | opt $(PASSES) -typeart -S | opt -O3 -S | opt $(PASSES) -typeart -typeart-alloca $(CALL_FILTER) -typeart-no-heap=true | llc -x=ir -filetype=obj -o $@ + $(CXX) ${CXXFLAGS} -O1 -Xclang -disable-llvm-passes -S -emit-llvm $< -o - | opt $(PASSES) -typeart -S | opt -O3 -S | opt $(PASSES) -typeart -typeart-stack $(CALL_FILTER) -typeart-heap=false | llc -x=ir -filetype=obj -o $@ else $(CXX) $(CXXFLAGS) -O3 -c -o $@ $< endif diff --git a/test/lulesh/lulesh.h b/test/lulesh/lulesh.h index 25a2edc3..66c97eb9 100644 --- a/test/lulesh/lulesh.h +++ b/test/lulesh/lulesh.h @@ -72,40 +72,40 @@ inline real10 FABS(real10 arg) { // Stuff needed for boundary conditions // 2 BCs on each of 6 hexahedral faces (12 bits) -#define XI_M 0x00007 +#define XI_M 0x00007 #define XI_M_SYMM 0x00001 #define XI_M_FREE 0x00002 #define XI_M_COMM 0x00004 -#define XI_P 0x00038 +#define XI_P 0x00038 #define XI_P_SYMM 0x00008 #define XI_P_FREE 0x00010 #define XI_P_COMM 0x00020 -#define ETA_M 0x001c0 +#define ETA_M 0x001c0 #define ETA_M_SYMM 0x00040 #define ETA_M_FREE 0x00080 #define ETA_M_COMM 0x00100 -#define ETA_P 0x00e00 +#define ETA_P 0x00e00 #define ETA_P_SYMM 0x00200 #define ETA_P_FREE 0x00400 #define ETA_P_COMM 0x00800 -#define ZETA_M 0x07000 +#define ZETA_M 0x07000 #define ZETA_M_SYMM 0x01000 #define ZETA_M_FREE 0x02000 #define ZETA_M_COMM 0x04000 -#define ZETA_P 0x38000 +#define ZETA_P 0x38000 #define ZETA_P_SYMM 0x08000 #define ZETA_P_FREE 0x10000 #define ZETA_P_COMM 0x20000 // MPI Message Tags -#define MSG_COMM_SBN 1024 +#define MSG_COMM_SBN 1024 #define MSG_SYNC_POS_VEL 2048 -#define MSG_MONOQ 3072 +#define MSG_MONOQ 3072 #define MAX_FIELDS_PER_MPI_COMM 6 diff --git a/test/pass/arrays/01_simple_array.c b/test/pass/arrays/01_simple_array.c index 13438bf0..885dc80d 100644 --- a/test/pass/arrays/01_simple_array.c +++ b/test/pass/arrays/01_simple_array.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-stack-lifetime=false -S 2>&1 | %filecheck %s --check-prefixes CHECK,ALLOC // clang-format on void test() { int a[100]; @@ -9,9 +9,9 @@ void test() { // CHECK: %__ta_alloca_counter = alloca i32 // CHECK-NEXT: store i32 0, i32* %__ta_alloca_counter -// CHECK: [[POINTER:%[0-9a-z]+]] = alloca [100 x i32] -// CHECK-NEXT: [[POINTER2:%[0-9a-z]+]] = bitcast [100 x i32]* [[POINTER]] to i8* -// CHECK-NEXT: call void @__typeart_alloc_stack(i8* [[POINTER2]], i32 2, i64 100) +// ALLOC: [[POINTER:%[0-9a-z]+]] = alloca [100 x i32] +// ALLOC-NEXT: [[POINTER2:%[0-9a-z]+]] = bitcast [100 x i32]* [[POINTER]] to i8* +// ALLOC-NEXT: call void @__typeart_alloc_stack(i8* [[POINTER2]], i32 2, i64 100) // CHECK: call void @__typeart_leave_scope(i32 %__ta_counter_load) diff --git a/test/pass/arrays/02_array_to_pointer.c b/test/pass/arrays/02_array_to_pointer.c index b1e57477..8185c963 100644 --- a/test/pass/arrays/02_array_to_pointer.c +++ b/test/pass/arrays/02_array_to_pointer.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-filter-pointer-alloca=false -typeart-stack-lifetime=false -S 2>&1 | %filecheck %s // clang-format on void test() { int a[100]; diff --git a/test/pass/arrays/03_multidim_array.c b/test/pass/arrays/03_multidim_array.c index e3804ed8..4b5a063d 100644 --- a/test/pass/arrays/03_multidim_array.c +++ b/test/pass/arrays/03_multidim_array.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -S 2>&1 | %filecheck %s // clang-format on void test() { const int n = 64; diff --git a/test/pass/arrays/04_vla.c b/test/pass/arrays/04_vla.c index 3bb2ef1d..700209bf 100644 --- a/test/pass/arrays/04_vla.c +++ b/test/pass/arrays/04_vla.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -alloca-array-only=true -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-stack-array-only=true -S 2>&1 | %filecheck %s // clang-format on void test(int n) { int a[n]; diff --git a/test/pass/arrays/05_vector.c b/test/pass/arrays/05_vector.c index b8c762e8..605d6304 100644 --- a/test/pass/arrays/05_vector.c +++ b/test/pass/arrays/05_vector.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -S 2>&1 | %filecheck %s // clang-format on typedef float float2 __attribute__((ext_vector_type(2))); diff --git a/test/pass/filter/00_ignore_ta_memops.c b/test/pass/filter/00_ignore_ta_memops.c index c9332a9b..c46ebebd 100644 --- a/test/pass/filter/00_ignore_ta_memops.c +++ b/test/pass/filter/00_ignore_ta_memops.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -S | %apply-typeart -typeart-alloca -typeart-no-heap=true -call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -S | %apply-typeart -typeart-stack -typeart-heap=false -typeart-call-filter -S 2>&1 | %filecheck %s // clang-format on #include diff --git a/test/pass/filter/01_alloca.llin b/test/pass/filter/01_alloca.llin index 5413b705..7bbf3722 100644 --- a/test/pass/filter/01_alloca.llin +++ b/test/pass/filter/01_alloca.llin @@ -1,6 +1,5 @@ -; RUN: cat %s | %apply-typeart -typeart-alloca -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s -; RUN: cat %s | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=deprecated::default -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s -check-prefix=CHECK-FILTER -; RUN: cat %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s -check-prefix=CHECK-FILTER-EXP +; RUN: cat %s | %apply-typeart -typeart-stack -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s +; RUN: cat %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s -check-prefix=CHECK-FILTER-EXP ; ModuleID = '01_alloca.c' source_filename = "01_alloca.c" @@ -61,21 +60,6 @@ entry: ; Function Attrs: nounwind declare dso_local noalias i8* @malloc(i64) #1 -; Deprecated standard filter: -; CHECK-FILTER: define dso_local void @foo() -; CHECK-FILTER: %__ta_alloca_counter = alloca i{{(64|32)}} -; CHECK-FILTER-NEXT: store i{{(64|32)}} 0, i{{(64|32)}}* %__ta_alloca_counter -; CHECK-FILTER: %0 = bitcast i32** %c to i8* -; CHECK-FILTER-NEXT call void @__typeart_alloc_stack(i8* %0, i32 10, i64 1) -; CHECK-FILTER: %1 = bitcast i32* %d to i8* -; CHECK-FILTER-NEXT call void @__typeart_alloc_stack(i8* %1, i32 2, i64 1) -; CHECK-FILTER: %2 = bitcast i32* %x to i8* -; CHECK-FILTER-NEXT call void @__typeart_alloc_stack(i8* %2, i32 2, i64 1) -; CHECK-FILTER: %9 = load i{{(64|32)}}, i{{(64|32)}}* %__ta_alloca_counter -; CHECK-FILTER-NEXT: %10 = add i{{(64|32)}} 3, %9 -; CHECK-FILTER: call void @__typeart_leave_scope(i{{(64|32)}} %__ta_counter_load) - - ; New filter, TODO: %0 = bitcast should be filterable with proper data-flow tracking ; CHECK-FILTER-EXP: define dso_local void @foo() ; CHECK-FILTER-EXP: %__ta_alloca_counter = alloca i{{(64|32)}} diff --git a/test/pass/filter/02_recursion.c b/test/pass/filter/02_recursion.c index 3589d460..510cbc13 100644 --- a/test/pass/filter/02_recursion.c +++ b/test/pass/filter/02_recursion.c @@ -1,7 +1,6 @@ // Template for recursion.ll.in // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=deprecated::default -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s // clang-format on void bar(int* x) { } diff --git a/test/pass/filter/03_globals.c b/test/pass/filter/03_globals.c index d53f6897..361799cf 100644 --- a/test/pass/filter/03_globals.c +++ b/test/pass/filter/03_globals.c @@ -1,6 +1,5 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=deprecated::default -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s // clang-format on int a; @@ -12,7 +11,7 @@ void foo() { } // CHECK: MemInstFinderPass -// Global : 2 -// Global filter total : 1 -// Global call filtered % : 50.00 -// Global filtered % : 50.00 \ No newline at end of file +// CHECK: Global : 2 +// CHECK: Global filter total : 1 +// CHECK: Global call filtered % : 50.00 +// CHECK: Global filtered % : 50.00 \ No newline at end of file diff --git a/test/pass/filter/04_cg.c b/test/pass/filter/04_cg.c index 8528e8e0..b1b8ab5c 100644 --- a/test/pass/filter/04_cg.c +++ b/test/pass/filter/04_cg.c @@ -1,7 +1,6 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=cg -call-filter-cg-file=%p/04_cg.ipcg -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=deprecated::default -S 2>&1 | %filecheck %s --check-prefix=CHECK-default -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s --check-prefix=CHECK-default +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-call-filter-impl=cg -typeart-call-filter-cg-file=%p/04_cg.ipcg -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s --check-prefix=CHECK-default // clang-format on extern void bar(int* ptr); // reaches MPI, see 04_cg.ipcg diff --git a/test/pass/filter/05_correlate_sig.c b/test/pass/filter/05_correlate_sig.c index 6dee58a1..c8a8c983 100644 --- a/test/pass/filter/05_correlate_sig.c +++ b/test/pass/filter/05_correlate_sig.c @@ -1,7 +1,6 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=deprecated::default -call-filter-deep=true -S 2>&1 | %filecheck %s --check-prefix=CHECK-default -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-default -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=cg -call-filter-cg-file=%p/05_cg.ipcg -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-cg +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-default +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-call-filter-impl=cg -typeart-call-filter-cg-file=%p/05_cg.ipcg -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-cg // clang-format on extern void MPI_Mock(int, int, int); @@ -18,11 +17,6 @@ void foo() { MPI_Send((void*)d, e); } -// Standard filter -// CHECK-default: > Stack Memory -// CHECK-default-NEXT: Alloca : 5.00 -// CHECK-default-NEXT: Stack call filtered % : 60.00 - // Standard experimental filter // CHECK-exp-default: > Stack Memory // CHECK-exp-default-NEXT: Alloca : 5.00 diff --git a/test/pass/filter/06_empty.c b/test/pass/filter/06_empty.c index dea0bfbd..b88ad792 100644 --- a/test/pass/filter/06_empty.c +++ b/test/pass/filter/06_empty.c @@ -1,6 +1,5 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=deprecated::default -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s // clang-format on extern int d; diff --git a/test/pass/filter/07_lulesh_mock.cpp b/test/pass/filter/07_lulesh_mock.cpp index 99cd2d67..e60ea5f9 100644 --- a/test/pass/filter/07_lulesh_mock.cpp +++ b/test/pass/filter/07_lulesh_mock.cpp @@ -1,8 +1,6 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %s | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=deprecated::default -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %s | %opt -O3 -S | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=deprecated::default -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=CHECK-opt -// RUN: %c-to-llvm -fno-discard-value-names %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-default -// RUN: %c-to-llvm -fno-discard-value-names %s | %opt -O3 -S | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-default-opt +// RUN: %c-to-llvm -fno-discard-value-names %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-default +// RUN: %c-to-llvm -fno-discard-value-names %s | %opt -O3 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-default-opt // clang-format on using Real_t = double; @@ -82,16 +80,6 @@ void TimeIncrement(Domain& domain) { ++domain.cycle(); } -// Standard filter -// CHECK: > Stack Memory -// CHECK-NEXT: Alloca : 16.00 -// CHECK-NEXT: Stack call filtered % : 81.25 - -// Standard filter with -O3 -// CHECK-opt: > Stack Memory -// CHECK-opt-NEXT: Alloca : 2.00 -// CHECK-opt-NEXT: Stack call filtered % : 0.00 - // Standard experimental filter // CHECK-exp-default: > Stack Memory // CHECK-exp-default-NEXT: Alloca : 16.00 diff --git a/test/pass/filter/08_amg_box_algebra_mock.c b/test/pass/filter/08_amg_box_algebra_mock.c index 6ee7cf90..bec68111 100644 --- a/test/pass/filter/08_amg_box_algebra_mock.c +++ b/test/pass/filter/08_amg_box_algebra_mock.c @@ -1,5 +1,6 @@ // This file tests for an specific endless recursion in the filter implementations w.r.t. following store targets -// RUN: %c-to-llvm -fno-discard-value-names %s | %opt -O3 -S | %apply-typeart -typeart-alloca -call-filter -S 2>&1 \ +// RUN: %c-to-llvm -fno-discard-value-names %s | %opt -O3 -S \ +// RUN: | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 \ // RUN: | %filecheck %s --check-prefix=CHECK-exp-default-opt // CHECK-exp-default-opt: TypeArtPass [Heap & Stack] @@ -61,14 +62,14 @@ typedef struct hypre_BoxArrayArray_struct { #define hypre_CCBoxOffsetDistance(box, index) 0 -#define hypre_BoxArrayBoxes(box_array) ((box_array)->boxes) -#define hypre_BoxArrayBox(box_array, i) &((box_array)->boxes[(i)]) -#define hypre_BoxArraySize(box_array) ((box_array)->size) +#define hypre_BoxArrayBoxes(box_array) ((box_array)->boxes) +#define hypre_BoxArrayBox(box_array, i) &((box_array)->boxes[(i)]) +#define hypre_BoxArraySize(box_array) ((box_array)->size) #define hypre_BoxArrayAllocSize(box_array) ((box_array)->alloc_size) -#define hypre_BoxArrayArrayBoxArrays(box_array_array) ((box_array_array)->box_arrays) +#define hypre_BoxArrayArrayBoxArrays(box_array_array) ((box_array_array)->box_arrays) #define hypre_BoxArrayArrayBoxArray(box_array_array, i) ((box_array_array)->box_arrays[(i)]) -#define hypre_BoxArrayArraySize(box_array_array) ((box_array_array)->size) +#define hypre_BoxArrayArraySize(box_array_array) ((box_array_array)->size) extern int hypre_UnionBoxes(hypre_BoxArray* boxes); extern hypre_BoxArrayArray* hypre_BoxArrayArrayCreate(int); diff --git a/test/pass/filter/09_milc_gauge_stuff_mock.c b/test/pass/filter/09_milc_gauge_stuff_mock.c index a08e5f23..786f131d 100644 --- a/test/pass/filter/09_milc_gauge_stuff_mock.c +++ b/test/pass/filter/09_milc_gauge_stuff_mock.c @@ -1,5 +1,6 @@ // This file tests for an specific endless recursion in the filter implementations w.r.t. following store targets -// RUN: %c-to-llvm -fno-discard-value-names %s | %opt -O3 -S | %apply-typeart -typeart-alloca -call-filter -S 2>&1 \ +// RUN: %c-to-llvm -fno-discard-value-names %s | %opt -O3 -S \ +// RUN: | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 \ // RUN: | %filecheck %s --check-prefix=CHECK-exp-default-opt // CHECK-exp-default-opt: TypeArtPass [Heap & Stack] @@ -13,10 +14,10 @@ #include #include -#define XUP 0 -#define YUP 1 -#define ZUP 2 -#define TUP 3 +#define XUP 0 +#define YUP 1 +#define ZUP 2 +#define TUP 3 #define TDOWN 4 #define ZDOWN 5 #define YDOWN 6 @@ -25,12 +26,12 @@ #define NODIR -1 #define OPP_DIR(dir) (7 - (dir)) -#define NDIRS 8 +#define NDIRS 8 -#define NREPS 1 -#define NLOOP 3 +#define NREPS 1 +#define NLOOP 3 #define MAX_LENGTH 6 -#define MAX_NUM 16 +#define MAX_NUM 16 extern char gauge_action_description[128]; int gauge_action_nloops = NLOOP; diff --git a/test/pass/filter/10_omp_empty.c b/test/pass/filter/10_omp_empty.c index dea6c49f..18f515f3 100644 --- a/test/pass/filter/10_omp_empty.c +++ b/test/pass/filter/10_omp_empty.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s // REQUIRES: openmp // clang-format on diff --git a/test/pass/filter/11_omp_mpi_simple.c b/test/pass/filter/11_omp_mpi_simple.c index bcfdb933..c9b79b2f 100644 --- a/test/pass/filter/11_omp_mpi_simple.c +++ b/test/pass/filter/11_omp_mpi_simple.c @@ -1,9 +1,9 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix CHECK-alloca-pointer -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix CHECK-alloca-pointer +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=true -S 2>&1 | %filecheck %s --check-prefix CHECK-alloca-pointer -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=true -S 2>&1 | %filecheck %s --check-prefix CHECK-alloca-pointer +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=true -S 2>&1 | %filecheck %s --check-prefix CHECK-alloca-pointer +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=true -S 2>&1 | %filecheck %s --check-prefix CHECK-alloca-pointer // clang-format on // REQUIRES: openmp diff --git a/test/pass/filter/12_omp_correlate.c b/test/pass/filter/12_omp_correlate.c index 4db5abee..aa994de9 100644 --- a/test/pass/filter/12_omp_correlate.c +++ b/test/pass/filter/12_omp_correlate.c @@ -1,11 +1,11 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=CHECK-opt -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=cg -call-filter-cg-file=%p/05_cg.ipcg -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-cg +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=CHECK-opt +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-call-filter-impl=cg -typeart-call-filter-cg-file=%p/05_cg.ipcg -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=CHECK-exp-cg -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=cg -call-filter-cg-file=%p/05_cg.ipcg -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-call-filter-impl=cg -typeart-call-filter-cg-file=%p/05_cg.ipcg -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst // REQUIRES: openmp // clang-format on @@ -20,8 +20,8 @@ void foo() { int c = 2; // check-inst: define {{.*}} @foo // check-inst: %d = alloca - // check-inst: %0 = bitcast i32* %d to i8* - // check-inst: call void @__typeart_alloc_stack(i8* %0, i32 2, i64 1) + // check-inst: [[POINTER:%[0-9a-z]+]] = bitcast i32* %d to i8* + // check-inst: call void @__typeart_alloc_stack(i8* [[POINTER]], i32 2, i64 1) // check-inst-not: __typeart_alloc_stack_omp int d = 3; int e = 4; diff --git a/test/pass/filter/13_omp_loops.c b/test/pass/filter/13_omp_loops.c index ba98326e..45102a50 100644 --- a/test/pass/filter/13_omp_loops.c +++ b/test/pass/filter/13_omp_loops.c @@ -1,11 +1,11 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=cg -call-filter-cg-file=%p/05_cg.ipcg -S 2>&1 +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-call-filter-impl=cg -typeart-call-filter-cg-file=%p/05_cg.ipcg -S 2>&1 -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -call-filter-impl=cg -call-filter-cg-file=%p/05_cg.ipcg -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-call-filter-impl=cg -typeart-call-filter-cg-file=%p/05_cg.ipcg -S | %filecheck %s --check-prefix=check-inst // REQUIRES: openmp // clang-format on @@ -20,8 +20,8 @@ void foo(int count) { int c = 2; // check-inst: define {{.*}} @foo // check-inst: %d = alloca - // check-inst: %0 = bitcast i32* %d to i8* - // check-inst: call void @__typeart_alloc_stack(i8* %0, i32 2, i64 1) + // check-inst: [[POINTER:%[0-9a-z]+]] = bitcast i32* %d to i8* + // check-inst: call void @__typeart_alloc_stack(i8* [[POINTER]], i32 2, i64 1) // check-inst-not: __typeart_alloc_stack_omp int d = 3; int e = 4; diff --git a/test/pass/filter/14_omp_nested.c b/test/pass/filter/14_omp_nested.c index bcc922ed..dc86bb65 100644 --- a/test/pass/filter/14_omp_nested.c +++ b/test/pass/filter/14_omp_nested.c @@ -1,9 +1,9 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst // REQUIRES: openmp // clang-format on extern void MPI_call(void*); diff --git a/test/pass/filter/15_omp_task.c b/test/pass/filter/15_omp_task.c index e5973f16..b79f4e82 100644 --- a/test/pass/filter/15_omp_task.c +++ b/test/pass/filter/15_omp_task.c @@ -1,8 +1,8 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s --check-prefix=CHECK-opt +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s --check-prefix=CHECK-opt -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst // REQUIRES: openmp // clang-format on extern void MPI_call(void*); diff --git a/test/pass/filter/16_omp_reduction.c b/test/pass/filter/16_omp_reduction.c index 6341ce22..1630f271 100644 --- a/test/pass/filter/16_omp_reduction.c +++ b/test/pass/filter/16_omp_reduction.c @@ -1,9 +1,9 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst // REQUIRES: openmp // clang-format on @@ -23,10 +23,10 @@ void foo() { float array[n] = {0}; // check-inst: define {{.*}} @foo // check-inst: %loc = alloca - // check-inst: %0 = bitcast float* %loc to i8* - // check-inst: call void @__typeart_alloc_stack(i8* %0, i32 5, i64 1) + // check-inst: [[POINTER:%[0-9a-z]+]] = bitcast float* %loc to i8* + // check-inst: call void @__typeart_alloc_stack(i8* [[POINTER]], i32 5, i64 1) // check-inst-not: __typeart_alloc_stack_omp - float loc = sum(array, n); + float loc = sum(array, n); MPI_send((void*)&loc); } diff --git a/test/pass/filter/17_omp_sharing_semantics.c b/test/pass/filter/17_omp_sharing_semantics.c index 66d4113c..3559b678 100644 --- a/test/pass/filter/17_omp_sharing_semantics.c +++ b/test/pass/filter/17_omp_sharing_semantics.c @@ -1,9 +1,9 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst // REQUIRES: openmp // clang-format on @@ -19,8 +19,8 @@ void foo(int count) { int e = 4; // check-inst: define {{.*}} @.omp_outlined // check-inst: %d.addr = alloca i64, align 8 - // check-inst-NEXT: %0 = bitcast i64* %d.addr to i8* - // check-inst-NEXT: call void @__typeart_alloc_stack_omp(i8* %0, i32 3, i64 1) + // check-inst: [[POINTER0:%[0-9a-z]+]] = bitcast i64* %d.addr to i8* + // check-inst: call void @__typeart_alloc_stack_omp(i8* [[POINTER0]], i32 3, i64 1) #pragma omp parallel for schedule(dynamic, 1) firstprivate(d) shared(e) for (int i = 0; i < count; ++i) { // Analysis should not filter d, but e... @@ -36,9 +36,9 @@ void bar(int count) { int d = 3; int e = 4; // check-inst: define {{.*}} @.omp_outlined - // check-inst: %d{{[0-9]}} = alloca i32 - // check-inst-NEXT: %0 = bitcast i32* %d{{[0-9]}} to i8* - // check-inst-NEXT: call void @__typeart_alloc_stack_omp(i8* %0, i32 2, i64 1) + // check-inst: [[ALLOCA1:%d[0-9]]] = alloca i32 + // check-inst: [[POINTER1:%[0-9a-z]+]] = bitcast i32* [[ALLOCA1]] to i8* + // check-inst: call void @__typeart_alloc_stack_omp(i8* [[POINTER1]], i32 2, i64 1) #pragma omp parallel for schedule(dynamic, 1) lastprivate(d) shared(e) for (int i = 0; i < count; ++i) { // Analysis should not filter d, but e... @@ -49,14 +49,14 @@ void bar(int count) { void bar2(int count) { // check-inst: define {{.*}} @bar2 // check-inst: %d = alloca - // check-inst-NEXT: %0 = bitcast i32* %d to i8* - // check-inst-NEXT: call void @__typeart_alloc_stack(i8* %0, i32 2, i64 1) + // check-inst: [[POINTER2:%[0-9a-z]+]] = bitcast i32* %d to i8* + // check-inst: call void @__typeart_alloc_stack(i8* [[POINTER2]], i32 2, i64 1) int d = 3; int e = 4; // check-inst: define {{.*}} @.omp_outlined - // check-inst: %d{{[0-9]}} = alloca i32 - // check-inst-NEXT: %0 = bitcast i32* %d{{[0-9]}} to i8* - // check-inst-NEXT: call void @__typeart_alloc_stack_omp(i8* %0, i32 2, i64 1) + // check-inst: [[ALLOCA3:%d[0-9]]] = alloca i32 + // check-inst: [[POINTER3:%[0-9a-z]+]] = bitcast i32* [[ALLOCA3]] to i8* + // check-inst: call void @__typeart_alloc_stack_omp(i8* [[POINTER3]], i32 2, i64 1) #pragma omp parallel for schedule(dynamic, 1) lastprivate(d) shared(e) for (int i = 0; i < count; ++i) { // Analysis should not filter d, but e... @@ -67,15 +67,15 @@ void bar2(int count) { } void foo_bar(int count) { - // private: d, e are "randomly" initialised values inside outlined region (outer d,e are not passed) + // private: d, e are "randomly" initialized values inside outlined region (outer d,e are not passed) // check-inst: define {{.*}} @foo_bar // check-inst-NOT: call void @__typeart_alloc_stack int d = 3; int e = 4; // check-inst: define {{.*}} @.omp_outlined // check-inst: %d = alloca - // check-inst-NEXT: %0 = bitcast i32* %d to i8* - // check-inst-NEXT: call void @__typeart_alloc_stack_omp(i8* %0, i32 2, i64 1) + // check-inst: [[POINTER4:%[0-9a-z]+]] = bitcast i32* %d to i8* + // check-inst: call void @__typeart_alloc_stack_omp(i8* [[POINTER4]], i32 2, i64 1) #pragma omp parallel for schedule(dynamic, 1) private(d, e) for (int i = 0; i < count; ++i) { MPI_Send((void*)&d, e); diff --git a/test/pass/filter/18_omp_last_priv_nested.c b/test/pass/filter/18_omp_last_priv_nested.c index 1c44b887..0c8426d7 100644 --- a/test/pass/filter/18_omp_last_priv_nested.c +++ b/test/pass/filter/18_omp_last_priv_nested.c @@ -1,7 +1,7 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst // REQUIRES: openmp // clang-format on @@ -19,7 +19,7 @@ void func(int* x, int* e) { // , and "int x=1;" is thus not tracked. // check-inst: define {{.*}} @func // check-inst: define {{.*}} @.omp_outlined - // check-inst: call void @__typeart_alloc_stack_omp(i8* %0, i32 10, i64 1) + // check-inst: call void @__typeart_alloc_stack_omp(i8* %{{[0-9]}}, i32 10, i64 1) #pragma omp parallel for lastprivate(x), shared(e) for (int i = 0; i < 10; ++i) { // Analysis should not filter x, but e... @@ -40,7 +40,7 @@ void func_other(int* x, int* e) { // lastprivate - addr(!) value of x is copied to "private_val" (which is tracked) in outlined region // check-inst: define {{.*}} @func_other // check-inst: define {{.*}} @.omp_outlined - // check-inst: call void @__typeart_alloc_stack_omp(i8* %0, i32 10, i64 1) + // check-inst: call void @__typeart_alloc_stack_omp(i8* %{{[0-9]}}, i32 10, i64 1) #pragma omp parallel for lastprivate(x), shared(e) for (int i = 0; i < 10; ++i) { // Analysis should not filter x, but e... @@ -51,7 +51,7 @@ void func_other(int* x, int* e) { void bar(int x_other) { // check-inst: define {{.*}} @bar - // check-inst: call void @__typeart_alloc_stack(i8* %0, i32 2, i64 1) + // check-inst: call void @__typeart_alloc_stack(i8* %{{[0-9]}}, i32 2, i64 1) int x = x_other; int y = 2; #pragma omp parallel diff --git a/test/pass/filter/19_omp_first_priv_nested.c b/test/pass/filter/19_omp_first_priv_nested.c index 5eedfc57..0ea8ac40 100644 --- a/test/pass/filter/19_omp_first_priv_nested.c +++ b/test/pass/filter/19_omp_first_priv_nested.c @@ -1,9 +1,9 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst // REQUIRES: openmp // clang-format on diff --git a/test/pass/filter/20_omp_priv_combi_nested.c b/test/pass/filter/20_omp_priv_combi_nested.c index 50ffdf39..94357434 100644 --- a/test/pass/filter/20_omp_priv_combi_nested.c +++ b/test/pass/filter/20_omp_priv_combi_nested.c @@ -1,9 +1,9 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=check-opt +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s --check-prefix=check-opt -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-opt-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -typeart-filter-pointer-alloca=false -S | %filecheck %s --check-prefix=check-opt-inst // REQUIRES: openmp // clang-format on @@ -22,7 +22,7 @@ void func(int* x, int* e) { // check-opt-inst-NOT: call void @__typeart_alloc_stack // check-inst: define {{.*}} @.omp_outlined - // check-inst: call void @__typeart_alloc_stack_omp(i8* %0, i32 10, i64 1) + // check-inst: call void @__typeart_alloc_stack_omp(i8* %{{[0-9]}}, i32 10, i64 1) // check-opt-inst: define {{.*}} @.omp_outlined // check-opt-inst-NOT: call void @__typeart_alloc_stack_omp @@ -53,7 +53,7 @@ void func_other(int* x, int* e) { // check-opt-inst-NOT: call void @__typeart_alloc_stack // check-inst: define {{.*}} @.omp_outlined - // check-inst: call void @__typeart_alloc_stack_omp(i8* %0, i32 10, i64 1) + // check-inst: call void @__typeart_alloc_stack_omp(i8* %{{[0-9]}}, i32 10, i64 1) // check-opt-inst: define {{.*}} @.omp_outlined // check-opt-inst-NOT: call void @__typeart_alloc_stack_omp @@ -67,10 +67,10 @@ void func_other(int* x, int* e) { void bar(int x_other) { // check-inst: define {{.*}} @bar - // check-inst: call void @__typeart_alloc_stack(i8* %0, i32 2, i64 1) + // check-inst: call void @__typeart_alloc_stack(i8* %{{[0-9]}}, i32 2, i64 1) // check-opt-inst: define {{.*}} @bar - // check-opt-inst: call void @__typeart_alloc_stack(i8* %0, i32 2, i64 1) + // check-opt-inst: call void @__typeart_alloc_stack(i8* %{{[0-9]}}, i32 2, i64 1) int x = x_other; int y = 2; #pragma omp parallel diff --git a/test/pass/filter/21_omp_task_struct.c b/test/pass/filter/21_omp_task_struct.c index 2da0fe3c..fd9a3ed5 100644 --- a/test/pass/filter/21_omp_task_struct.c +++ b/test/pass/filter/21_omp_task_struct.c @@ -1,9 +1,9 @@ // clang-format off -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s --check-prefix=CHECK-opt +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s --check-prefix=CHECK-opt -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst -// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-alloca -call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst +// RUN: %c-to-llvm -fno-discard-value-names %omp_c_flags %s | %opt -O2 -S | %apply-typeart -typeart-stack -typeart-call-filter -S | %filecheck %s --check-prefix=check-inst // REQUIRES: openmp // clang-format on extern void MPI_call(void*); diff --git a/test/pass/filter/22_omp_ident_offset.llin b/test/pass/filter/22_omp_ident_offset.llin index 2d254712..a63e992d 100644 --- a/test/pass/filter/22_omp_ident_offset.llin +++ b/test/pass/filter/22_omp_ident_offset.llin @@ -1,4 +1,4 @@ -; RUN: cat %s | %apply-typeart -typeart-alloca -call-filter -S 2>&1 | %filecheck %s +; RUN: cat %s | %apply-typeart -typeart-stack -typeart-call-filter -S 2>&1 | %filecheck %s %struct.ident_t = type { i32, i32, i32, i32, i8* } @@ -23,8 +23,8 @@ define dso_local void @foo() #0 { entry: ; TEST: the translation to fork_call(%s, %outlined, ...) -> outlined should handle the internal struct.ident_t %s arg when following dataflow ; CHECK: @foo() -; CHECK: %0 = bitcast i32* %x to i8* -; CHECK-NEXT: call void @__typeart_alloc_stack(i8* %0, i32 2, i64 1) +; CHECK: [[POINTER:%[0-9a-z]+]] = bitcast i32* %x to i8* +; CHECK: call void @__typeart_alloc_stack(i8* [[POINTER]], i32 2, i64 1) %x = alloca i32, align 4 %0 = bitcast i32* %x to i8* %s = alloca %struct.ident_t, align 8 diff --git a/test/pass/filter/23_pointer_alloca.c b/test/pass/filter/23_pointer_alloca.c index d6674dad..492fe197 100644 --- a/test/pass/filter/23_pointer_alloca.c +++ b/test/pass/filter/23_pointer_alloca.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -typeart-filter-pointer-alloca=true -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-filter-pointer-alloca=true -S 2>&1 | %filecheck %s // clang-format on int main(int argc, char** argv) { diff --git a/test/pass/global/01_globals.c b/test/pass/global/01_globals.c index aa9858ff..38544e98 100644 --- a/test/pass/global/01_globals.c +++ b/test/pass/global/01_globals.c @@ -1,4 +1,4 @@ -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-global -S 2>&1 | %filecheck %s int global; int global_2 = 0; diff --git a/test/pass/global/02_globals.cpp b/test/pass/global/02_globals.cpp index aa9e63b7..cc740ad5 100644 --- a/test/pass/global/02_globals.cpp +++ b/test/pass/global/02_globals.cpp @@ -1,4 +1,4 @@ -// RUN: %cpp-to-llvm %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart -typeart-global -S 2>&1 | %filecheck %s int global; int global_2 = 0; diff --git a/test/pass/global/03_milc_setup_readin_mock.llin b/test/pass/global/03_milc_setup_readin_mock.llin index aa56a989..c4000923 100644 --- a/test/pass/global/03_milc_setup_readin_mock.llin +++ b/test/pass/global/03_milc_setup_readin_mock.llin @@ -1,4 +1,4 @@ -; RUN: cat %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +; RUN: cat %s | %apply-typeart -typeart-global -S 2>&1 | %filecheck %s ; CHECK: call void @__typeart_alloc_global(i8* bitcast (%struct.params* @par_buf to i8*) diff --git a/test/pass/global/04_const_char.c b/test/pass/global/04_const_char.c index e98215ab..1bc8cfc0 100644 --- a/test/pass/global/04_const_char.c +++ b/test/pass/global/04_const_char.c @@ -1,4 +1,4 @@ -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-global -S 2>&1 | %filecheck %s void bar(const void*); diff --git a/test/pass/global/05_asan.c b/test/pass/global/05_asan.c index 82bd9c17..040bae3d 100644 --- a/test/pass/global/05_asan.c +++ b/test/pass/global/05_asan.c @@ -1,4 +1,4 @@ -// RUN: %c-to-llvm %s -fsanitize=address | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s -fsanitize=address | %apply-typeart -typeart-global -S 2>&1 | %filecheck %s // REQUIRES: asan diff --git a/test/pass/global/06_coverage.c b/test/pass/global/06_coverage.c index d30286a5..94e6644c 100644 --- a/test/pass/global/06_coverage.c +++ b/test/pass/global/06_coverage.c @@ -1,4 +1,4 @@ -// RUN: %c-to-llvm --coverage %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm --coverage %s | %apply-typeart -typeart-global -S 2>&1 | %filecheck %s int global; int global_2 = 0; diff --git a/test/pass/global/07_coverage_llvm.c b/test/pass/global/07_coverage_llvm.c index bd32c320..83155ab1 100644 --- a/test/pass/global/07_coverage_llvm.c +++ b/test/pass/global/07_coverage_llvm.c @@ -1,4 +1,4 @@ -// RUN: %c-to-llvm -fprofile-instr-generate -fcoverage-mapping %s | %apply-typeart -typeart-alloca -S 2>&1 \ +// RUN: %c-to-llvm -fprofile-instr-generate -fcoverage-mapping %s | %apply-typeart -typeart-global -S 2>&1 \ // RUN: | %filecheck %s int global; diff --git a/test/pass/global/08_global_skip.c b/test/pass/global/08_global_skip.c new file mode 100644 index 00000000..66a041eb --- /dev/null +++ b/test/pass/global/08_global_skip.c @@ -0,0 +1,28 @@ +// RUN: %c-to-llvm %s | %apply-typeart -typeart-global -S 2>&1 | %filecheck %s + +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-global=false -S 2>&1 \ +// RUN: | %filecheck %s --check-prefix CHECK-SKIP + +int global; +int global_2 = 0; +extern int global_3; +extern int global_4; +static int global_5; +static int global_6 = 0; + +extern void bar(int*); + +void foo() { + int non_glob_x = 1; + bar(&global); + bar(&global_2); + bar(&global_3); +} + +// CHECK: void @__typeart_init_module_ +// CHECK-NEXT: entry: +// CHECK-DAG: call void @__typeart_alloc_global(i8* bitcast (i32* @global to i8*) +// CHECK-DAG: call void @__typeart_alloc_global(i8* bitcast (i32* @global_2 to i8*) +// CHECK: ret void + +// CHECK-SKIP-NOT: void @__typeart_init_module_ diff --git a/test/pass/malloc_free/02_simple_malloc_free_int.c b/test/pass/malloc_free/02_simple_malloc_free_int.c index 1c65b8b4..6a4bc175 100644 --- a/test/pass/malloc_free/02_simple_malloc_free_int.c +++ b/test/pass/malloc_free/02_simple_malloc_free_int.c @@ -12,7 +12,7 @@ void test() { // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], // CHECK-NEXT: bitcast i8* [[POINTER]] to i32* -// CHECK: call void @free(i8* [[POINTER:%[0-9a-z]+]]) +// CHECK: call void @free(i8*{{( noundef)?}} [[POINTER:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* [[POINTER]]) // CHECK: TypeArtPass [Heap] diff --git a/test/pass/malloc_free/03_simple_malloc_free_double.c b/test/pass/malloc_free/03_simple_malloc_free_double.c index ba1a33ae..feb8e98b 100644 --- a/test/pass/malloc_free/03_simple_malloc_free_double.c +++ b/test/pass/malloc_free/03_simple_malloc_free_double.c @@ -11,7 +11,7 @@ void test() { // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 6, i64 42) // CHECK-NEXT: bitcast i8* [[POINTER]] to double* -// CHECK: call void @free(i8* [[POINTER:%[0-9a-z]+]]) +// CHECK: call void @free(i8*{{( noundef)?}} [[POINTER:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* [[POINTER]]) // CHECK: TypeArtPass [Heap] diff --git a/test/pass/malloc_free/05_simple_malloc_struct.c b/test/pass/malloc_free/05_simple_malloc_struct.c index 55b2df36..18463e0d 100644 --- a/test/pass/malloc_free/05_simple_malloc_struct.c +++ b/test/pass/malloc_free/05_simple_malloc_struct.c @@ -16,7 +16,7 @@ void test() { // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 256, i64 1) // CHECK-NEXT: bitcast i8* [[POINTER]] to %struct.ms* -// CHECK: call void @free(i8* [[POINTER:%[0-9a-z]+]]) +// CHECK: call void @free(i8*{{( noundef)?}} [[POINTER:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* [[POINTER]]) // CHECK: TypeArtPass [Heap] diff --git a/test/pass/malloc_free/07_simple_malloc_free_void_type.c b/test/pass/malloc_free/07_simple_malloc_free_void_type.c index db8de13f..6329395a 100644 --- a/test/pass/malloc_free/07_simple_malloc_free_void_type.c +++ b/test/pass/malloc_free/07_simple_malloc_free_void_type.c @@ -12,7 +12,7 @@ void test() { // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], // CHECK-NOT: bitcast i8* [[POINTER]] to i32* -// CHECK: call void @free(i8* [[POINTER:%[0-9a-z]+]]) +// CHECK: call void @free(i8*{{( noundef)?}} [[POINTER:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* [[POINTER]]) // PASS-OUT: TypeArtPass [Heap] diff --git a/test/pass/malloc_free/08_simple_malloc_struct_void.c b/test/pass/malloc_free/08_simple_malloc_struct_void.c index ffec58c9..be40bdbe 100644 --- a/test/pass/malloc_free/08_simple_malloc_struct_void.c +++ b/test/pass/malloc_free/08_simple_malloc_struct_void.c @@ -17,7 +17,7 @@ void test() { // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 0, i64 16) // CHECK-NOT: bitcast i8* [[POINTER]] to i32* -// CHECK: call void @free(i8* [[POINTER:%[0-9a-z]+]]) +// CHECK: call void @free(i8*{{( noundef)?}} [[POINTER:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* [[POINTER]]) // PASS-OUT: TypeArtPass [Heap] diff --git a/test/pass/malloc_free/09_malloc_with_disjunct_free.c b/test/pass/malloc_free/09_malloc_with_disjunct_free.c index c92ae469..f6450be5 100644 --- a/test/pass/malloc_free/09_malloc_with_disjunct_free.c +++ b/test/pass/malloc_free/09_malloc_with_disjunct_free.c @@ -19,7 +19,7 @@ void foo(double* ptr) { // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], // CHECK-NEXT: bitcast i8* [[POINTER]] to double* -// CHECK: call void @free(i8* [[POINTER:%[0-9a-z]+]]) +// CHECK: call void @free(i8*{{( noundef)?}} [[POINTER:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* [[POINTER]]) // CHECK: TypeArtPass [Heap] diff --git a/test/pass/malloc_free/11_calloc_realloc.c b/test/pass/malloc_free/11_calloc_realloc.c index 52432fc2..ae59ca04 100644 --- a/test/pass/malloc_free/11_calloc_realloc.c +++ b/test/pass/malloc_free/11_calloc_realloc.c @@ -12,15 +12,19 @@ int main() { return 0; } -// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @calloc(i64 [[SIZE:[0-9]+]], i64 8) +// clang-format off + +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @calloc(i64{{( noundef)?}} [[SIZE:[0-9]+]], i64{{( noundef)?}} 8) // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 6, i64 [[SIZE]]) // CHECK-NEXT: bitcast i8* [[POINTER]] to double* // REALLOC: __typeart_free(i8* [[POINTER:%[0-9a-z]+]]) -// REALLOC-NEXT: [[POINTER2:%[0-9a-z]+]] = call{{( align [0-9]+)?}} i8* @realloc(i8* [[POINTER]], i64 160) +// REALLOC-NEXT: [[POINTER2:%[0-9a-z]+]] = call{{( align [0-9]+)?}} i8* @realloc(i8*{{( noundef)?}} [[POINTER]], i64{{( noundef)?}} 160) // REALLOC-NEXT: __typeart_alloc(i8* [[POINTER2]], i32 6, i64 20) // CHECK: TypeArtPass [Heap] // CHECK-NEXT: Malloc{{[ ]*}}:{{[ ]*}}2 // CHECK-NEXT: Free{{[ ]*}}:{{[ ]*}}0 // CHECK-NEXT: Alloca{{[ ]*}}:{{[ ]*}}0 + +// clang-format on diff --git a/test/pass/malloc_free/13_calloc_void_type.c b/test/pass/malloc_free/13_calloc_void_type.c index 2fe5a9c6..1b08d561 100644 --- a/test/pass/malloc_free/13_calloc_void_type.c +++ b/test/pass/malloc_free/13_calloc_void_type.c @@ -9,10 +9,14 @@ void foo(int n) { void* pvd2 = calloc(n, sizeof(double)); } -// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @calloc(i64 [[SIZE:[0-9a-z]+]], i64 8) +// clang-format off + +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @calloc(i64{{( noundef)?}} [[SIZE:[0-9a-z]+]], i64{{( noundef)?}} 8) // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 0, i64 80) // CHECK-NOT: bitcast i8* [[POINTER]] to double* -// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @calloc(i64 [[SIZE2:%[0-9a-z]+]], i64 8) +// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @calloc(i64{{( noundef)?}} [[SIZE2:%[0-9a-z]+]], i64{{( noundef)?}} 8) // CHECK-NOT: call void @__typeart_alloc(i8* [[POINTER2]], i32 0, i64 [[SIZE2]]) -// CHECK-NOT: bitcast i8* [[POINTER]] to double* \ No newline at end of file +// CHECK-NOT: bitcast i8* [[POINTER]] to double* + +// clang-format on diff --git a/test/pass/malloc_free/14_aligned_alloc.c b/test/pass/malloc_free/14_aligned_alloc.c index 0bd74b2b..c125af5e 100644 --- a/test/pass/malloc_free/14_aligned_alloc.c +++ b/test/pass/malloc_free/14_aligned_alloc.c @@ -10,11 +10,11 @@ void foo(int n) { } // clang-format off -// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @aligned_alloc(i64 64, i64 20) +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @aligned_alloc(i64{{( noundef)?}} 64, i64{{( noundef)?}} 20) // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 2, i64 5) // CHECK-NEXT: bitcast i8* [[POINTER]] to i32* -// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @aligned_alloc(i64 128, i64 [[SIZE:%[0-9a-z]+]]) +// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @aligned_alloc(i64{{( noundef)?}} 128, i64{{( noundef)?}} [[SIZE:%[0-9a-z]+]]) // CHECK-NOT: call void @__typeart_alloc(i8* [[POINTER2]], i32 2, i64 [[SIZE]]) // CHECK: call void @__typeart_alloc(i8* [[POINTER2]], i32 2, i64 %{{[0-9a-z]+}}) // CHECK-NEXT: bitcast i8* [[POINTER2]] to i32* diff --git a/test/pass/malloc_free/15_aligned_alloc_void_type.c b/test/pass/malloc_free/15_aligned_alloc_void_type.c index cb5f746a..b55f2a63 100644 --- a/test/pass/malloc_free/15_aligned_alloc_void_type.c +++ b/test/pass/malloc_free/15_aligned_alloc_void_type.c @@ -10,11 +10,11 @@ void foo(int n) { } // clang-format off -// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @aligned_alloc(i64 64, i64 20) +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @aligned_alloc(i64{{( noundef)?}} 64, i64{{( noundef)?}} 20) // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 0, i64 20) // CHECK-NOT: bitcast i8* [[POINTER]] to {{.*}}* -// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @aligned_alloc(i64 128, i64 [[SIZE:%[0-9a-z]+]]) +// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @aligned_alloc(i64{{( noundef)?}} 128, i64{{( noundef)?}} [[SIZE:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER2]], i32 0, i64 [[SIZE]]) // CHECK-NOT: bitcast i8* [[POINTER]] to {{.*}}* // clang-format on diff --git a/test/pass/malloc_free/16_omp_heap.c b/test/pass/malloc_free/16_omp_heap.c index 4bc24329..f0787758 100644 --- a/test/pass/malloc_free/16_omp_heap.c +++ b/test/pass/malloc_free/16_omp_heap.c @@ -18,13 +18,14 @@ void foo(int** x) { free(x[i]); } } +// clang-format off -// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @calloc(i64 [[SIZE:[0-9a-z]+]], i64 8) +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @calloc(i64{{( noundef)?}} [[SIZE:[0-9a-z]+]], i64{{( noundef)?}} 8) // CHECK-NEXT: call void @__typeart_alloc_omp(i8* [[POINTER]], i32 6, i64 [[SIZE]]) // CHECK-NEXT: bitcast i8* [[POINTER]] to double* // CHECK: __typeart_free_omp(i8* [[POINTER:%[0-9a-z]+]]) -// CHECK-NEXT: [[POINTER2:%[0-9a-z]+]] = call{{( align [0-9]+)?}} i8* @realloc(i8* [[POINTER]], i64 160) +// CHECK-NEXT: [[POINTER2:%[0-9a-z]+]] = call{{( align [0-9]+)?}} i8* @realloc(i8*{{( noundef)?}} [[POINTER]], i64{{( noundef)?}} 160) // CHECK-NEXT: __typeart_alloc_omp(i8* [[POINTER2]], i32 6, i64 20) // CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} i8* @malloc @@ -37,4 +38,6 @@ void foo(int** x) { // CHECK: TypeArtPass [Heap] // CHECK-NEXT: Malloc{{[ ]*}}:{{[ ]*}}3 // CHECK-NEXT: Free{{[ ]*}}:{{[ ]*}}1 -// CHECK-NEXT: Alloca{{[ ]*}}:{{[ ]*}}0 \ No newline at end of file +// CHECK-NEXT: Alloca{{[ ]*}}:{{[ ]*}}0 + +// clang-format on \ No newline at end of file diff --git a/test/pass/misc/01_MemInstFinder_Args.c b/test/pass/misc/01_MemInstFinder_Args.c index 4b886aa2..2554458a 100644 --- a/test/pass/misc/01_MemInstFinder_Args.c +++ b/test/pass/misc/01_MemInstFinder_Args.c @@ -1,15 +1,14 @@ // clang-format off // Sanity check for arg names // RUN: %c-to-llvm %s | %opt -load %transform_pass -typeart \ -// RUN: -call-filter \ -// RUN: -call-filter-impl=empty \ -// RUN: -call-filter-str=MPI1 \ -// RUN: -call-filter-deep-str=MPI2 \ -// RUN: -call-filter-cg-file=/foo/file.cg \ -// RUN: -call-filter-deep=true \ -// RUN: -alloca-array-only=true \ -// RUN: -malloc-store-filter=true \ -// RUN: -filter-globals=true \ +// RUN: -typeart-call-filter \ +// RUN: -typeart-call-filter-impl=none \ +// RUN: -typeart-call-filter-str=MPI1 \ +// RUN: -typeart-call-filter-deep-str=MPI2 \ +// RUN: -typeart-call-filter-cg-file=/foo/file.cg \ +// RUN: -typeart-stack-array-only=true \ +// RUN: -typeart-malloc-store-filter=true \ +// RUN: -typeart-filter-globals=true \ // RUN: -typeart-filter-pointer-alloca=false // clang-format on diff --git a/test/pass/misc/02_TypeArtPass_Args.c b/test/pass/misc/02_TypeArtPass_Args.c index d05896b9..48996e62 100644 --- a/test/pass/misc/02_TypeArtPass_Args.c +++ b/test/pass/misc/02_TypeArtPass_Args.c @@ -2,9 +2,10 @@ // Sanity check for arg names // RUN: %c-to-llvm %s | %opt -load %transform_pass -typeart \ // RUN: -typeart-stats \ -// RUN: -typeart-no-heap=false \ -// RUN: -typeart-alloca=true \ -// RUN: -typeart-outfile=typeart_types.yaml +// RUN: -typeart-heap=true \ +// RUN: -typeart-stack=true \ +// RUN: -typeart-global=false \ +// RUN: -typeart-types=typeart_types.yaml // clang-format on void foo() { diff --git a/test/pass/misc/03_make_mismatch_callback.c b/test/pass/misc/03_make_mismatch_callback.c index 93b1e86e..ff684d86 100644 --- a/test/pass/misc/03_make_mismatch_callback.c +++ b/test/pass/misc/03_make_mismatch_callback.c @@ -1,4 +1,4 @@ -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -S 2>&1 | %filecheck %s // XFAIL: * #include diff --git a/test/pass/misc/04_make_callback_match.c b/test/pass/misc/04_make_callback_match.c index 6a01f9f9..95a82450 100644 --- a/test/pass/misc/04_make_callback_match.c +++ b/test/pass/misc/04_make_callback_match.c @@ -1,4 +1,4 @@ -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -S 2>&1 | %filecheck %s void __typeart_leave_scope(int alloca_count); diff --git a/test/pass/misc/05_make_all_callbacks.c b/test/pass/misc/05_make_all_callbacks.c index ff1426ed..29064b16 100644 --- a/test/pass/misc/05_make_all_callbacks.c +++ b/test/pass/misc/05_make_all_callbacks.c @@ -1,4 +1,4 @@ -// RUN: %c-to-llvm %s | %apply-typeart -typeart-alloca -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -S 2>&1 | %filecheck %s #include "../../../lib/runtime/CallbackInterface.h" diff --git a/test/pass/misc/06_unknown_type.llin b/test/pass/misc/06_unknown_type.llin index 9e01de88..e0b4538f 100644 --- a/test/pass/misc/06_unknown_type.llin +++ b/test/pass/misc/06_unknown_type.llin @@ -1,4 +1,4 @@ -; RUN: cat %s | %apply-typeart -typeart-alloca -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s +; RUN: cat %s | %apply-typeart -typeart-stack -typeart-filter-pointer-alloca=false -S 2>&1 | %filecheck %s define dso_local i32 @main() #0 { ; CHECK: [Error]{{.*}}Target type of casted allocation is unknown. Not instrumenting.{{.*}}%3 = call noalias i8* @malloc(i64 12) diff --git a/test/pass/new_delete/01_inv_simple_new_int.cpp b/test/pass/new_delete/01_inv_simple_new_int.cpp index 0afedb78..64f2c9e3 100644 --- a/test/pass/new_delete/01_inv_simple_new_int.cpp +++ b/test/pass/new_delete/01_inv_simple_new_int.cpp @@ -3,7 +3,7 @@ // clang-format on #include -// CHECK: invoke{{.*}} i8* @_Znwm(i64 4) +// CHECK: invoke{{.*}} i8* @_Znwm(i64{{( noundef)?}} 4) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 2, i64 1) // CHECK-NEXT: bitcast i8* {{.*}}[[POINTER]] to i32* int main() { diff --git a/test/pass/new_delete/02_inv_simple_int_array.cpp b/test/pass/new_delete/02_inv_simple_int_array.cpp index 960ba2e0..ee79e6bc 100644 --- a/test/pass/new_delete/02_inv_simple_int_array.cpp +++ b/test/pass/new_delete/02_inv_simple_int_array.cpp @@ -3,7 +3,7 @@ // clang-format on #include -// CHECK: invoke{{.*}} i8* @_Znam(i64 8) +// CHECK: invoke{{.*}} i8* @_Znam(i64{{( noundef)?}} 8) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 2, i64 2) // CHECK-NEXT: bitcast i8* {{.*}}[[POINTER]] to i32* int main() { diff --git a/test/pass/new_delete/03_inv_struct.cpp b/test/pass/new_delete/03_inv_struct.cpp index 0ea9218d..1216cd47 100644 --- a/test/pass/new_delete/03_inv_struct.cpp +++ b/test/pass/new_delete/03_inv_struct.cpp @@ -9,7 +9,7 @@ struct S1 { virtual ~S1() = default; }; -// CHECK: invoke{{.*}} i8* @_Znwm(i64 16) +// CHECK: invoke{{.*}} i8* @_Znwm(i64{{( noundef)?}} 16) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 {{2[0-9]+}}, i64 1) // CHECK: bitcast i8* [[POINTER]] to %struct.S1* int main() { diff --git a/test/pass/new_delete/04_inv_struct_array.cpp b/test/pass/new_delete/04_inv_struct_array.cpp index 9a260a9d..1d7b3a8a 100644 --- a/test/pass/new_delete/04_inv_struct_array.cpp +++ b/test/pass/new_delete/04_inv_struct_array.cpp @@ -9,7 +9,7 @@ struct S1 { virtual ~S1() = default; }; -// CHECK: invoke{{.*}} i8* @_Znam(i64 40) +// CHECK: invoke{{.*}} i8* @_Znam(i64{{( noundef)?}} 40) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 {{2[5-9][0-9]}}, i64 2) // CHECK: bitcast i8* [[POINTER]] to %struct.S1* int main() { diff --git a/test/pass/new_delete/05_struct_array.cpp b/test/pass/new_delete/05_struct_array.cpp index 29b6a5a2..a295500e 100644 --- a/test/pass/new_delete/05_struct_array.cpp +++ b/test/pass/new_delete/05_struct_array.cpp @@ -6,7 +6,7 @@ struct S1 { int x; }; -// CHECK: call{{.*}} i8* @_Znam(i64 8) +// CHECK: call{{.*}} i8* @_Znam(i64{{( noundef)?}} 8) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 {{2[0-9]+}}, i64 2) // CHECK: bitcast i8* [[POINTER]] to %struct.S1* int main() { diff --git a/test/pass/new_delete/06_struct_array_def_dest.cpp b/test/pass/new_delete/06_struct_array_def_dest.cpp index afb8ba1c..89077c1d 100644 --- a/test/pass/new_delete/06_struct_array_def_dest.cpp +++ b/test/pass/new_delete/06_struct_array_def_dest.cpp @@ -7,7 +7,7 @@ struct S1 { ~S1() = default; }; -// CHECK: call{{.*}} i8* @_Znam(i64 8) +// CHECK: call{{.*}} i8* @_Znam(i64{{( noundef)?}} 8) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 {{2[0-9]+}}, i64 2) // CHECK: bitcast i8* [[POINTER]] to %struct.S1* int main() { diff --git a/test/pass/new_delete/07_struct_array_userdef_dest.cpp b/test/pass/new_delete/07_struct_array_userdef_dest.cpp index 4d237c56..cd8962df 100644 --- a/test/pass/new_delete/07_struct_array_userdef_dest.cpp +++ b/test/pass/new_delete/07_struct_array_userdef_dest.cpp @@ -9,7 +9,7 @@ struct S1 { ~S1(){}; }; -// CHECK: call i8* @_Znam(i64 8) +// CHECK: call i8* @_Znam(i64{{( noundef)?}} 8) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 {{2[0-9]+}}, i64 2) // CHECK: bitcast i8* [[POINTER]] to %struct.S1* int main() { diff --git a/test/pass/new_delete/08_inv_double_array_delete.cpp b/test/pass/new_delete/08_inv_double_array_delete.cpp index f0920ffe..ed8d721c 100644 --- a/test/pass/new_delete/08_inv_double_array_delete.cpp +++ b/test/pass/new_delete/08_inv_double_array_delete.cpp @@ -3,10 +3,10 @@ // clang-format on #include -// CHECK: invoke{{.*}} i8* @_Znam(i64 16) +// CHECK: invoke{{.*}} i8* @_Znam(i64{{( noundef)?}} 16) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 6, i64 2) // CHECK-NEXT: bitcast i8* {{.*}}[[POINTER]] to double* -// CHECK: call void @_ZdaPv(i8* [[POINTER2:%[0-9a-z]+]]) +// CHECK: call void @_ZdaPv(i8*{{( noundef)?}} [[POINTER2:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* {{.*}}[[POINTER2]]) int main() { try { @@ -18,10 +18,10 @@ int main() { return 0; } -// CHECK: invoke{{.*}} i8* @_Znam(i64 16) +// CHECK: invoke{{.*}} i8* @_Znam(i64{{( noundef)?}} 16) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 6, i64 2) // CHECK-NEXT: bitcast i8* {{.*}}[[POINTER]] to double* -// CHECK: call void @_ZdaPv(i8* [[POINTER2:%[0-9a-z]+]]) +// CHECK: call void @_ZdaPv(i8*{{( noundef)?}} [[POINTER2:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* {{.*}}[[POINTER2]]) void foo() { double* b{nullptr}; diff --git a/test/pass/new_delete/09_inv_struct_delete.cpp b/test/pass/new_delete/09_inv_struct_delete.cpp index 3f8cbd52..0bd6a8b0 100644 --- a/test/pass/new_delete/09_inv_struct_delete.cpp +++ b/test/pass/new_delete/09_inv_struct_delete.cpp @@ -9,10 +9,10 @@ struct S1 { virtual ~S1() = default; }; -// CHECK: invoke{{.*}} i8* @_Znwm(i64 16) +// CHECK: invoke{{.*}} i8* @_Znwm(i64{{( noundef)?}} 16) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 {{2[0-9]+}}, i64 1) // CHECK: bitcast i8* [[POINTER]] to %struct.S1* -// CHECK-NOT: call void @_ZdlPv(i8* [[POINTER2:%[0-9a-z]+]]) +// CHECK-NOT: call void @_ZdlPv(i8*{{( noundef)?}} [[POINTER2:%[0-9a-z]+]]) // CHECK-NOT: call void @__typeart_free(i8* {{.*}}[[POINTER2]]) void foo() { S1* b{nullptr}; @@ -25,10 +25,10 @@ void foo() { } } -// CHECK: invoke{{.*}} i8* @_Znwm(i64 16) +// CHECK: invoke{{.*}} i8* @_Znwm(i64{{( noundef)?}} 16) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 {{2[0-9]+}}, i64 1) // CHECK: bitcast i8* [[POINTER]] to %struct.S1* -// CHECK-NOT: call void @_ZdaPv(i8* [[POINTER2:%[0-9a-z]+]]) +// CHECK-NOT: call void @_ZdaPv(i8*{{( noundef)?}} [[POINTER2:%[0-9a-z]+]]) // CHECK-NOT: call void @__typeart_free(i8* {{.*}}[[POINTER2]]) int main() { try { @@ -41,7 +41,7 @@ int main() { } // CHECK: @_ZN2S1D0Ev -// CHECK: call void @_ZdlPv(i8* [[POINTER2:%[0-9a-z]+]]) +// CHECK: call void @_ZdlPv(i8*{{( noundef)?}} [[POINTER2:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* {{.*}}[[POINTER2]]) // CHECK: TypeArtPass [Heap] diff --git a/test/pass/new_delete/10_inv_struct_array_delete.cpp b/test/pass/new_delete/10_inv_struct_array_delete.cpp index b6b66e02..06dc025c 100644 --- a/test/pass/new_delete/10_inv_struct_array_delete.cpp +++ b/test/pass/new_delete/10_inv_struct_array_delete.cpp @@ -9,10 +9,10 @@ struct S1 { virtual ~S1() = default; }; -// CHECK: invoke{{.*}} i8* @_Znam(i64 56) +// CHECK: invoke{{.*}} i8* @_Znam(i64{{( noundef)?}} 56) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 {{2[0-9]+}}, i64 3) // CHECK: [[MEMORYBLOB:%[0-9a-z]+]] = getelementptr inbounds i8, i8* [[ARRPTR:%[0-9a-z]+]], i64 -8 -// CHECK: call void @_ZdaPv(i8* [[MEMORYBLOB]]) +// CHECK: call void @_ZdaPv(i8*{{( noundef)?}} [[MEMORYBLOB]]) // CHECK-NEXT: call void @__typeart_free(i8* [[ARRPTR]]) void foo() { S1* b{nullptr}; @@ -25,10 +25,10 @@ void foo() { } } -// CHECK: invoke{{.*}} i8* @_Znam(i64 40) +// CHECK: invoke{{.*}} i8* @_Znam(i64{{( noundef)?}} 40) // CHECK: call void @__typeart_alloc(i8* [[POINTER:%[0-9a-z]+]], i32 {{2[0-9]+}}, i64 2) // CHECK: [[MEMORYBLOB:%[0-9a-z]+]] = getelementptr inbounds i8, i8* [[ARRPTR:%[0-9a-z]+]], i64 -8 -// CHECK: call void @_ZdaPv(i8* [[MEMORYBLOB]]) +// CHECK: call void @_ZdaPv(i8*{{( noundef)?}} [[MEMORYBLOB]]) // CHECK-NEXT: call void @__typeart_free(i8* [[ARRPTR]]) int main() { try { @@ -41,7 +41,7 @@ int main() { } // CHECK: @_ZN2S1D0Ev -// CHECK: call void @_ZdlPv(i8* [[POINTER2:%[0-9a-z]+]]) +// CHECK: call void @_ZdlPv(i8*{{( noundef)?}} [[POINTER2:%[0-9a-z]+]]) // CHECK-NEXT: call void @__typeart_free(i8* [[POINTER2]]) // CHECK: TypeArtPass [Heap] diff --git a/test/pass/new_delete/11_new_nothrow.cpp b/test/pass/new_delete/11_new_nothrow.cpp index 25c3e4d3..a8dec1a0 100644 --- a/test/pass/new_delete/11_new_nothrow.cpp +++ b/test/pass/new_delete/11_new_nothrow.cpp @@ -16,8 +16,8 @@ C* bar() { return new (std::nothrow) C; } -// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias i8* @_ZnamRKSt9nothrow_t(i64 40, +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( noundef)?}} i8* @_ZnamRKSt9nothrow_t(i64{{( noundef)?}} 40, // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 [[ID:2[5-9][0-9]]], i64 10) -// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias i8* @_ZnwmRKSt9nothrow_t(i64 4, +// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias{{( noundef)?}} i8* @_ZnwmRKSt9nothrow_t(i64{{( noundef)?}} 4, // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER2]], i32 [[ID]], i64 1) \ No newline at end of file diff --git a/test/pass/new_delete/12_new_aligned.cpp b/test/pass/new_delete/12_new_aligned.cpp index 197f37b1..cbe82ad4 100644 --- a/test/pass/new_delete/12_new_aligned.cpp +++ b/test/pass/new_delete/12_new_aligned.cpp @@ -17,8 +17,8 @@ C* bar() { return new (std::align_val_t(128)) C; } -// CHECK: [[POINTER:%[0-9a-z]+]] = call{{.*}} i8* @_ZnamSt11align_val_t(i64 40, i64 64) +// CHECK: [[POINTER:%[0-9a-z]+]] = call{{.*}} i8* @_ZnamSt11align_val_t(i64{{( noundef)?}} 40, i64{{( noundef)?}} 64) // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 [[ID:2[5-9][0-9]]], i64 10) -// CHECK: [[POINTER2:%[0-9a-z]+]] = call{{.*}} i8* @_ZnwmSt11align_val_t(i64 4, i64 128) +// CHECK: [[POINTER2:%[0-9a-z]+]] = call{{.*}} i8* @_ZnwmSt11align_val_t(i64{{( noundef)?}} 4, i64{{( noundef)?}} 128) // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER2]], i32 [[ID]], i64 1) \ No newline at end of file diff --git a/test/pass/new_delete/13_new_aligned_nothrow.cpp b/test/pass/new_delete/13_new_aligned_nothrow.cpp index 3f64b52d..b8059481 100644 --- a/test/pass/new_delete/13_new_aligned_nothrow.cpp +++ b/test/pass/new_delete/13_new_aligned_nothrow.cpp @@ -17,8 +17,12 @@ C* bar() { return new (std::align_val_t(128), std::nothrow) C; } -// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias i8* @_ZnamSt11align_val_tRKSt9nothrow_t(i64 40, +// clang-format off + +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( noundef)?}} i8* @_ZnamSt11align_val_tRKSt9nothrow_t(i64{{( noundef)?}} 40, // CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER]], i32 [[ID:2[5-9][0-9]]], i64 10) -// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias i8* @_ZnwmSt11align_val_tRKSt9nothrow_t(i64 4, -// CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER2]], i32 [[ID]], i64 1) \ No newline at end of file +// CHECK: [[POINTER2:%[0-9a-z]+]] = call noalias{{( noundef)?}} i8* @_ZnwmSt11align_val_tRKSt9nothrow_t(i64{{( noundef)?}} 4, +// CHECK-NEXT: call void @__typeart_alloc(i8* [[POINTER2]], i32 [[ID]], i64 1) + +// clang-format on diff --git a/test/pass/new_delete/15_array_cookie.cpp b/test/pass/new_delete/15_array_cookie.cpp index 261eecd5..e843f4af 100644 --- a/test/pass/new_delete/15_array_cookie.cpp +++ b/test/pass/new_delete/15_array_cookie.cpp @@ -7,7 +7,7 @@ struct S1 { ~S1(){}; }; -// CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} i8* @_Znam(i64 16) +// CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} i8* @_Znam(i64{{( noundef)?}} 16) // CHECK: [[ARR:%[0-9a-z]+]] = getelementptr inbounds i8, i8* [[MEM]], i64 8 // CHECK: call void @__typeart_alloc(i8* [[ARR:%[0-9a-z]+]], i32 {{2[0-9]+}}, i64 2) // CHECK: bitcast i8* [[ARR]] to %struct.S1* diff --git a/test/pass/new_delete/16_array_cookie_padded.cpp b/test/pass/new_delete/16_array_cookie_padded.cpp index 0fe08935..33de75ff 100644 --- a/test/pass/new_delete/16_array_cookie_padded.cpp +++ b/test/pass/new_delete/16_array_cookie_padded.cpp @@ -7,7 +7,7 @@ struct alignas(16) S1 { ~S1(){}; }; -// CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} i8* @_Znam(i64 48) +// CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} i8* @_Znam(i64{{( noundef)?}} 48) // CHECK: [[ARR:%[0-9a-z]+]] = getelementptr inbounds i8, i8* [[MEM]], i64 16 // CHECK: call void @__typeart_alloc(i8* [[ARR]], i32 {{2[0-9]+}}, i64 2) // CHECK: bitcast i8* [[ARR]] to %struct.S1* diff --git a/test/pass/new_delete/17_array_cookie_dynamic_size.cpp b/test/pass/new_delete/17_array_cookie_dynamic_size.cpp index f8961d03..98c1ea12 100644 --- a/test/pass/new_delete/17_array_cookie_dynamic_size.cpp +++ b/test/pass/new_delete/17_array_cookie_dynamic_size.cpp @@ -7,7 +7,7 @@ struct S1 { ~S1(){}; }; -// CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} i8* @_Znam(i64 [[ALLOC:%[0-9a-z]+]]) +// CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} i8* @_Znam(i64{{( noundef)?}} [[ALLOC:%[0-9a-z]+]]) // CHECK: [[COOKIE:%[0-9a-z]+]] = bitcast i8* [[MEM]] to i64* // CHECK: store i64 [[COUNT:%[0-9a-z]+]], i64* [[COOKIE]], align 8 // CHECK: [[ARR:%[0-9a-z]+]] = getelementptr inbounds i8, i8* [[MEM]], i64 8 diff --git a/test/pass/new_delete/18_array_cookie_delete.cpp b/test/pass/new_delete/18_array_cookie_delete.cpp index b5af6bff..56e0a7d2 100644 --- a/test/pass/new_delete/18_array_cookie_delete.cpp +++ b/test/pass/new_delete/18_array_cookie_delete.cpp @@ -8,7 +8,7 @@ struct S1 { }; // CHECK: [[MEM:%[0-9a-z]+]] = getelementptr inbounds i8, i8* [[ARR:%[0-9a-z]+]], i64 -8 -// CHECK: call void @_ZdaPv(i8* [[MEM]]) +// CHECK: call void @_ZdaPv(i8*{{( noundef)?}} [[MEM]]) // CHECK: call void @__typeart_free(i8* [[ARR]]) int main() { S1* ss = new S1[2]; diff --git a/test/pass/stack/01_stack_lifetime.c b/test/pass/stack/01_stack_lifetime.c new file mode 100644 index 00000000..03b9fca6 --- /dev/null +++ b/test/pass/stack/01_stack_lifetime.c @@ -0,0 +1,23 @@ +// clang-format off +// RUN: %c-to-llvm %s | %apply-typeart -typeart-stack -typeart-stack-lifetime -S 2>&1 | %filecheck %s +// clang-format on + +extern void type_check(void*); + +void correct(int rank) { + if (rank == 1) { + int buffer[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + type_check(buffer); + type_check(&buffer[2][2]); + } else { + int rcv[3] = {0, 1, 2}; + type_check(rcv); + } +} + +// CHECK: [[POINTER:%[0-9a-z]+]] = bitcast [3 x [3 x i32]]* [[BUF:%[0-9a-z]+]] to i8* +// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 36, i8* [[POINTER]]) +// CHECK-NEXT: call void @__typeart_alloc_stack(i8* [[POINTER]], i32 2, i64 9) + +// CHECK: call void @llvm.lifetime.start.p0i8(i64 12, i8* [[POINTER2:%[0-9a-z]+]]) +// CHECK-NEXT: call void @__typeart_alloc_stack(i8* [[POINTER2]], i32 2, i64 3) diff --git a/test/pass/stack/02_stack_color.llin b/test/pass/stack/02_stack_color.llin new file mode 100644 index 00000000..f172f7d9 --- /dev/null +++ b/test/pass/stack/02_stack_color.llin @@ -0,0 +1,43 @@ +; RUN: %apply-typeart -typeart-stack -typeart-stack-lifetime -S < %s | %filecheck %s + +; Adapted from LLVM codegen test suite + +; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %b) +; CHECK-NEXT: call void @__typeart_alloc_stack(i8* %b, i32 10, i64 17) + +; CHECK: bb2: +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %b2) +; CHECK-NEXT: call void @__typeart_alloc_stack(i8* %b2, i32 10, i64 16) + + + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @myCall2_w2(i32 %in, i1 %d) { +entry: + %a = alloca [17 x i8*], align 8 + %a2 = alloca [16 x i8*], align 8 + %b = bitcast [17 x i8*]* %a to i8* + %b2 = bitcast [16 x i8*]* %a2 to i8* + call void @llvm.lifetime.start.p0i8(i64 -1, i8* %b) + %t1 = call i32 @foo(i32 %in, i8* %b) + %t2 = call i32 @foo(i32 %in, i8* %b) + call void @llvm.lifetime.end.p0i8(i64 -1, i8* %b) + br i1 %d, label %bb2, label %bb3 +bb2: + call void @llvm.lifetime.start.p0i8(i64 -1, i8* %b2) + %t3 = call i32 @foo(i32 %in, i8* %b2) + %t4 = call i32 @foo(i32 %in, i8* %b2) + call void @llvm.lifetime.end.p0i8(i64 -1, i8* %b2) + %t5 = add i32 %t1, %t2 + %t6 = add i32 %t3, %t4 + %t7 = add i32 %t5, %t6 + ret i32 %t7 +bb3: + ret i32 0 +} + +declare i32 @foo(i32, i8* nocapture readonly) nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind diff --git a/test/pass/stack/03_stack_nocolor.llin b/test/pass/stack/03_stack_nocolor.llin new file mode 100644 index 00000000..481087b3 --- /dev/null +++ b/test/pass/stack/03_stack_nocolor.llin @@ -0,0 +1,52 @@ +; RUN: %apply-typeart -typeart-stack -typeart-stack-lifetime -S < %s 2>&1 | %filecheck %s + +; Modified from the LLVM codegen test suite + +; CHECK: %a = alloca [17 x i8*], align 8 +; CHECK-NEXT: %0 = bitcast [17 x i8*]* %a to i8* +; CHECK-NEXT: @__typeart_alloc_stack(i8* %0, i32 10, i64 17) +; CHECK-NEXT: %a2 = alloca [16 x i8*], align 8 +; CHECK-NEXT: %1 = bitcast [16 x i8*]* %a2 to i8* +; CHECK-NEXT: @__typeart_alloc_stack(i8* %1, i32 10, i64 16) + +; CHECK: Alloca : 2 + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @func_phi_lifetime(i32 %in, i1 %d) { +entry: + %a = alloca [17 x i8*], align 8 + %a2 = alloca [16 x i8*], align 8 + %b = bitcast [17 x i8*]* %a to i8* + %b2 = bitcast [16 x i8*]* %a2 to i8* + %t1 = call i32 @foo(i32 %in, i8* %b) + %t2 = call i32 @foo(i32 %in, i8* %b) + call void @llvm.lifetime.end.p0i8(i64 -1, i8* %b) + br i1 %d, label %bb0, label %bb1 + +bb0: + %I1 = bitcast [17 x i8*]* %a to i8* + br label %bb2 + +bb1: + %I2 = bitcast [16 x i8*]* %a2 to i8* + br label %bb2 + +bb2: + %split = phi i8* [ %I1, %bb0 ], [ %I2, %bb1 ] + call void @llvm.lifetime.start.p0i8(i64 -1, i8* %split) + %t3 = call i32 @foo(i32 %in, i8* %b2) + %t4 = call i32 @foo(i32 %in, i8* %b2) + %t5 = add i32 %t1, %t2 + %t6 = add i32 %t3, %t4 + %t7 = add i32 %t5, %t6 + call void @llvm.lifetime.end.p0i8(i64 -1, i8* %split) + ret i32 %t7 +bb3: + ret i32 0 +} + +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind +declare i32 @foo(i32, i8*) nounwind diff --git a/test/runtime/07_simple_struct_type_check.c b/test/runtime/07_simple_struct_type_check.c index 1c391fc2..7a6052f3 100644 --- a/test/runtime/07_simple_struct_type_check.c +++ b/test/runtime/07_simple_struct_type_check.c @@ -1,4 +1,4 @@ -// RUN: %run %s -alloca-array-only=true 2>&1 | %filecheck %s +// RUN: %run %s -typeart-stack-array-only=true 2>&1 | %filecheck %s #include "../struct_defs.h" #include "util.h" diff --git a/test/runtime/08_recursive_struct_type_check.c b/test/runtime/08_recursive_struct_type_check.c index 7c03a2f8..e9138ed3 100644 --- a/test/runtime/08_recursive_struct_type_check.c +++ b/test/runtime/08_recursive_struct_type_check.c @@ -1,4 +1,4 @@ -// RUN: %run %s -alloca-array-only=true 2>&1 | %filecheck %s +// RUN: %run %s -typeart-stack-array-only=true 2>&1 | %filecheck %s #include "../struct_defs.h" #include "util.h" diff --git a/test/runtime/10_vector_fill_demo.c b/test/runtime/10_vector_fill_demo.c index 6a7b781c..29d4ae8e 100644 --- a/test/runtime/10_vector_fill_demo.c +++ b/test/runtime/10_vector_fill_demo.c @@ -36,18 +36,18 @@ int fill_vector(void* values, int count, vector* v) { } int main(int argc, char** argv) { - const int n = 3; + const int n = 3; // CHECK: [Trace] TypeART Runtime Trace // CHECK: [Trace] Alloc 0x{{.*}} int32 4 3 - int int_vals[3] = {1, 2, 3}; + int int_vals[3] = {1, 2, 3}; // CHECK: [Trace] Alloc 0x{{.*}} double 8 3 double d_vals[3] = {1, 2, 3}; // CHECK: [Trace] Alloc 0x{{.*}} float 4 3 - float f_vals[3] = {1, 2, 3}; + float f_vals[3] = {1, 2, 3}; // CHECK: [Trace] Alloc 0x{{.*}} double 8 3 - vector v = alloc_vector(n); + vector v = alloc_vector(n); // CHECK: [Trace] Alloc 0x{{.*}} double 8 3 - vector w = alloc_vector(n); + vector w = alloc_vector(n); // CHECK: Success fill_vector(w.vals, n, &v); // CHECK: Failure diff --git a/test/runtime/12_alloc_multi.c b/test/runtime/12_alloc_multi.c index 30e22e4c..c076acc1 100644 --- a/test/runtime/12_alloc_multi.c +++ b/test/runtime/12_alloc_multi.c @@ -1,6 +1,6 @@ // clang-format off // RUN: %run %s -typeart-filter-pointer-alloca=false 2>&1 | %filecheck %s -// RUN: %run %s "-call-filter" 2>&1 | %filecheck %s --check-prefix CHECK-FILTER +// RUN: %run %s "-typeart-call-filter" 2>&1 | %filecheck %s --check-prefix CHECK-FILTER // clang-format on #include diff --git a/test/runtime/24_threads_type_check.cpp b/test/runtime/24_threads_type_check.cpp index 91b81b89..b5947994 100644 --- a/test/runtime/24_threads_type_check.cpp +++ b/test/runtime/24_threads_type_check.cpp @@ -57,7 +57,6 @@ int main(int argc, char** argv) { // CHECK-TSAN-NOT: ThreadSanitizer - // CHECK-NOT: Error // CHECK: Allocation type detail (heap, stack, global) // CHECK: 6 : 3000 , 0 , 0 , double // CHECK: Free allocation type detail (heap, stack) diff --git a/test/runtime/27_omp_softcounter.c b/test/runtime/27_omp_softcounter.c index 1e4d5cdd..38e9d6de 100644 --- a/test/runtime/27_omp_softcounter.c +++ b/test/runtime/27_omp_softcounter.c @@ -1,9 +1,9 @@ // clang-format off -// RUN: %run %s --omp --call-filter 2>&1 | %filecheck %s --check-prefix=CHECK-TSAN -// RUN: %run %s -o -O2 --omp --call-filter 2>&1 | %filecheck %s --check-prefix=CHECK-TSAN +// RUN: %run %s --omp -typeart-call-filter 2>&1 | %filecheck %s --check-prefix=CHECK-TSAN +// RUN: %run %s -o -O2 --omp -typeart-call-filter 2>&1 | %filecheck %s --check-prefix=CHECK-TSAN -// RUN: %run %s -o -O2 --omp --call-filter 2>&1 | %filecheck %s -// RUN: %run %s --omp --call-filter 2>&1 | %filecheck %s +// RUN: %run %s -o -O2 --omp -typeart-call-filter 2>&1 | %filecheck %s +// RUN: %run %s --omp -typeart-call-filter 2>&1 | %filecheck %s // REQUIRES: openmp && softcounter // clang-format on diff --git a/test/runtime/28_omp_softcounter_stack.c b/test/runtime/28_omp_softcounter_stack.c index f7b8b227..913b312e 100644 --- a/test/runtime/28_omp_softcounter_stack.c +++ b/test/runtime/28_omp_softcounter_stack.c @@ -1,6 +1,6 @@ // clang-format off // RUN: %run %s -o -O0 --omp -typeart-filter-pointer-alloca=false 2>&1 | %filecheck %s --check-prefix=CHECK-TSAN -// RUN: %run %s -o -O0 --omp -typeart-filter-pointer-alloca=false 2>&1 | %filecheck %s +// RUN: %run %s -o -O0 --omp -typeart-filter-pointer-alloca=false 2>&1 | %filecheck %s --check-prefixes=CHECK,ERROR // REQUIRES: openmp && softcounter // clang-format on @@ -30,18 +30,18 @@ int main(int argc, char** argv) { ptr(n); // CHECK-TSAN-NOT: ThreadSanitizer + // ERROR-NOT: [Error] // CHECK: [Trace] TypeART Runtime Trace - // TODO: CHECK-NOT: [Error] - Currently we get 'Pointer already in map' followed by 'Free on unregistered address' // CHECK: Alloc Stats from softcounters // CHECK-NEXT: Total heap : 0 , 0 , - // CHECK: Total stack : {{[0-9]+}} , 400 , - // CHECK-NEXT: Total global : {{[0-9]+}} , {{[0-9]+}} , - // CHECK-NEXT: Max. Heap Allocs : 0 , - , - - // CHECK-NEXT: Max. Stack Allocs : 17 , - , - + // CHECK-NEXT: Max. Stack Allocs : 16 , - , - // CHECK-NEXT: Addresses checked : 0 , - , - // CHECK-NEXT: Distinct Addresses checked : 0 , - , - - // CHECK-NEXT: Addresses re-used : 2 , - , - + // CHECK-NEXT: Addresses re-used : 0 , - , - // CHECK-NEXT: Addresses missed : 0 , - , - // CHECK-NEXT: Distinct Addresses missed : 0 , - , - // CHECK-NEXT: Total free heap : 0 , 0 , - diff --git a/test/runtime/45_default_types.c b/test/runtime/45_default_types.c index 08ba79ba..779fc6bc 100644 --- a/test/runtime/45_default_types.c +++ b/test/runtime/45_default_types.c @@ -7,7 +7,7 @@ int main(int argc, char** argv) { // CHECK: [Trace] TypeART Runtime Trace // CHECK: [Warning]{{.*}}No type file with default name // CHECK: [Trace] Alloc 0x{{.*}} int8 1 42 - char* a = malloc(n * sizeof(char)); + char* a = malloc(n * sizeof(char)); // CHECK: [Trace] Free 0x{{.*}} free(a); } diff --git a/test/runtime/47_memory_use.cpp b/test/runtime/47_memory_use.cpp index 2a05fa1b..04b6a80c 100644 --- a/test/runtime/47_memory_use.cpp +++ b/test/runtime/47_memory_use.cpp @@ -10,10 +10,10 @@ struct Datastruct { float end; }; -int main(int argc, char** argv) { +int main() { Datastruct d; - const auto rss = typeart::system::Process::get().getMaxRSS(); + const auto rss = typeart::system::Process::getMaxRSS(); printf("Max RSS: %ld\n", rss); return 0; diff --git a/test/runtime/48_pointer_alloca.c b/test/runtime/48_pointer_alloca.c index df2ef382..785cd6ec 100644 --- a/test/runtime/48_pointer_alloca.c +++ b/test/runtime/48_pointer_alloca.c @@ -3,6 +3,8 @@ // RUN: %run %s -typeart-filter-pointer-alloca=false 2>&1 | %filecheck %s --check-prefix CHECK-pointer // clang-format on +// REQUIRES: softcounter + int main(int argc, char** argv) { int n = argc * 2; int* x; diff --git a/test/runtime/50_global_skip.cpp b/test/runtime/50_global_skip.cpp new file mode 100644 index 00000000..e1a45f9e --- /dev/null +++ b/test/runtime/50_global_skip.cpp @@ -0,0 +1,28 @@ +// RUN: %run %s 2>&1 | %filecheck %s +// RUN: %run %s -typeart-global=false 2>&1 | %filecheck %s --check-prefix CHECK-SKIP + +// REQUIRES: softcounter + +double global_d; + +void f() { + static int global_t{0}; + char c[7]; + double d = 5; +} + +int main(int argc, char** argv) { + f(); + f(); + return 0; +} + +// CHECK: Allocation type detail (heap, stack, global) +// CHECK: 0 : 0 , {{[0-9]}} , 0 , int8 +// CHECK: 2 : 0 , {{[0-9]}} , 1 , int32 +// CHECK: 6 : 0 , {{[0-9]}} , 1 , double + +// CHECK-SKIP: Allocation type detail (heap, stack, global) +// CHECK-SKIP: 0 : 0 , {{[0-9]}} , 0 , int8 +// CHECK-SKIP: 2 : 0 , {{[0-9]}} , 0 , int32 +// CHECK-SKIP: 6 : 0 , {{[0-9]}} , 0 , double diff --git a/test/runtime/51_stack_lifetime.c b/test/runtime/51_stack_lifetime.c new file mode 100644 index 00000000..b82ee8b3 --- /dev/null +++ b/test/runtime/51_stack_lifetime.c @@ -0,0 +1,44 @@ +// RUN: %run %s -typeart-stack-lifetime=true 2>&1 | %filecheck %s + +#include "../../lib/runtime/RuntimeInterface.h" + +#include + +void type_check(const void* addr) { + int id_result = 0; + size_t count_check = 0; + typeart_status status; + status = typeart_get_type(addr, &id_result, &count_check); + + if (status != TYPEART_OK) { + fprintf(stderr, "[Error]: Status not OK: %i for %p\n", status, addr); + } else { + fprintf(stderr, "Status OK: %i %zu\n", id_result, count_check); + } +} + +void correct(int rank) { + if (rank == 1) { + // CHECK: Status OK: 2 9 + // CHECK: Status OK: 2 8 + // CHECK: Status OK: 2 7 + // CHECK: Status OK: 2 1 + int buffer[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + type_check(buffer); + type_check(&buffer[0][1]); + type_check(&buffer[0][2]); + type_check(&buffer[2][2]); + } else { + // CHECK: Status OK: 2 3 + // CHECK: Status OK: 2 1 + int rcv[3] = {0, 1, 2}; + type_check(rcv); + type_check(&rcv[2]); + } +} + +int main(void) { + correct(1); + correct(0); + return 0; +} diff --git a/test/runtime/52_stack_lifetime_2.llin b/test/runtime/52_stack_lifetime_2.llin new file mode 100644 index 00000000..8792ff3c --- /dev/null +++ b/test/runtime/52_stack_lifetime_2.llin @@ -0,0 +1,57 @@ +; RUN: %apply-typeart -typeart-stack -typeart-stack-lifetime -S < %s | %llc -x=ir --filetype=obj -o %s.o +; RUN: %wrapper-cc %s.o -o %s.exe +; RUN: %s.exe 2>&1 | %filecheck %s + +; REQUIRES: softcounter + +; Adapted from LLVM codegen test suite + +; CHECK: [Error]{{.*}}Free on unregistered address +; CHECK: Allocation type detail (heap, stack, global) +; CHECK-NEXT: 10 : 0 , 2 , 0 , pointer +; CHECK-NEXT: ######################################### +; CHECK-NEXT: Free allocation type detail (heap, stack) +; CHECK-NEXT; 10 : 0 , 1 , pointer + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @myCall2_w2(i32 %in, i1 %d) { +entry: + %a = alloca [17 x i8*], align 8 + %a2 = alloca [16 x i8*], align 8 ; a and a2 are colored, hence tracking a2 overwrites a in TypeART + %b = bitcast [17 x i8*]* %a to i8* + %b2 = bitcast [16 x i8*]* %a2 to i8* + call void @llvm.lifetime.start.p0i8(i64 -1, i8* %b) + %t1 = call i32 @foo(i32 %in, i8* %b) + %t2 = call i32 @foo(i32 %in, i8* %b) + call void @llvm.lifetime.end.p0i8(i64 -1, i8* %b) + br i1 %d, label %bb2, label %bb3 +bb2: + call void @llvm.lifetime.start.p0i8(i64 -1, i8* %b2) + %t3 = call i32 @foo(i32 %in, i8* %b2) + %t4 = call i32 @foo(i32 %in, i8* %b2) + call void @llvm.lifetime.end.p0i8(i64 -1, i8* %b2) + %t5 = add i32 %t1, %t2 + %t6 = add i32 %t3, %t4 + %t7 = add i32 %t5, %t6 + ret i32 %t7 +bb3: + ret i32 0 +} + +define dso_local i32 @foo(i32 %0, i8* %1) #0 { + ret i32 1 +} + +define dso_local i32 @main() local_unnamed_addr { + %1 = tail call i32 @myCall2_w2(i32 1, i1 1) + ret i32 0 +} + +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable willreturn } diff --git a/test/runtime/53_get_type.c b/test/runtime/53_get_type.c new file mode 100644 index 00000000..f7a79454 --- /dev/null +++ b/test/runtime/53_get_type.c @@ -0,0 +1,107 @@ +// RUN: %run %s 2>&1 | %filecheck %s + +#include "util.h" + +#include +#include + +typedef struct { + int a; + double b; + float c[2]; +} DataStruct; + +void print_layout() { + // CHECK: Layout: 0 8 16 + fprintf(stderr, "Layout: %zu %zu %zu\n", offsetof(DataStruct, a), offsetof(DataStruct, b), offsetof(DataStruct, c)); +} + +void type_check(const void* addr) { + int id_result = 0; + size_t count_check = 0; + typeart_status status = typeart_get_type(addr, &id_result, &count_check); + + if (status != TYPEART_OK) { + fprintf(stderr, "[Error]: Status not OK: %i for %p\n", status, addr); + } else { + fprintf(stderr, "Status OK: type_id=%i count=%zu\n", id_result, count_check); + } +} + +void test_get_type() { + DataStruct data[5]; + // CHECK: Status OK: type_id=5 count=2 + type_check(&data[1].c[0]); +} + +void type_check_containing(const void* addr) { + size_t offset = 0; + const void* base_adrr = NULL; + int id_result = 0; + size_t count_check = 0; + + typeart_status status = typeart_get_containing_type(addr, &id_result, &count_check, &base_adrr, &offset); + + if (status != TYPEART_OK) { + fprintf(stderr, "[Error]: Status not OK: %i for %p\n", status, addr); + } else { + fprintf(stderr, "Status OK: type_id=%i count=%zu offset=%zu base=%p\n", id_result, count_check, offset, base_adrr); + } +} + +void test_get_containing() { + DataStruct data[5]; + // CHECK: type_id=257 count=4 offset=16 base= + type_check_containing(&data[1].c[0]); +} + +void type_check_sub(const void* addr, size_t offset) { + const void* base_adrr = NULL; + size_t count_check = 0; + typeart_status status; + + typeart_struct_layout layout; + { + int type_id; + size_t offset_containing; + status = typeart_get_containing_type(addr, &type_id, &count_check, &base_adrr, &offset_containing); + if (status != TYPEART_OK) { + fprintf(stderr, "[Error]: with containing type\n"); + return; + } + status = typeart_resolve_type_id(type_id, &layout); + if (status != TYPEART_OK) { + fprintf(stderr, "[Error]: with resolving struct\n"); + return; + } + } + + int subtype_id; + size_t subtype_byte_offset; + status = typeart_get_subtype(base_adrr, offset, &layout, &subtype_id, &base_adrr, &subtype_byte_offset, &count_check); + + if (status != TYPEART_OK) { + fprintf(stderr, "[Error]: Status not OK: %i for %p\n", status, addr); + } else { + fprintf(stderr, "Status OK: type_id=%i count=%zu offset=%zu addr(%p) base(%p)\n", subtype_id, count_check, + subtype_byte_offset, addr, base_adrr); + } +} + +void test_get_subtype() { + DataStruct data[5]; + // CHECK: type_id=5 count=1 offset=0 + type_check_sub(&data[1], offsetof(DataStruct, c[1])); +} + +int main(void) { + print_layout(); + + test_get_type(); + + test_get_containing(); + + test_get_subtype(); + + return 0; +} diff --git a/test/runtime/54_get_type_illegal.c b/test/runtime/54_get_type_illegal.c new file mode 100644 index 00000000..119a5b0a --- /dev/null +++ b/test/runtime/54_get_type_illegal.c @@ -0,0 +1,135 @@ +// RUN: %run %s 2>&1 | %filecheck %s + +#include "util.h" + +#include +#include + +typedef struct { + int a; + double b; + float c[2]; +} DataStruct; + +void print_layout() { + // CHECK: Layout: 0 8 16 + fprintf(stderr, "Layout: %zu %zu %zu\n", offsetof(DataStruct, a), offsetof(DataStruct, b), offsetof(DataStruct, c)); +} + +void type_check(const void* addr) { + int id_result = 0; + size_t count_check = 0; + typeart_status status = typeart_get_type(addr, &id_result, &count_check); + + if (status != TYPEART_OK) { + fprintf(stderr, "[Expected]: Status not OK: %s for %p\n", err_code_to_string(status), addr); + } else { + fprintf(stderr, "[Error] Status OK: type_id=%i count=%zu\n", id_result, count_check); + } +} + +void test_get_type() { + DataStruct data[5]; + void* illegal_addr = (char*)&data[0].a + sizeof(int); + + // CHECK: Diff(4) + ptrdiff_t diff = (char*)illegal_addr - (char*)&data[0]; + fprintf(stderr, "Diff(%td)\n", diff); + // CHECK: [Expected]: Status not OK: TYPEART_BAD_ALIGNMENT + type_check(illegal_addr); +} + +void type_check_containing(const void* addr) { + size_t offset = 0; + const void* base_adrr = NULL; + int id_result = 0; + size_t count_check = 0; + + typeart_status status = typeart_get_containing_type(addr, &id_result, &count_check, &base_adrr, &offset); + + if (status != TYPEART_OK) { + fprintf(stderr, "[Expected]: Status not OK: %s for %p\n", err_code_to_string(status), addr); + } else { + fprintf(stderr, "Status OK: type_id=%i count=%zu offset=%zu base=%p\n", id_result, count_check, offset, base_adrr); + } +} + +void test_get_containing() { + DataStruct data[5]; + // Illegal address, but containing_type does not resolve such things: + void* illegal_addr = (char*)&data[0].a + sizeof(int); + // CHECK: Status OK: type_id=257 count=5 offset=4 + type_check_containing(illegal_addr); +} + +void type_check_sub(const void* addr, size_t offset) { + const void* base_adrr = NULL; + size_t count_check = 0; + typeart_status status; + + typeart_struct_layout layout; + { + int type_id; + size_t offset_containing; + status = typeart_get_containing_type(addr, &type_id, &count_check, &base_adrr, &offset_containing); + if (status != TYPEART_OK) { + fprintf(stderr, "[Error]: with containing type\n"); + return; + } + status = typeart_resolve_type_id(type_id, &layout); + if (status != TYPEART_OK) { + fprintf(stderr, "[Error]: with resolving struct\n"); + return; + } + } + + int subtype_id; + size_t subtype_byte_offset; + status = typeart_get_subtype(base_adrr, offset, &layout, &subtype_id, &base_adrr, &subtype_byte_offset, &count_check); + + if (status != TYPEART_OK) { + fprintf(stderr, "[Expected]: Status not OK: %s for %p\n", err_code_to_string(status), addr); + } else { + fprintf(stderr, "Status OK: type_id=%i count=%zu offset=%zu addr(%p) base(%p)\n", subtype_id, count_check, + subtype_byte_offset, addr, base_adrr); + } +} + +void test_get_subtype() { + DataStruct data[5]; + void* legal_addr = (char*)&data[0].a; + + // Legal address but illegal offset: + // CHECK: [Expected]: Status not OK: TYPEART_BAD_ALIGNMENT + type_check_sub(legal_addr, sizeof(int)); + + // CHECK: [Expected]: Status not OK: TYPEART_BAD_OFFSET + type_check_sub(legal_addr, 2 * sizeof(DataStruct)); +} + +void test_get_subtype_direct() { + typeart_struct_layout layout; + typeart_status status = typeart_resolve_type_id(777, &layout); + int subtype_id; + size_t subtype_byte_offset; + const void* base_adrr = NULL; + size_t count_check; + status = typeart_get_subtype(NULL, 0, &layout, &subtype_id, &base_adrr, &subtype_byte_offset, &count_check); + + // CHECK: [Expected]: Status not OK: TYPEART_ERROR + fprintf(stderr, "[Expected]: Status not OK: %s\n", err_code_to_string(status)); +} + +int main(void) { + print_layout(); + + test_get_type(); + + test_get_containing(); + + test_get_subtype(); + + test_get_subtype_direct(); + + return 0; +} diff --git a/test/runtime/55_query_struct.c b/test/runtime/55_query_struct.c new file mode 100644 index 00000000..b32309fa --- /dev/null +++ b/test/runtime/55_query_struct.c @@ -0,0 +1,51 @@ +// RUN: %run %s 2>&1 | %filecheck %s + +#include "../../lib/runtime/RuntimeInterface.h" + +#include +#include + +struct Datastruct { + int start; + double middle; + float end; +}; + +void print_layout(typeart_struct_layout* layout) { + fprintf(stderr, "layout->id %i\n", layout->type_id); + fprintf(stderr, "layout->name %s\n", layout->name); + fprintf(stderr, "layout->num_members %zu\n", layout->num_members); + fprintf(stderr, "layout->extent %zu\n", layout->extent); +} + +int main(void) { + struct Datastruct data = {0}; + + // CHECK-NOT: [Error] return status + // CHECK: layout->id {{[2-9][0-9]+}} + // CHECK: layout->name struct.Datastruct + // CHECK: layout->num_members 3 + // CHECK: struct count 1 + typeart_struct_layout layout; + typeart_status status = typeart_resolve_type_addr(&data, &layout); + if (status != TYPEART_OK) { + fprintf(stderr, "[Error] return status\n"); + } + print_layout(&layout); + size_t count; + typeart_get_type_length(&data, &count); + fprintf(stderr, "struct count %zu\n", count); + + // CHECK-NOT: [Error] status unexpectedly OK + // CHECK: layout->id + // CHECK: layout->name + // CHECK: layout->num_members 0 + typeart_struct_layout layout_err; + status = typeart_resolve_type_id(777, &layout_err); + if (status == TYPEART_OK) { + fprintf(stderr, "[Error] status unexpectedly OK\n"); + } + print_layout(&layout_err); + + return 0; +} diff --git a/test/runtime/util.h b/test/runtime/util.h index 5d5abe9e..596c50d3 100644 --- a/test/runtime/util.h +++ b/test/runtime/util.h @@ -7,6 +7,27 @@ #include #include +const char* err_code_to_string(typeart_status status) { + switch (status) { + case TYPEART_OK: + return "TYPEART_OK"; + case TYPEART_BAD_ALIGNMENT: + return "TYPEART_BAD_ALIGNMENT"; + case TYPEART_UNKNOWN_ADDRESS: + return "TYPEART_UNKNOWN_ADDRESS"; + case TYPEART_ERROR: + return "TYPEART_ERROR"; + case TYPEART_BAD_OFFSET: + return "TYPEART_BAD_OFFSET"; + case TYPEART_INVALID_ID: + return "TYPEART_INVALID_ID"; + case TYPEART_WRONG_KIND: + return "TYPEART_WRONG_KIND"; + default: + return "unknown_status"; + } +} + int get_struct_id(int index) { return TYPEART_NUM_RESERVED_IDS + index; } diff --git a/test/script/01_wrapper_internal.sh b/test/script/01_wrapper_internal.sh index 7be33341..b0065c62 100755 --- a/test/script/01_wrapper_internal.sh +++ b/test/script/01_wrapper_internal.sh @@ -14,13 +14,13 @@ source "$1" --version # wcxx: TypeART-Toolchain: -# wcxx-NEXT: clang++{{(-10|-11|-12|-13)?}} -# wcxx-NEXT: opt{{(-10|-11|-12|-13)?}} -# wcxx-NEXT: llc{{(-10|-11|-12|-13)?}} +# wcxx-NEXT: clang++{{(-10|-11|-12|-13|-14)?}} +# wcxx-NEXT: opt{{(-10|-11|-12|-13|-14)?}} +# wcxx-NEXT: llc{{(-10|-11|-12|-13|-14)?}} # wcc: TypeART-Toolchain: -# wcc-NEXT: clang{{(-10|-11|-12|-13)?}} -# wcc-NEXT: opt{{(-10|-11|-12|-13)?}} -# wcc-NEXT: llc{{(-10|-11|-12|-13)?}} +# wcc-NEXT: clang{{(-10|-11|-12|-13|-14)?}} +# wcc-NEXT: opt{{(-10|-11|-12|-13|-14)?}} +# wcc-NEXT: llc{{(-10|-11|-12|-13|-14)?}} echo "TypeART-Toolchain:" echo "$compiler" echo "$opt_tool" @@ -44,7 +44,7 @@ is_linking -c echo $? # CHECK: 1 -skip_typeart -E main.c +skip_typeart_compile -E main.c echo $? function parse_check() { @@ -115,3 +115,20 @@ echo "${ta_more_args}" parse_cmd_line -o amg2013 amg2013.o -L. -L../parcsr_ls -L../parcsr_mv -L../IJ_mv -L../seq_mv -L../sstruct_mv -L../struct_mv -L../krylov -L../utilities -lparcsr_ls -lparcsr_mv -lseq_mv -lsstruct_mv -lIJ_mv -lHYPRE_struct_mv -lkrylov -lHYPRE_utilities -lm -fopenmp parse_check echo "${ta_more_args}" + +# a linker call: +# CHECK: 0 0 1 1 0 0 -O0 +# CHECK-NEXT: es eo ea libtool.so +# CHECK-NEXT: -fPIC -shared -Wl,-soname,libtool.so CMakeFiles/tool.dir/tool.c.o +linking=1 # This call would typically not be passed to parse_cmd_line, linking is required for proper parsing. +parse_cmd_line -fPIC -shared -Wl,-soname,libtool.so -o libtool.so CMakeFiles/tool.dir/tool.c.o +linking=0 +parse_check +echo "${ta_more_args}" + +# CHECK: 1 1 0 1 0 0 -O0 +# CHECK-NEXT: typeart/demo/tool.c CMakeFiles/tool.dir/tool.c.o ea eb +# CHECK-NEXT: -Dtool_EXPORTS -fPIC -MD -MT CMakeFiles/tool.dir/tool.c.o -MF CMakeFiles/tool.dir/tool.c.o.d +parse_cmd_line -Dtool_EXPORTS -fPIC -MD -MT CMakeFiles/tool.dir/tool.c.o -MF CMakeFiles/tool.dir/tool.c.o.d -o CMakeFiles/tool.dir/tool.c.o -c typeart/demo/tool.c +parse_check +echo "${ta_more_args}" diff --git a/test/script/02_wrapper_mpi_internal.sh b/test/script/02_wrapper_mpi_internal.sh index c563ec6f..0d75ae4b 100755 --- a/test/script/02_wrapper_mpi_internal.sh +++ b/test/script/02_wrapper_mpi_internal.sh @@ -11,13 +11,13 @@ source "$1" --version # wcxx: TypeART-Toolchain: -# wcxx-NEXT: env OMPI_CXX={{.*}}clang++{{(-10|-11|-12|-13)?}} [[FCMPICXX]] -# wcxx-NEXT: opt{{(-10|-11|-12|-13)?}} -# wcxx-NEXT: llc{{(-10|-11|-12|-13)?}} +# wcxx-NEXT: env OMPI_CXX={{.*}}clang++{{(-10|-11|-12|-13|-14)?}} [[FCMPICXX]] +# wcxx-NEXT: opt{{(-10|-11|-12|-13|-14)?}} +# wcxx-NEXT: llc{{(-10|-11|-12|-13|-14)?}} # wcc: TypeART-Toolchain: -# wcc-NEXT: env OMPI_CC={{.*}}clang{{(-10|-11|-12|-13)?}} [[FCMPICC]] -# wcc-NEXT: opt{{(-10|-11|-12|-13)?}} -# wcc-NEXT: llc{{(-10|-11|-12|-13)?}} +# wcc-NEXT: env OMPI_CC={{.*}}clang{{(-10|-11|-12|-13|-14)?}} [[FCMPICC]] +# wcc-NEXT: opt{{(-10|-11|-12|-13|-14)?}} +# wcc-NEXT: llc{{(-10|-11|-12|-13|-14)?}} echo "TypeART-Toolchain:" echo "$compiler" echo "$opt_tool" diff --git a/test/script/03_wrapper_cxx.cpp b/test/script/03_wrapper_cxx.cpp index 34fa97b9..92d0e7ea 100644 --- a/test/script/03_wrapper_cxx.cpp +++ b/test/script/03_wrapper_cxx.cpp @@ -2,6 +2,10 @@ // RUN: %wrapper-cxx -O1 %s -o %s.exe // RUN: %s.exe 2>&1 | %filecheck %s +// RUN: %wrapper-cxx -O1 -c %s -o %s.o +// RUN: %wrapper-cxx %s.o -o %s.exe +// RUN: %mpi-exec -np 1 %s.exe 2>&1 | %filecheck %s + #include "../../lib/runtime/CallbackInterface.h" int main(int argc, char** argv) { diff --git a/test/script/04_wrapper_cc.c b/test/script/04_wrapper_cc.c index 364402e9..2a5dcb8c 100644 --- a/test/script/04_wrapper_cc.c +++ b/test/script/04_wrapper_cc.c @@ -2,6 +2,10 @@ // RUN: %wrapper-cc -O1 %s -o %s.exe // RUN: %s.exe 2>&1 | %filecheck %s +// RUN: %wrapper-cc -O1 -c %s -o %s.o +// RUN: %wrapper-cc %s.o -o %s.exe +// RUN: %mpi-exec -np 1 %s.exe 2>&1 | %filecheck %s + #include "../../lib/runtime/CallbackInterface.h" int main(int argc, char** argv) { diff --git a/test/script/05_wrapper_mpicxx.cpp b/test/script/05_wrapper_mpicxx.cpp index 672c1d21..563dd7e8 100644 --- a/test/script/05_wrapper_mpicxx.cpp +++ b/test/script/05_wrapper_mpicxx.cpp @@ -2,6 +2,10 @@ // RUN: %wrapper-mpicxx -g %s -o %s.exe // RUN: %mpi-exec -np 1 %s.exe 2>&1 | %filecheck %s +// RUN: %wrapper-mpicxx -g -c %s -o %s.o +// RUN: %wrapper-mpicxx %s.o -o %s.exe +// RUN: %mpi-exec -np 1 %s.exe 2>&1 | %filecheck %s + // REQUIRES: mpicxx // UNSUPPORTED: sanitizer diff --git a/test/script/06_wrapper_mpicc.c b/test/script/06_wrapper_mpicc.c index 3fb4d442..ad95003d 100644 --- a/test/script/06_wrapper_mpicc.c +++ b/test/script/06_wrapper_mpicc.c @@ -2,6 +2,10 @@ // RUN: %wrapper-mpicc -O1 %s -o %s.exe // RUN: %mpi-exec -np 1 %s.exe 2>&1 | %filecheck %s +// RUN: %wrapper-mpicc -O1 -c %s -o %s.o +// RUN: %wrapper-mpicc %s.o -o %s.exe +// RUN: %mpi-exec -np 1 %s.exe 2>&1 | %filecheck %s + // REQUIRES: mpicc // UNSUPPORTED: sanitizer diff --git a/test/script/09_wrapper_single_tu.c b/test/script/09_wrapper_single_tu.c new file mode 100644 index 00000000..73872019 --- /dev/null +++ b/test/script/09_wrapper_single_tu.c @@ -0,0 +1,26 @@ +// RUN: echo --- > types.yaml +// RUN: %wrapper-cc %s -o %s.exe +// RUN: %s.exe 2>&1 | %filecheck %s + +// RUN: %wrapper-cc %s +// RUN: %p/a.out 2>&1 | %filecheck %s + +// RUN: %wrapper-cc -O1 %s +// RUN: %p/a.out 2>&1 | %filecheck %s --allow-empty + +// RUN: %wrapper-cc -MD -MT %s.o -MF %s.o.d %s +// RUN: %p/a.out 2>&1 | %filecheck %s + +// RUN: %wrapper-cc -MD -MT %s.o -MF %s.o.d -c %s -o %s.o +// RUN: %wrapper-cc %s.o +// RUN: %p/a.out 2>&1 | %filecheck %s + +// RUN: TYPEART_WRAPPER=OFF %wrapper-cc %s +// RUN: %p/a.out 2>&1 | %filecheck %s --allow-empty + +int main(int argc, char** argv) { + int a = 0; + return a; +} + +// CHECK-NOT: Error diff --git a/test/script/10_wrapper_asm.c b/test/script/10_wrapper_asm.c new file mode 100644 index 00000000..475a33b5 --- /dev/null +++ b/test/script/10_wrapper_asm.c @@ -0,0 +1,18 @@ +// RUN: %wrapper-cc -S -O1 %s -o %s.s +// RUN: cat %s.s 2>&1 | %filecheck %s + +// RUN: %wrapper-cc -fPIC -S -O1 %s -o %s.s +// RUN: cat %s.s 2>&1 | %filecheck %s + +// RUN: TYPEART_WRAPPER=OFF %wrapper-cc -S -O1 %s -o %s-van.s +// RUN: cat %s-van.s 2>&1 | %filecheck %s --check-prefixes vanilla-CHECK + +#include + +int main(int argc, char** argv) { + int* p = malloc(argc * sizeof(int)); + return 0; +} + +// CHECK: call{{.*}}__typeart_alloc +// vanilla-CHECK-NOT: call{{.*}}__typeart_alloc