From acf5c0ea2058551647d66bd5b818cde28ff4018d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Thu, 13 Nov 2025 16:24:35 +0100 Subject: [PATCH 01/14] Global variables as type descriptors (#173) --- .clang-tidy | 1 - .github/workflows/basic-ci.yml | 22 +- .github/workflows/ext-ci.yml | 12 +- demo/Makefile | 2 +- externals/abseil/CMakeLists.txt | 2 +- lib/passes/CMakeLists.txt | 2 + lib/passes/Commandline.cpp | 12 + lib/passes/TypeARTPass.cpp | 111 ++-- lib/passes/analysis/MemInstFinder.cpp | 2 +- .../EnvironmentConfiguration.cpp | 5 + lib/passes/configuration/OptionsUtil.h | 29 +- lib/passes/configuration/PassBuilderUtil.h | 4 +- .../configuration/PassConfiguration.cpp | 7 + lib/passes/configuration/TypeARTOptions.cpp | 19 +- lib/passes/configuration/TypeARTOptions.h | 12 +- lib/passes/filter/FilterUtil.h | 8 +- .../CallBackFunctionInserter.cpp | 94 ++++ .../CallBackFunctionInserter.h | 54 ++ .../instrumentation/InstrumentationHelper.h | 1 - .../instrumentation/MemOpInstrumentation.cpp | 59 +- .../instrumentation/MemOpInstrumentation.h | 16 +- .../instrumentation/TypeARTFunctions.cpp | 247 ++++++++- lib/passes/instrumentation/TypeARTFunctions.h | 56 +- lib/passes/instrumentation/TypeIDProvider.cpp | 509 ++++++++++++++++++ lib/passes/instrumentation/TypeIDProvider.h | 39 ++ lib/passes/typegen/TypeGenerator.cpp | 5 +- lib/passes/typegen/TypeGenerator.h | 12 +- lib/passes/typegen/TypeIDGenerator.h | 2 +- lib/passes/typegen/dimeta/DimetaTypeGen.cpp | 16 +- lib/runtime/AccessCountPrinter.h | 6 - lib/runtime/AccessCounter.h | 6 - lib/runtime/AllocMapWrapper.h | 1 + lib/runtime/AllocationTracking.cpp | 75 ++- lib/runtime/CMakeLists.txt | 2 + lib/runtime/CallbackInterface.h | 9 + lib/runtime/GlobalTypeDefCallbacks.cpp | 116 ++++ lib/runtime/GlobalTypeDefCallbacks.h | 44 ++ lib/runtime/Runtime.cpp | 16 +- lib/runtime/Runtime.h | 45 +- lib/runtime/RuntimeData.h | 48 +- lib/runtime/TypeResolution.cpp | 45 +- lib/runtime/TypeResolution.h | 8 +- lib/support/ConfigurationBaseOptions.h | 2 + lib/typelib/TypeDB.cpp | 21 +- lib/typelib/TypeDatabase.h | 2 +- scripts/opt-shim.in | 8 + scripts/typeart-wrapperv2.in | 4 +- test/CMakeLists.txt | 1 + test/lit.cfg | 1 + test/pass/arrays/05_vector.c | 2 +- test/pass/arrays/07_avx.c | 2 +- test/pass/filter/08_amg_box_algebra_mock.c | 4 +- test/pass/filter/09_milc_gauge_stuff_mock.c | 6 +- test/pass/inline_types/01_simple_malloc_int.c | 30 ++ test/pass/inline_types/02_calloc_realloc.c | 31 ++ .../inline_types/03_simple_malloc_struct.c | 39 ++ test/pass/inline_types/04_fwd_decl.cpp | 30 ++ .../malloc_free/05_simple_malloc_struct.c | 2 +- test/pass/misc/05_make_all_callbacks.c | 19 +- test/pass/misc/07_config_file.c | 5 +- test/pass/misc/07_typeart_config_stack.yml | 2 + test/pass/misc/08_config_file_default.c | 3 + test/pass/misc/09_config_file_cl.c | 2 - test/pass/new_delete/03_inv_struct.cpp | 2 +- test/pass/new_delete/04_inv_struct_array.cpp | 2 +- test/pass/new_delete/05_struct_array.cpp | 2 +- .../new_delete/06_struct_array_def_dest.cpp | 2 +- .../07_struct_array_userdef_dest.cpp | 4 +- test/pass/new_delete/09_inv_struct_delete.cpp | 2 +- .../new_delete/10_inv_struct_array_delete.cpp | 2 +- test/pass/new_delete/11_new_nothrow.cpp | 2 +- test/pass/new_delete/12_new_aligned.cpp | 2 +- .../new_delete/13_new_aligned_nothrow.cpp | 2 +- test/pass/new_delete/15_array_cookie.cpp | 4 +- .../new_delete/16_array_cookie_padded.cpp | 4 +- .../17_array_cookie_dynamic_size.cpp | 2 +- .../new_delete/18_array_cookie_delete.cpp | 2 +- .../19_array_cookie_dynamic_size_opaque.cpp | 4 +- .../20_no_array_cookie_lulesh_ad.llin | 2 +- test/runtime/07_simple_struct_type_check.c | 34 +- test/runtime/08_recursive_struct_type_check.c | 24 +- test/runtime/22_threads_stack.cpp | 3 +- test/runtime/30_omp_concurrent_w.cpp | 33 +- test/runtime/41_array_cookie.cpp | 2 +- test/runtime/44_typedb.cpp | 3 + test/runtime/49_default_types_udef.c | 1 + .../01_simple_malloc_int.c | 17 + .../02_simple_malloc_int_multi_tu.c | 32 ++ .../03_simple_malloc_struct.c | 24 + test/runtime_inlined_types/04_malloc_struct.c | 29 + test/script/07_wrapper_demo.sh | 4 - test/script/12_ir_viewer.sh | 8 +- test/typemapping/01_simple_struct.c | 2 +- test/typemapping/02_recursive_struct.c | 2 +- test/typemapping/04_milc_mock.c | 2 +- test/typemapping/06_anon_struct.c | 2 +- .../07_no_ebo_heap_multi_inheritance.cpp | 2 +- .../08_ebo_only_heap_multi_inheritance.cpp | 2 +- .../09_stack_class_inheritance_virtual.cpp | 2 +- .../10_multi_inheritance_virtual.cpp | 4 +- test/typemapping/11_void_nullptr.cpp | 2 +- test/typemapping/12_complex.cpp | 2 +- test/typemapping/13_complex.c | 2 +- test/typemapping/14_union.c | 2 +- test/typemapping/15_wchar.c | 2 +- test/typemapping/16_mpi_dtype.c | 24 + 106 files changed, 1936 insertions(+), 367 deletions(-) create mode 100644 lib/passes/instrumentation/CallBackFunctionInserter.cpp create mode 100644 lib/passes/instrumentation/CallBackFunctionInserter.h create mode 100644 lib/passes/instrumentation/TypeIDProvider.cpp create mode 100644 lib/passes/instrumentation/TypeIDProvider.h create mode 100644 lib/runtime/GlobalTypeDefCallbacks.cpp create mode 100644 lib/runtime/GlobalTypeDefCallbacks.h create mode 100644 test/pass/inline_types/01_simple_malloc_int.c create mode 100644 test/pass/inline_types/02_calloc_realloc.c create mode 100644 test/pass/inline_types/03_simple_malloc_struct.c create mode 100644 test/pass/inline_types/04_fwd_decl.cpp create mode 100644 test/runtime_inlined_types/01_simple_malloc_int.c create mode 100644 test/runtime_inlined_types/02_simple_malloc_int_multi_tu.c create mode 100644 test/runtime_inlined_types/03_simple_malloc_struct.c create mode 100644 test/runtime_inlined_types/04_malloc_struct.c create mode 100644 test/typemapping/16_mpi_dtype.c diff --git a/.clang-tidy b/.clang-tidy index 624d78a8..d3c30232 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -2,7 +2,6 @@ Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,performance-*,modernize-*,llvm-namespace-comment,google-explicit-constructor,bugprone-*,misc-*,readability-*, -readability-named-parameter,-modernize-use-trailing-return-type,-modernize-use-using' WarningsAsErrors: '' HeaderFilterRegex: '' -AnalyzeTemporaryDtors: false CheckOptions: - key: google-readability-braces-around-statements.ShortStatementLines value: '1' diff --git a/.github/workflows/basic-ci.yml b/.github/workflows/basic-ci.yml index f8a39fda..39044e6b 100644 --- a/.github/workflows/basic-ci.yml +++ b/.github/workflows/basic-ci.yml @@ -12,10 +12,22 @@ env: jobs: format-check: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + + - run: | + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-18 main" | sudo tee /etc/apt/sources.list.d/llvm-18.list + + - name: Update apt + run: sudo apt-get update + + - name: Install clang-format + run: | + sudo apt-get remove clang-format-* + sudo apt-get install -t llvm-toolchain-noble-18 clang-format-18 - name: Format source code run: | @@ -24,7 +36,7 @@ jobs: -a \( -name "*.c" -o -name "*.cpp" -o -name "*.h" \) \ -not -path "*/lulesh/*" -not -path "*/CallSite.h" \ -print0 \ - | xargs -0 clang-format-14 -i + | xargs -0 clang-format-18 -i - name: Format check run: | @@ -35,7 +47,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: codespell-project/actions-codespell@v2 lit-suite: @@ -73,7 +85,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: LLVM apt if: ${{ matrix.llvm-version == 19 }} diff --git a/.github/workflows/ext-ci.yml b/.github/workflows/ext-ci.yml index 9d16f848..dffa84f1 100644 --- a/.github/workflows/ext-ci.yml +++ b/.github/workflows/ext-ci.yml @@ -31,10 +31,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Checkout test-bench - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: tudasc/typeart-bench ssh-key: ${{ secrets.AUTH_SSH_CI_EXT }} @@ -129,10 +129,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Checkout AD test-bench - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: ahueck/typeart-ad-benchmarks ssh-key: ${{ secrets.AUTH_SSH_CI_EXT_AD }} @@ -215,10 +215,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Checkout OMP test-bench - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: tudasc/typeart-bench ssh-key: ${{ secrets.AUTH_SSH_CI_EXT }} diff --git a/demo/Makefile b/demo/Makefile index 16dd527b..3224b55b 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -3,7 +3,7 @@ MPIRUN ?= mpirun MPICC ?= typeart-mpicc # instead of standard mpicc -all: libtool.so 01_ex 02_ex toy toy-stack +all: libtool.so demo demo_broken libtool.so: tool.c $(MPICC) -shared -fPIC $< -o $@ diff --git a/externals/abseil/CMakeLists.txt b/externals/abseil/CMakeLists.txt index cf6c35a8..c47f6890 100644 --- a/externals/abseil/CMakeLists.txt +++ b/externals/abseil/CMakeLists.txt @@ -3,7 +3,7 @@ set(ABSL_PROPAGATE_CXX_STD ON) FetchContent_Declare( cpp-abseil GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git - GIT_TAG 20240722.1 + GIT_TAG 20250814.1 GIT_SHALLOW 1 ) diff --git a/lib/passes/CMakeLists.txt b/lib/passes/CMakeLists.txt index 7d8f44af..0346d7f0 100644 --- a/lib/passes/CMakeLists.txt +++ b/lib/passes/CMakeLists.txt @@ -12,6 +12,8 @@ set(PASS_SOURCES instrumentation/MemOpArgCollector.cpp instrumentation/MemOpInstrumentation.cpp instrumentation/Instrumentation.cpp + instrumentation/TypeIDProvider.cpp + instrumentation/CallBackFunctionInserter.cpp TypeARTConfiguration.cpp Commandline.cpp ) diff --git a/lib/passes/Commandline.cpp b/lib/passes/Commandline.cpp index 204766ef..3ea91a4e 100644 --- a/lib/passes/Commandline.cpp +++ b/lib/passes/Commandline.cpp @@ -15,6 +15,7 @@ #include "analysis/MemInstFinder.h" #include "configuration/Configuration.h" #include "configuration/EnvironmentConfiguration.h" +#include "instrumentation/TypeIDProvider.h" #include "support/ConfigurationBase.h" #include "support/Logger.h" #include "typegen/TypeGenerator.h" @@ -83,6 +84,15 @@ static cl::opt cl_typeart_instrument_stack(Commandl cl::init(ConfigStdArgValues::stack), cl::cat(typeart_category)); +static cl::opt cl_typeart_type_serialization( + CommandlineStdArgs::type_serialization, cl::desc(ConfigStdArgDescriptions::type_serialization), + cl::values(clEnumValN(typeart::TypeSerializationImplementation::FILE, "file", "File based type serialization"), + clEnumValN(typeart::TypeSerializationImplementation::INLINE, "inline", + "Type descriptors through global variables"), + clEnumValN(typeart::TypeSerializationImplementation::HYBRID, "hybrid", + "Type descriptors through global variables except for C/C++ built-in types")), + cl::Hidden, cl::init(typeart::TypeSerializationImplementation::FILE), cl::cat(typeart_category)); + static cl::opt cl_typeart_instrument_stack_lifetime( CommandlineStdArgs::stack_lifetime, cl::desc(ConfigStdArgDescriptions::stack_lifetime), cl::init(ConfigStdArgValues::stack_lifetime), cl::cat(typeart_category)); @@ -198,6 +208,7 @@ CommandLineOptions::CommandLineOptions() { make_entry(ConfigStdArgs::heap, cl_typeart_instrument_heap), make_entry(ConfigStdArgs::global, cl_typeart_instrument_global), make_entry(ConfigStdArgs::stack, cl_typeart_instrument_stack), + make_entry(ConfigStdArgs::type_serialization, cl_typeart_type_serialization), make_entry(ConfigStdArgs::stack_lifetime, cl_typeart_instrument_stack_lifetime), make_entry(ConfigStdArgs::typegen, cl_typeart_typegen_implementation), make_entry(ConfigStdArgs::filter, cl_typeart_call_filter), @@ -217,6 +228,7 @@ CommandLineOptions::CommandLineOptions() { make_occurr_entry(ConfigStdArgs::heap, cl_typeart_instrument_heap), make_occurr_entry(ConfigStdArgs::global, cl_typeart_instrument_global), make_occurr_entry(ConfigStdArgs::stack, cl_typeart_instrument_stack), + make_occurr_entry(ConfigStdArgs::type_serialization, cl_typeart_type_serialization), make_occurr_entry(ConfigStdArgs::stack_lifetime, cl_typeart_instrument_stack_lifetime), make_occurr_entry(ConfigStdArgs::typegen, cl_typeart_typegen_implementation), make_occurr_entry(ConfigStdArgs::filter, cl_typeart_call_filter), diff --git a/lib/passes/TypeARTPass.cpp b/lib/passes/TypeARTPass.cpp index 23bc5afa..eed4416e 100644 --- a/lib/passes/TypeARTPass.cpp +++ b/lib/passes/TypeARTPass.cpp @@ -19,9 +19,11 @@ #include "configuration/PassBuilderUtil.h" #include "configuration/PassConfiguration.h" #include "configuration/TypeARTOptions.h" +#include "instrumentation/CallBackFunctionInserter.h" #include "instrumentation/MemOpArgCollector.h" #include "instrumentation/MemOpInstrumentation.h" #include "instrumentation/TypeARTFunctions.h" +#include "instrumentation/TypeIDProvider.h" #include "support/ConfigurationBase.h" #include "support/Logger.h" #include "support/ModuleDumper.h" @@ -48,7 +50,9 @@ #include #include +#include #include +#include #include #include #include @@ -95,26 +99,10 @@ class TypeArtPass : public llvm::PassInfoMixin { std::optional pass_opts{std::nullopt}; std::unique_ptr pass_config; - struct TypeArtFunc { - const std::string name; - llvm::Value* f{nullptr}; - }; - - TypeArtFunc typeart_alloc{"__typeart_alloc"}; - TypeArtFunc typeart_alloc_global{"__typeart_alloc_global"}; - TypeArtFunc typeart_alloc_stack{"__typeart_alloc_stack"}; - TypeArtFunc typeart_free{"__typeart_free"}; - TypeArtFunc typeart_leave_scope{"__typeart_leave_scope"}; - - TypeArtFunc typeart_alloc_omp = typeart_alloc; - TypeArtFunc typeart_alloc_stacks_omp = typeart_alloc_stack; - TypeArtFunc typeart_free_omp = typeart_free; - TypeArtFunc typeart_leave_scope_omp = typeart_leave_scope; - std::unique_ptr meminst_finder; std::unique_ptr typeManager; InstrumentationHelper instrumentation_helper; - TAFunctions functions; + std::unique_ptr functions; std::unique_ptr instrumentation_context; const config::Configuration& configuration() const { @@ -168,15 +156,27 @@ class TypeArtPass : public llvm::PassInfoMixin { instrumentation_helper.setModule(m); ModuleData mdata{&m}; - typeManager->registerModule(mdata); + const auto has_cu_types = typeManager->registerModule(mdata); + + declareInstrumentationFunctions(m); + { + auto type_id_handler = get_type_id_handler(m, &typeManager->getTypeDatabase(), configuration(), functions.get()); + // const bool heap = configuration()[config::ConfigStdArgs::heap]; + if (has_cu_types) { + LOG_DEBUG("Registering compilation unit types list") + type_id_handler->registerModule(mdata); + } - auto arg_collector = - std::make_unique(configuration(), typeManager.get(), instrumentation_helper); - // const bool instrument_stack_lifetime = configuration()[config::ConfigStdArgs::stack_lifetime]; - auto mem_instrument = std::make_unique(configuration(), functions, instrumentation_helper); - instrumentation_context = - std::make_unique(std::move(arg_collector), std::move(mem_instrument)); + auto arg_collector = + std::make_unique(configuration(), typeManager.get(), instrumentation_helper); + // const bool instrument_stack_lifetime = configuration()[config::ConfigStdArgs::stack_lifetime]; + auto cb_provider = make_callback_inserter(configuration(), std::move(type_id_handler), functions.get()); + auto mem_instrument = std::make_unique(configuration(), functions.get(), + instrumentation_helper, std::move(cb_provider)); + instrumentation_context = + std::make_unique(std::move(arg_collector), std::move(mem_instrument)); + } return true; } @@ -184,16 +184,20 @@ class TypeArtPass : public llvm::PassInfoMixin { /* * Persist the accumulated type definition information for this module. */ - const std::string types_file = configuration()[config::ConfigStdArgs::types]; - LOG_DEBUG("Writing type file to " << types_file); - - const auto [stored, error] = typeManager->store(); - if (stored) { - LOG_DEBUG("Success!"); - } else { - LOG_FATAL("Failed writing type config to " << types_file << ". Reason: " << error.message()); + // TODO: inline/hybrid types not supported in non-opaque mode + const bool emit_type_file_always = bool(LLVM_VERSION_MAJOR < 15); + TypeSerializationImplementation mode = configuration()[config::ConfigStdArgs::type_serialization]; + if (emit_type_file_always || mode == TypeSerializationImplementation::FILE) { + const std::string types_file = configuration()[config::ConfigStdArgs::types]; + LOG_DEBUG("Writing type file to " << types_file); + + const auto [stored, error] = typeManager->store(); + if (stored) { + LOG_DEBUG("Success!"); + } else { + LOG_FATAL("Failed writing type config to " << types_file << ". Reason: " << error.message()); + } } - const bool print_stats = configuration()[config::ConfigStdArgs::stats]; if (print_stats) { auto& out = llvm::errs(); @@ -203,30 +207,7 @@ class TypeArtPass : public llvm::PassInfoMixin { } void declareInstrumentationFunctions(Module& m) { - // Remove this return if problems come up during compilation - if (typeart_alloc_global.f != nullptr && typeart_alloc_stack.f != nullptr && typeart_alloc.f != nullptr && - typeart_free.f != nullptr && typeart_leave_scope.f != nullptr) { - return; - } - - TAFunctionDeclarator decl(m, instrumentation_helper, functions); - - auto alloc_arg_types = instrumentation_helper.make_parameters(IType::ptr, IType::type_id, IType::extent); - auto free_arg_types = instrumentation_helper.make_parameters(IType::ptr); - auto leavescope_arg_types = instrumentation_helper.make_parameters(IType::stack_count); - - typeart_alloc.f = decl.make_function(IFunc::heap, typeart_alloc.name, alloc_arg_types); - typeart_alloc_stack.f = decl.make_function(IFunc::stack, typeart_alloc_stack.name, alloc_arg_types); - typeart_alloc_global.f = decl.make_function(IFunc::global, typeart_alloc_global.name, alloc_arg_types); - typeart_free.f = decl.make_function(IFunc::free, typeart_free.name, free_arg_types); - typeart_leave_scope.f = decl.make_function(IFunc::scope, typeart_leave_scope.name, leavescope_arg_types); - - typeart_alloc_omp.f = decl.make_function(IFunc::heap_omp, typeart_alloc_omp.name, alloc_arg_types, true); - typeart_alloc_stacks_omp.f = - decl.make_function(IFunc::stack_omp, typeart_alloc_stacks_omp.name, alloc_arg_types, true); - typeart_free_omp.f = decl.make_function(IFunc::free_omp, typeart_free_omp.name, free_arg_types, true); - typeart_leave_scope_omp.f = - decl.make_function(IFunc::scope_omp, typeart_leave_scope_omp.name, leavescope_arg_types, true); + functions = declare_instrumentation_functions(m, configuration()); } void printStats(llvm::raw_ostream& out) { @@ -292,7 +273,7 @@ class TypeArtPass : public llvm::PassInfoMixin { const bool instrument_global = configuration()[config::ConfigStdArgs::global]; bool globals_were_instrumented{false}; if (instrument_global) { - declareInstrumentationFunctions(m); + // declareInstrumentationFunctions(m); const auto& globalsList = meminst_finder->getModuleGlobals(); if (!globalsList.empty()) { @@ -322,7 +303,7 @@ class TypeArtPass : public llvm::PassInfoMixin { // FIXME this is required when "PassManagerBuilder::EP_OptimizerLast" is used as the function (constant) pointer are // nullpointer/invalidated - declareInstrumentationFunctions(*f.getParent()); + // declareInstrumentationFunctions(*f.getParent()); bool mod{false}; // auto& c = f.getContext(); @@ -364,7 +345,7 @@ class LegacyTypeArtPass : public llvm::ModulePass { public: static char ID; // NOLINT - LegacyTypeArtPass() : ModulePass(ID){}; + LegacyTypeArtPass() : ModulePass(ID) {}; bool doInitialization(llvm::Module&) override; @@ -399,8 +380,9 @@ llvm::PassPluginLibraryInfo getTypeartPassPluginInfo() { using namespace llvm; return {LLVM_PLUGIN_API_VERSION, "TypeART", LLVM_VERSION_STRING, [](PassBuilder& pass_builder) { pass_builder.registerPipelineStartEPCallback([](auto& MPM, OptimizationLevel) { - auto parameters = typeart::util::pass::parsePassParameters(typeart::config::pass::parse_typeart_config, - "typeart", "typeart"); + auto parameters = + typeart::util::pass::parsePassParameters(typeart::config::pass::parse_typeart_config, + "typeart", "typeart"); if (!parameters) { LOG_FATAL("Error parsing heap params: " << parameters.takeError()) return; @@ -408,8 +390,9 @@ llvm::PassPluginLibraryInfo getTypeartPassPluginInfo() { MPM.addPass(typeart::pass::TypeArtPass(typeart::pass::TypeArtPass(parameters.get()))); }); pass_builder.registerOptimizerLastEPCallback([](auto& MPM, OptimizationLevel) { - auto parameters = typeart::util::pass::parsePassParameters(typeart::config::pass::parse_typeart_config, - "typeart", "typeart"); + auto parameters = typeart::util::pass::parsePassParameters( + typeart::config::pass::parse_typeart_config, "typeart", + "typeart"); if (!parameters) { LOG_FATAL("Error parsing stack params: " << parameters.takeError()) return; diff --git a/lib/passes/analysis/MemInstFinder.cpp b/lib/passes/analysis/MemInstFinder.cpp index 051fc85b..27bfb9ec 100644 --- a/lib/passes/analysis/MemInstFinder.cpp +++ b/lib/passes/analysis/MemInstFinder.cpp @@ -193,7 +193,7 @@ bool MemInstFinderPass::runOnModule(Module& module) { } if (util::starts_with_any_of(name, "llvm.", "__llvm_gcov", "__llvm_gcda", "__profn", "___asan", - "__msan", "__tsan")) { + "__msan", "__tsan", "__typeart", "_typeart")) { LOG_DEBUG("Prefixed matched on " << name) return true; } diff --git a/lib/passes/configuration/EnvironmentConfiguration.cpp b/lib/passes/configuration/EnvironmentConfiguration.cpp index 339ff524..2d43fa8a 100644 --- a/lib/passes/configuration/EnvironmentConfiguration.cpp +++ b/lib/passes/configuration/EnvironmentConfiguration.cpp @@ -16,6 +16,7 @@ #include "OptionsUtil.h" #include "PassConfiguration.h" #include "configuration/TypeARTOptions.h" +#include "instrumentation/TypeIDProvider.h" #include "support/ConfigurationBase.h" #include "support/Logger.h" #include "support/Util.h" @@ -113,6 +114,9 @@ EnvironmentFlagsOptions::EnvironmentFlagsOptions() { EnvironmentStdArgsValues::global), make_entry(ConfigStdArgs::stack, EnvironmentStdArgs::stack, EnvironmentStdArgsValues::stack), + make_entry(ConfigStdArgs::type_serialization, + EnvironmentStdArgs::type_serialization, + EnvironmentStdArgsValues::type_serialization), make_entry( ConfigStdArgs::stack_lifetime, EnvironmentStdArgs::stack_lifetime, EnvironmentStdArgsValues::stack_lifetime), make_entry(ConfigStdArgs::typegen, EnvironmentStdArgs::typegen, @@ -148,6 +152,7 @@ EnvironmentFlagsOptions::EnvironmentFlagsOptions() { make_occurr_entry(ConfigStdArgs::heap, EnvironmentStdArgs::heap), make_occurr_entry(ConfigStdArgs::global, EnvironmentStdArgs::global), make_occurr_entry(ConfigStdArgs::stack, EnvironmentStdArgs::stack), + make_occurr_entry(ConfigStdArgs::type_serialization, EnvironmentStdArgs::type_serialization), make_occurr_entry(ConfigStdArgs::stack_lifetime, EnvironmentStdArgs::stack_lifetime), make_occurr_entry(ConfigStdArgs::typegen, EnvironmentStdArgs::typegen), make_occurr_entry(ConfigStdArgs::filter, EnvironmentStdArgs::filter), diff --git a/lib/passes/configuration/OptionsUtil.h b/lib/passes/configuration/OptionsUtil.h index 1c308565..f44ac0c4 100644 --- a/lib/passes/configuration/OptionsUtil.h +++ b/lib/passes/configuration/OptionsUtil.h @@ -10,10 +10,11 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef TYPEART_CONFIGURATION_OPTIONS_UTIL_H -#define TYPEART_CONFIGURATION_OPTIONS_UTIL_H +#ifndef LIB_PASSES_CONFIGURATION_OPTIONSUTIL +#define LIB_PASSES_CONFIGURATION_OPTIONSUTIL #include "analysis/MemInstFinder.h" +#include "instrumentation/TypeIDProvider.h" #include "support/Logger.h" #include "typegen/TypeGenerator.h" @@ -30,6 +31,7 @@ bool with_any_of(llvm::StringRef lhs, Strings&&... rhs) { template ClType string_to_enum(llvm::StringRef cl_value) { using ::typeart::TypegenImplementation; + using ::typeart::TypeSerializationImplementation; using ::typeart::analysis::FilterImplementation; if constexpr (std::is_same_v) { auto val = llvm::StringSwitch(cl_value) @@ -38,12 +40,21 @@ ClType string_to_enum(llvm::StringRef cl_value) { .Default(TypegenImplementation::DIMETA); return val; } else { - auto val = llvm::StringSwitch(cl_value) - .Case("cg", FilterImplementation::cg) - .Case("none", FilterImplementation::none) - .Case("std", FilterImplementation::standard) - .Default(FilterImplementation::standard); - return val; + if constexpr (std::is_same_v) { + auto val = llvm::StringSwitch(cl_value) + .Case("cg", FilterImplementation::cg) + .Case("none", FilterImplementation::none) + .Case("std", FilterImplementation::standard) + .Default(FilterImplementation::standard); + return val; + } else { + auto val = llvm::StringSwitch(cl_value) + .Case("file", TypeSerializationImplementation::FILE) + .Case("hybrid", TypeSerializationImplementation::HYBRID) + .Case("inline", TypeSerializationImplementation::INLINE) + .Default(TypeSerializationImplementation::INLINE); + return val; + } } } @@ -69,4 +80,4 @@ ClType make_opt(llvm::StringRef cl_value) { } } // namespace typeart::config::util -#endif /* TYPEART_CONFIGURATION_OPTIONS_UTIL_H */ +#endif /* LIB_PASSES_CONFIGURATION_OPTIONSUTIL */ diff --git a/lib/passes/configuration/PassBuilderUtil.h b/lib/passes/configuration/PassBuilderUtil.h index bebeda9d..8908e2f5 100644 --- a/lib/passes/configuration/PassBuilderUtil.h +++ b/lib/passes/configuration/PassBuilderUtil.h @@ -52,8 +52,8 @@ inline bool checkParametrizedPassName(llvm::StringRef Name, llvm::StringRef Pass /// Expected<> template class. /// template -inline auto parsePassParameters(ParametersParseCallableT&& Parser, llvm::StringRef Name, llvm::StringRef PassName) - -> decltype(Parser(llvm::StringRef{})) { +inline auto parsePassParameters(ParametersParseCallableT&& Parser, llvm::StringRef Name, + llvm::StringRef PassName) -> decltype(Parser(llvm::StringRef{})) { using namespace llvm; using ParametersT = typename decltype(Parser(StringRef{}))::value_type; diff --git a/lib/passes/configuration/PassConfiguration.cpp b/lib/passes/configuration/PassConfiguration.cpp index 24177765..659aab1f 100644 --- a/lib/passes/configuration/PassConfiguration.cpp +++ b/lib/passes/configuration/PassConfiguration.cpp @@ -15,6 +15,7 @@ #include "OptionsUtil.h" #include "analysis/MemInstFinder.h" #include "configuration/Configuration.h" +#include "instrumentation/TypeIDProvider.h" #include "support/ConfigurationBase.h" #include "support/ConfigurationBaseOptions.h" #include "support/Error.h" @@ -102,6 +103,12 @@ PassConfig parse_typeart_config_with_occurrence(llvm::StringRef parameters) { continue; } + if (parameter_name.consume_front(PassStdArgsEq::type_serialization)) { + result.type_serialization = util::string_to_enum(parameter_name); + occurrence_map[ConfigStdArgs::type_serialization] = true; + continue; + } + if (parameter_name.consume_front(PassStdArgsEq::filter_glob)) { result.filter_config.glob = parameter_name; occurrence_map[ConfigStdArgs::filter_glob] = true; diff --git a/lib/passes/configuration/TypeARTOptions.cpp b/lib/passes/configuration/TypeARTOptions.cpp index 00a1d113..db1a76eb 100644 --- a/lib/passes/configuration/TypeARTOptions.cpp +++ b/lib/passes/configuration/TypeARTOptions.cpp @@ -14,6 +14,7 @@ #include "Configuration.h" #include "FileConfiguration.h" +#include "instrumentation/TypeIDProvider.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -24,6 +25,15 @@ using namespace llvm::yaml; using namespace typeart::config::file; +template <> +struct llvm::yaml::ScalarEnumerationTraits { + static void enumeration(IO& io, typeart::TypeSerializationImplementation& value) { + io.enumCase(value, "inline", typeart::TypeSerializationImplementation::INLINE); + io.enumCase(value, "file", typeart::TypeSerializationImplementation::FILE); + io.enumCase(value, "hybrid", typeart::TypeSerializationImplementation::HYBRID); + } +}; + template <> struct llvm::yaml::ScalarEnumerationTraits { static void enumeration(IO& io, typeart::analysis::FilterImplementation& value) { @@ -85,6 +95,7 @@ struct llvm::yaml::MappingTraits { yml_io.mapOptional(ConfigStdArgs::stats, info.statistics); yml_io.mapOptional(ConfigStdArgs::stack_lifetime, info.stack_lifetime); yml_io.mapRequired(ConfigStdArgs::typegen, info.typegen); + yml_io.mapRequired(ConfigStdArgs::type_serialization, info.type_serialization); yml_io.mapRequired(ConfigStdArgs::filter, info.filter); yml_io.mapOptional("call-filter", info.filter_config); yml_io.mapOptional("analysis", info.analysis_config); @@ -140,6 +151,7 @@ TypeARTConfigOptions construct_with(Constructor&& make_entry) { make_entry(ConfigStdArgs::analysis_filter_pointer_alloc, config.analysis_config.filter_pointer_alloc); make_entry(ConfigStdArgs::analysis_filter_alloca_non_array, config.analysis_config.filter_alloca_non_array); make_entry(ConfigStdArgs::typegen, config.typegen); + make_entry(ConfigStdArgs::type_serialization, config.type_serialization); return config; } @@ -160,8 +172,8 @@ TypeARTConfigOptions config_to_options(const Configuration& configuration) { } template -auto make_entry(std::string_view key, const T& field_value) - -> std::pair { +auto make_entry(std::string_view key, + const T& field_value) -> std::pair { if constexpr (std::is_enum_v) { return {key, config::OptionValue{static_cast(field_value)}}; } else { @@ -187,9 +199,10 @@ OptionsMap options_to_map(const TypeARTConfigOptions& config) { make_entry(ConfigStdArgs::analysis_filter_heap_alloc, config.analysis_config.filter_heap_alloc), make_entry(ConfigStdArgs::analysis_filter_pointer_alloc, config.analysis_config.filter_pointer_alloc), make_entry(ConfigStdArgs::analysis_filter_alloca_non_array, config.analysis_config.filter_alloca_non_array), + make_entry(ConfigStdArgs::type_serialization, config.type_serialization), }; return mapping_; -} +} // namespace helper } // namespace helper diff --git a/lib/passes/configuration/TypeARTOptions.h b/lib/passes/configuration/TypeARTOptions.h index 7110bed1..edccff6f 100644 --- a/lib/passes/configuration/TypeARTOptions.h +++ b/lib/passes/configuration/TypeARTOptions.h @@ -10,11 +10,12 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef TYPEART_CONFIGURATION_OPTIONS_H -#define TYPEART_CONFIGURATION_OPTIONS_H +#ifndef LIB_PASSES_CONFIGURATION_TYPEARTOPTIONS +#define LIB_PASSES_CONFIGURATION_TYPEARTOPTIONS #include "analysis/MemInstFinder.h" #include "configuration/Configuration.h" +#include "instrumentation/TypeIDProvider.h" #include "support/ConfigurationBase.h" #include "typegen/TypeGenerator.h" @@ -50,6 +51,11 @@ struct TypeARTConfigOptions { bool statistics{ConfigStdArgValues::stats}; bool stack_lifetime{ConfigStdArgValues::stack_lifetime}; TypegenImplementation typegen{TypegenImplementation::DIMETA}; +#if LLVM_VERSION_MAJOR > 14 + TypeSerializationImplementation type_serialization{TypeSerializationImplementation::HYBRID}; +#else + TypeSerializationImplementation type_serialization{TypeSerializationImplementation::FILE}; +#endif bool filter{false}; TypeARTCallFilterOptions filter_config{}; @@ -76,4 +82,4 @@ llvm::raw_ostream& operator<<(llvm::raw_ostream& out_s, const TypeARTConfigOptio } // namespace typeart::config -#endif /* TYPEART_CONFIGURATION_OPTIONS_H */ +#endif /* LIB_PASSES_CONFIGURATION_TYPEARTOPTIONS */ diff --git a/lib/passes/filter/FilterUtil.h b/lib/passes/filter/FilterUtil.h index 9878b8aa..c54ca2f5 100644 --- a/lib/passes/filter/FilterUtil.h +++ b/lib/passes/filter/FilterUtil.h @@ -46,8 +46,12 @@ using namespace llvm; namespace typeart::filter { struct FunctionAnalysis { - using FunctionCounts = struct { int decl, def, intrinsic, indirect; }; - using FunctionCalls = struct { llvm::SmallVector decl, def, intrinsic, indirect; }; + using FunctionCounts = struct { + int decl, def, intrinsic, indirect; + }; + using FunctionCalls = struct { + llvm::SmallVector decl, def, intrinsic, indirect; + }; FunctionCalls calls; diff --git a/lib/passes/instrumentation/CallBackFunctionInserter.cpp b/lib/passes/instrumentation/CallBackFunctionInserter.cpp new file mode 100644 index 00000000..cd89f9f7 --- /dev/null +++ b/lib/passes/instrumentation/CallBackFunctionInserter.cpp @@ -0,0 +1,94 @@ +#include "CallBackFunctionInserter.h" + +#include "configuration/Configuration.h" +#include "instrumentation/TypeIDProvider.h" +#include "support/ConfigurationBase.h" +#include "support/Logger.h" + +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IRBuilder.h" + +#include + +namespace typeart { + +class CallbackFunctionInserter final : public InstrumentationInserter { + std::unique_ptr type_id_handler_; + TAFunctionQuery* function_query_; + TypeSerializationImplementation mode_; + // bool mixed_mode{false}; + + private: + llvm::CallInst* create_instrumentation_call(llvm::IRBuilder<>& IRB, IFunc callback_type, + llvm::Value* instruction_or_value, InstrumentationPayload args); + + public: + CallbackFunctionInserter(const config::Configuration& configuration, std::unique_ptr type_id_handler, + TAFunctionQuery* function_query); + + llvm::CallInst* insert_heap_instrumentation(llvm::IRBuilder<>& IRB, llvm::CallBase* heap_call, + InstrumentationPayload) override; + + llvm::CallInst* insert_stack_instrumentation(llvm::IRBuilder<>& IRB, llvm::Instruction* alloca, + InstrumentationPayload) override; + + llvm::CallInst* insert_global_instrumentation(llvm::IRBuilder<>& IRB, llvm::GlobalValue* global_var, + InstrumentationPayload) override; + + llvm::CallInst* insert_free_instrumentation(llvm::IRBuilder<>& IRB, llvm::CallBase* call, + llvm::Value* pointer_value) override; +}; + +CallbackFunctionInserter::CallbackFunctionInserter(const config::Configuration& configuration, + std::unique_ptr type_id_handler, + TAFunctionQuery* function_query) + : type_id_handler_(std::move(type_id_handler)), function_query_(function_query) { + mode_ = configuration[config::ConfigStdArgs::type_serialization]; + // mixed_mode = value == TypeSerializationImplementation::HYBRID; +} + +// Private Helper Definition +llvm::CallInst* CallbackFunctionInserter::create_instrumentation_call(llvm::IRBuilder<>& IRB, IFunc callback_type, + llvm::Value* instruction_or_value, + InstrumentationPayload args) { + const auto callback_id = ifunc_for_function(callback_type, instruction_or_value); + auto type_id_param_out = type_id_handler_->getOrRegister(args.typeid_value); + + const auto mode = llvm::isa(type_id_param_out) ? mode_ : TypeSerializationImplementation::FILE; + auto function = function_query_->getFunctionFor(callback_id, mode); + + return IRB.CreateCall(function, + llvm::ArrayRef{args.pointer_value, type_id_param_out, args.element_count}); +} + +llvm::CallInst* CallbackFunctionInserter::insert_heap_instrumentation(llvm::IRBuilder<>& IRB, llvm::CallBase* heap_call, + InstrumentationPayload args) { + return create_instrumentation_call(IRB, IFunc::heap, heap_call, args); +} + +llvm::CallInst* CallbackFunctionInserter::insert_stack_instrumentation(llvm::IRBuilder<>& IRB, + llvm::Instruction* alloca, + InstrumentationPayload args) { + return create_instrumentation_call(IRB, IFunc::stack, alloca, args); +} + +llvm::CallInst* CallbackFunctionInserter::insert_global_instrumentation(llvm::IRBuilder<>& IRB, + llvm::GlobalValue* global_var, + InstrumentationPayload args) { + return create_instrumentation_call(IRB, IFunc::global, global_var, args); +} + +llvm::CallInst* CallbackFunctionInserter::insert_free_instrumentation(llvm::IRBuilder<>& IRB, llvm::CallBase* call, + llvm::Value* pointer_value) { + const auto callback_id = ifunc_for_function(IFunc::free, call); + return IRB.CreateCall(function_query_->getFunctionFor(callback_id), llvm::ArrayRef{pointer_value}); +} + +std::unique_ptr make_callback_inserter(const config::Configuration& configuration, + std::unique_ptr type_id_handler, + TAFunctionQuery* function_query) { + return std::make_unique(configuration, std::move(type_id_handler), function_query); +} + +} // namespace typeart \ No newline at end of file diff --git a/lib/passes/instrumentation/CallBackFunctionInserter.h b/lib/passes/instrumentation/CallBackFunctionInserter.h new file mode 100644 index 00000000..70e88737 --- /dev/null +++ b/lib/passes/instrumentation/CallBackFunctionInserter.h @@ -0,0 +1,54 @@ +#ifndef LIB_PASSES_INSTRUMENTATION_CALLBACKFUNCTIONINSERTER +#define LIB_PASSES_INSTRUMENTATION_CALLBACKFUNCTIONINSERTER + +#include "instrumentation/TypeARTFunctions.h" + +#include "llvm/IR/IRBuilder.h" + +#include + +namespace llvm { +class CallInst; +class Value; +class CallBase; +class Instruction; +class GlobalValue; +} // namespace llvm + +namespace typeart { +namespace config { +class Configuration; +} +class TypeRegistry; +class TAFunctionQuery; + +struct InstrumentationPayload { + llvm::Value* pointer_value; + llvm::Value* element_count; + llvm::Value* typeid_value; +}; + +class InstrumentationInserter { + public: + virtual ~InstrumentationInserter() = default; + + virtual llvm::CallInst* insert_heap_instrumentation(llvm::IRBuilder<>& IRB, llvm::CallBase* heap_call, + InstrumentationPayload) = 0; + + virtual llvm::CallInst* insert_stack_instrumentation(llvm::IRBuilder<>& IRB, llvm::Instruction* alloca, + InstrumentationPayload) = 0; + + virtual llvm::CallInst* insert_global_instrumentation(llvm::IRBuilder<>& IRB, llvm::GlobalValue* global_var, + InstrumentationPayload) = 0; + + virtual llvm::CallInst* insert_free_instrumentation(llvm::IRBuilder<>& IRB, llvm::CallBase* heap_call, + llvm::Value* pointer_value) = 0; +}; + +std::unique_ptr make_callback_inserter(const config::Configuration& configuration, + std::unique_ptr type_id_handler, + TAFunctionQuery* function_query); + +} // namespace typeart + +#endif /* LIB_PASSES_INSTRUMENTATION_CALLBACKFUNCTIONINSERTER */ diff --git a/lib/passes/instrumentation/InstrumentationHelper.h b/lib/passes/instrumentation/InstrumentationHelper.h index 081f1d5d..38d2a322 100644 --- a/lib/passes/instrumentation/InstrumentationHelper.h +++ b/lib/passes/instrumentation/InstrumentationHelper.h @@ -60,7 +60,6 @@ class InstrumentationHelper { llvm::Type* getTypeFor(IType id); llvm::ConstantInt* getConstantFor(IType id, size_t val = 0); - const std::map& getFunctionMap() const; virtual ~InstrumentationHelper(); }; diff --git a/lib/passes/instrumentation/MemOpInstrumentation.cpp b/lib/passes/instrumentation/MemOpInstrumentation.cpp index 5a763dc2..b50f1fc2 100644 --- a/lib/passes/instrumentation/MemOpInstrumentation.cpp +++ b/lib/passes/instrumentation/MemOpInstrumentation.cpp @@ -19,6 +19,8 @@ #include "TypeInterface.h" #include "analysis/MemOpData.h" #include "configuration/Configuration.h" +#include "instrumentation/CallBackFunctionInserter.h" +#include "instrumentation/TypeIDProvider.h" #include "support/ConfigurationBase.h" #include "support/Logger.h" #include "support/OmpUtil.h" @@ -41,6 +43,8 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/ModuleUtils.h" +#include +#include #include namespace llvm { @@ -51,9 +55,14 @@ using namespace llvm; namespace typeart { -MemOpInstrumentation::MemOpInstrumentation(const config::Configuration& typeart_conf, TAFunctionQuery& fquery, - InstrumentationHelper& instr) - : MemoryInstrument(), typeart_config(typeart_conf), function_query(&fquery), instrumentation_helper(&instr) { +MemOpInstrumentation::MemOpInstrumentation(const config::Configuration& typeart_conf, TAFunctionQuery* fquery, + InstrumentationHelper& instr, + std::unique_ptr function_instrumenter) + : MemoryInstrument(), + typeart_config(typeart_conf), + function_query(fquery), + instrumentation_helper(&instr), + function_instrumenter_(std::move(function_instrumenter)) { instrument_lifetime = typeart_config[config::ConfigStdArgs::stack_lifetime]; } @@ -61,6 +70,7 @@ InstrCount MemOpInstrumentation::instrumentHeap(const HeapArgList& heap) { InstrCount counter{0}; auto type_gen = typeart_config[config::ConfigStdArgs::typegen]; const bool is_llvm_ir_type = static_cast(type_gen) == static_cast(TypegenImplementation::IR); + for (const auto& [malloc, args] : heap) { auto kind = malloc.kind; auto* malloc_call = args.get_as(ArgMap::ID::pointer); @@ -87,8 +97,8 @@ InstrCount MemOpInstrumentation::instrumentHeap(const HeapArgList& heap) { Value* element_count{nullptr}; - auto parent_f = malloc.call->getFunction(); - const bool omp = util::omp::isOmpContext(parent_f); + // auto parent_f = malloc.call->getFunction(); + // const bool omp = util::omp::isOmpContext(parent_f); const bool dimeta_calc_byte_size = !is_llvm_ir_type && (typeid_value->equalsInt(TYPEART_VOID)); @@ -129,9 +139,8 @@ InstrCount MemOpInstrumentation::instrumentHeap(const HeapArgList& heap) { element_count = calculate_element_count(bytes); IRBuilder<> free_before_realloc(malloc_call); - const auto callback_id = omp ? IFunc::free_omp : IFunc::free; - free_before_realloc.CreateCall(function_query->getFunctionFor(callback_id), - ArrayRef{target_memory_address}); + function_instrumenter_->insert_free_instrumentation(free_before_realloc, llvm::dyn_cast(malloc_call), + target_memory_address); break; } default: @@ -139,9 +148,12 @@ InstrCount MemOpInstrumentation::instrumentHeap(const HeapArgList& heap) { continue; } - const auto callback_id = omp ? IFunc::heap_omp : IFunc::heap; - IRB.CreateCall(function_query->getFunctionFor(callback_id), - ArrayRef{malloc_call, typeid_value, element_count}); + function_instrumenter_->insert_heap_instrumentation(IRB, malloc.call, {malloc_call, element_count, typeid_value}); + + // const auto callback_id = ifunc_for_function(IFunc::heap, malloc.call); + // auto type_id_param = function_instrumenter->getOrRegister(typeid_value); + // IRB.CreateCall(function_query->getFunctionFor(callback_id), + // ArrayRef{malloc_call, type_id_param, element_count}); ++counter; } @@ -174,10 +186,13 @@ InstrCount MemOpInstrumentation::instrumentFree(const FreeArgList& frees) { IRBuilder<> IRB(insertBefore); - auto parent_f = fdata.call->getFunction(); - const auto callback_id = util::omp::isOmpContext(parent_f) ? IFunc::free_omp : IFunc::free; + function_instrumenter_->insert_free_instrumentation(IRB, fdata.call, free_arg); + + // auto parent_f = fdata.call->getFunction(); + // const auto callback_id = util::omp::isOmpContext(parent_f) ? IFunc::free_omp : IFunc::free; + // const auto callback_id = ifunc_for_function(IFunc::free, fdata.call); - IRB.CreateCall(function_query->getFunctionFor(callback_id), ArrayRef{free_arg}); + // IRB.CreateCall(function_query->getFunctionFor(callback_id), ArrayRef{free_arg}); ++counter; } @@ -195,9 +210,12 @@ InstrCount MemOpInstrumentation::instrumentStack(const StackArgList& stack) { auto* numElementsVal = args.get_value(ArgMap::ID::element_count); 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(function_query->getFunctionFor(callback_id), - ArrayRef{data_ptr, typeIdConst, numElementsVal}); + // const auto callback_id = util::omp::isOmpContext(anchor->getFunction()) ? IFunc::stack_omp : IFunc::stack; + // const auto callback_id = ifunc_for_function(IFunc::stack, alloca); + // auto type_id_param = function_instrumenter->getOrRegister(typeIdConst); + // IRB.CreateCall(function_query->getFunctionFor(callback_id), + // ArrayRef{data_ptr, type_id_param, numElementsVal}); + function_instrumenter_->insert_stack_instrumentation(IRB, alloca, {data_ptr, numElementsVal, typeIdConst}); ++counter; auto* bblock = anchor->getParent(); @@ -238,8 +256,11 @@ InstrCount MemOpInstrumentation::instrumentGlobal(const GlobalArgList& globals) auto typeIdConst = args.get_value(ArgMap::ID::type_id); auto numElementsVal = args.get_value(ArgMap::ID::element_count); auto globalPtr = IRB.CreateBitOrPointerCast(global, instrumentation_helper->getTypeFor(IType::ptr)); - IRB.CreateCall(function_query->getFunctionFor(IFunc::global), - ArrayRef{globalPtr, typeIdConst, numElementsVal}); + // const auto callback_id = ifunc_for_function(IFunc::global, global); + // auto type_id_param = function_instrumenter->getOrRegister(typeIdConst); + // IRB.CreateCall(function_query->getFunctionFor(callback_id), + // ArrayRef{globalPtr, type_id_param, numElementsVal}); + function_instrumenter_->insert_global_instrumentation(IRB, global, {globalPtr, numElementsVal, typeIdConst}); ++counter; } }; diff --git a/lib/passes/instrumentation/MemOpInstrumentation.h b/lib/passes/instrumentation/MemOpInstrumentation.h index 0a8bd442..0b82c0bd 100644 --- a/lib/passes/instrumentation/MemOpInstrumentation.h +++ b/lib/passes/instrumentation/MemOpInstrumentation.h @@ -10,28 +10,34 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef TYPEART_MEMOPINSTRUMENTATION_H -#define TYPEART_MEMOPINSTRUMENTATION_H +#ifndef LIB_PASSES_INSTRUMENTATION_MEMOPINSTRUMENTATION +#define LIB_PASSES_INSTRUMENTATION_MEMOPINSTRUMENTATION #include "Instrumentation.h" #include "configuration/Configuration.h" +#include + namespace typeart { namespace config { class Configuration; } class TAFunctionQuery; class InstrumentationHelper; +class TypeRegistry; +class InstrumentationInserter; class MemOpInstrumentation final : public MemoryInstrument { const config::Configuration& typeart_config; TAFunctionQuery* function_query; + // std::unique_ptr type_id_handler; InstrumentationHelper* instrumentation_helper; + std::unique_ptr function_instrumenter_; bool instrument_lifetime{false}; public: - MemOpInstrumentation(const config::Configuration& typeart_conf, TAFunctionQuery& fquery, - InstrumentationHelper& instr); + MemOpInstrumentation(const config::Configuration& typeart_conf, TAFunctionQuery* fquery, InstrumentationHelper& instr, + std::unique_ptr function_instrumenter); InstrCount instrumentHeap(const HeapArgList& heap) override; InstrCount instrumentFree(const FreeArgList& frees) override; InstrCount instrumentStack(const StackArgList& stack) override; @@ -39,4 +45,4 @@ class MemOpInstrumentation final : public MemoryInstrument { }; } // namespace typeart -#endif // TYPEART_MEMOPINSTRUMENTATION_H +#endif /* LIB_PASSES_INSTRUMENTATION_MEMOPINSTRUMENTATION */ diff --git a/lib/passes/instrumentation/TypeARTFunctions.cpp b/lib/passes/instrumentation/TypeARTFunctions.cpp index f4955ec3..5ddfa462 100644 --- a/lib/passes/instrumentation/TypeARTFunctions.cpp +++ b/lib/passes/instrumentation/TypeARTFunctions.cpp @@ -1,4 +1,5 @@ // TypeART library + // // Copyright (c) 2017-2025 TypeART Authors // Distributed under the BSD 3-Clause license. @@ -12,7 +13,11 @@ #include "TypeARTFunctions.h" +#include "configuration/Configuration.h" +#include "instrumentation/TypeIDProvider.h" +#include "support/ConfigurationBase.h" #include "support/Logger.h" +#include "support/OmpUtil.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" @@ -27,7 +32,11 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" +#include +#include #include +#include +#include namespace typeart { class InstrumentationHelper; @@ -37,29 +46,134 @@ using namespace llvm; namespace typeart { +namespace detail { +std::string get_func_suffix(IFunc id) { + switch (id) { + // case IFunc::free_cuda: + // case IFunc::heap_cuda: + // return "_cuda"; + case IFunc::free_omp: + case IFunc::heap_omp: + case IFunc::stack_omp: + case IFunc::scope_omp: + return "_omp"; + default: + return ""; + } +} + +enum class IFuncType : unsigned { standard, omp, cuda }; + +IFuncType ifunc_type_for(llvm::Function* f) { + if (f == nullptr) { + return IFuncType::standard; + } + + if (util::omp::isOmpContext(f)) { + return IFuncType::omp; + } + + return IFuncType::standard; +} + +} // namespace detail + +IFunc ifunc_for_function(IFunc general_type, llvm::Value* value) { + detail::IFuncType type = typeart::detail::IFuncType::standard; + + if (auto function = llvm::dyn_cast(value)) { + type = detail::ifunc_type_for(function); + } else if (auto alloca = llvm::dyn_cast(value)) { + type = detail::ifunc_type_for(alloca->getFunction()); + } else if (llvm::isa(value)) { + type = detail::ifunc_type_for(nullptr); + } else if (auto callbase = llvm::dyn_cast(value)) { + type = detail::ifunc_type_for(callbase->getFunction()); + // auto maybe_cuda = detail::ifunc_type_for(callbase->getCalledFunction()); + // if (maybe_cuda == detail::IFuncType::cuda) { + // type = detail::IFuncType::cuda; + // } + } + + if (detail::IFuncType::standard == type) { + return general_type; + } + + // if (detail::IFuncType::cuda == type) { + // switch (general_type) { + // case IFunc::heap: + // return IFunc::heap_cuda; + // case IFunc::free: + // return IFunc::free_cuda; + // default: + // return general_type; + // // llvm_unreachable("IFunc not supported for CUDA."); + // } + // } + + switch (general_type) { + case IFunc::stack: + return IFunc::stack_omp; + case IFunc::heap: + return IFunc::heap_omp; + case IFunc::free: + return IFunc::free_omp; + case IFunc::scope: + return IFunc::scope_omp; + default: + llvm_unreachable("IFunc type is not supported for OpenMP."); + } +} + +class TAFunctions final : public TAFunctionQuery { + // densemap has problems with IFunc + using FMap = std::unordered_map; + FMap typeart_callbacks; + + public: + llvm::Function* getFunctionFor( + IFunc id, TypeSerializationImplementation impl = TypeSerializationImplementation::FILE) const override; + void putFunctionFor(IFunc id, llvm::Function* f); + // void putAlternativeFunctionFor(IFunc id, llvm::Function* f); +}; + +class TAFunctionDeclarator { + llvm::Module& module; + // [[maybe_unused]] InstrumentationHelper& instr; + TAFunctions& typeart_functions; + llvm::StringMap function_map; + + public: + TAFunctionDeclarator(llvm::Module& m, InstrumentationHelper& instr, TAFunctions& typeart_func); + llvm::Function* make_function(IFunc function, llvm::StringRef basename, llvm::ArrayRef args, + bool alternative = false); + const llvm::StringMap& getFunctionMap() const; + virtual ~TAFunctionDeclarator() = default; +}; + TAFunctionDeclarator::TAFunctionDeclarator(Module& mod, InstrumentationHelper&, TAFunctions& typeart_funcs) : module(mod), typeart_functions(typeart_funcs) { } llvm::Function* TAFunctionDeclarator::make_function(IFunc func_id, llvm::StringRef basename, - llvm::ArrayRef args, bool with_omp, bool fixed_name) { - const auto make_fname = [&fixed_name](llvm::StringRef name, llvm::ArrayRef callback_arguments, - bool with_omp_postfix) { + llvm::ArrayRef args, bool alternative) { + const auto make_fname = [&func_id](llvm::StringRef name, llvm::ArrayRef callback_arguments) { std::string fname; llvm::raw_string_ostream os(fname); os << name; + os << detail::get_func_suffix(func_id); - if (!fixed_name) { - os << "_" << std::to_string(callback_arguments.size()); - } - if (with_omp_postfix) { - os << "_" - << "omp"; - } + // if (!fixed_name) { + // os << "_" << std::to_string(callback_arguments.size()); + // } + // if (with_omp_postfix) { + // os << "_" + // << "omp"; + // } return os.str(); }; - const auto name = make_fname(basename, args, with_omp); + const auto name = make_fname(basename, args); if (auto it = function_map.find(name); it != function_map.end()) { return it->second; @@ -91,7 +205,7 @@ llvm::Function* TAFunctionDeclarator::make_function(IFunc func_id, llvm::StringR Function* function{nullptr}; if (has_func_declared) { - LOG_WARNING("Function " << function_name << " is already declared in the module.") + LOG_DEBUG("Function " << function_name << " is already declared in the module.") function = dyn_cast(func_in_module.getCallee()->stripPointerCasts()); } else { function = dyn_cast(func_in_module.getCallee()); @@ -102,12 +216,15 @@ llvm::Function* TAFunctionDeclarator::make_function(IFunc func_id, llvm::StringR return function; }; - auto generated_function = do_make(name, FunctionType::get(Type::getVoidTy(c), args, false)); + auto* generated_function = do_make(name, FunctionType::get(Type::getVoidTy(c), args, false)); function_map[name] = generated_function; + // if (alternative) { + // typeart_functions.putAlternativeFunctionFor(func_id, generated_function); + // } else { typeart_functions.putFunctionFor(func_id, generated_function); - + // } return generated_function; } @@ -115,14 +232,110 @@ const llvm::StringMap& TAFunctionDeclarator::getFunctionMap() c return function_map; } -TAFunctions::TAFunctions() = default; +Function* TAFunctions::getFunctionFor(IFunc id, TypeSerializationImplementation impl) const { + const auto find_ = [&](const auto& map_) -> std::optional { + const auto element = map_.find(id); + if (element == std::end(map_)) { + LOG_WARNING("No functions for id " << int(id)) + return {}; + } + return element->second; + }; -Function* TAFunctions::getFunctionFor(IFunc id) { - return typeart_callbacks[id]; + auto result = find_(typeart_callbacks); + return result.value_or(nullptr); } void TAFunctions::putFunctionFor(IFunc id, llvm::Function* f) { typeart_callbacks[id] = f; } +class TAFunctionAlternatives : public TAFunctionQuery { + TAFunctions standard_; + TAFunctions alternative_; + + public: + TAFunctionAlternatives(TAFunctions standard, TAFunctions alternative) + : standard_(std::move(standard)), alternative_(std::move(alternative)) { + } + Function* getFunctionFor(IFunc id, TypeSerializationImplementation impl) const override { + if (impl != TypeSerializationImplementation::FILE) { + auto alternative = alternative_.getFunctionFor(id); + if (alternative != nullptr) { + return alternative; + } + } + return standard_.getFunctionFor(id); + } +}; + +namespace callbacks { +struct TypeArtFunc { + const std::string name; + llvm::Value* f{nullptr}; +}; + +TypeArtFunc typeart_alloc{"__typeart_alloc"}; +TypeArtFunc typeart_alloc_global{"__typeart_alloc_global"}; +TypeArtFunc typeart_alloc_stack{"__typeart_alloc_stack"}; +TypeArtFunc typeart_free{"__typeart_free"}; +TypeArtFunc typeart_leave_scope{"__typeart_leave_scope"}; + +TypeArtFunc typeart_alloc_omp = typeart_alloc; +TypeArtFunc typeart_alloc_stacks_omp = typeart_alloc_stack; +TypeArtFunc typeart_free_omp = typeart_free; +TypeArtFunc typeart_leave_scope_omp = typeart_leave_scope; + +TypeArtFunc typeart_alloc_mty{"__typeart_alloc_mty"}; +TypeArtFunc typeart_alloc_stack_mty{"__typeart_alloc_stack_mty"}; +TypeArtFunc typeart_alloc_global_mty{"__typeart_alloc_global_mty"}; +TypeArtFunc typeart_register_type{"__typeart_register_type"}; +TypeArtFunc typeart_alloc_omp_mty = typeart_alloc_mty; +TypeArtFunc typeart_alloc_stacks_omp_mty = typeart_alloc_stack_mty; + +} // namespace callbacks + +std::unique_ptr declare_instrumentation_functions(llvm::Module& m, + const config::Configuration& configuration) { + using namespace callbacks; + TAFunctions functions; + TAFunctions functions_alternative; + InstrumentationHelper instrumentation_helper; + instrumentation_helper.setModule(m); + TAFunctionDeclarator decl(m, instrumentation_helper, functions); + TAFunctionDeclarator decl_alternatives(m, instrumentation_helper, functions_alternative); + + auto alloc_arg_types = instrumentation_helper.make_parameters(IType::ptr, IType::type_id, IType::extent); + auto free_arg_types = instrumentation_helper.make_parameters(IType::ptr); + auto leavescope_arg_types = instrumentation_helper.make_parameters(IType::stack_count); + + // const TypeSerializationImplementation local_types = configuration[config::ConfigStdArgs::type_serialization]; + auto alloc_arg_types_mty = instrumentation_helper.make_parameters(IType::ptr, IType::ptr, IType::extent); + typeart_alloc_mty.f = decl_alternatives.make_function(IFunc::heap, typeart_alloc_mty.name, alloc_arg_types_mty); + typeart_alloc_stack_mty.f = + decl_alternatives.make_function(IFunc::stack, typeart_alloc_stack_mty.name, alloc_arg_types_mty); + typeart_alloc_global_mty.f = + decl_alternatives.make_function(IFunc::global, typeart_alloc_global_mty.name, alloc_arg_types_mty); + typeart_register_type.f = decl.make_function(IFunc::type, typeart_register_type.name, free_arg_types); + + typeart_alloc.f = decl.make_function(IFunc::heap, typeart_alloc.name, alloc_arg_types); + typeart_alloc_stack.f = decl.make_function(IFunc::stack, typeart_alloc_stack.name, alloc_arg_types); + typeart_alloc_global.f = decl.make_function(IFunc::global, typeart_alloc_global.name, alloc_arg_types); + typeart_free.f = decl.make_function(IFunc::free, typeart_free.name, free_arg_types); + typeart_leave_scope.f = decl.make_function(IFunc::scope, typeart_leave_scope.name, leavescope_arg_types); + + typeart_alloc_omp.f = decl.make_function(IFunc::heap_omp, typeart_alloc_omp.name, alloc_arg_types); + typeart_alloc_stacks_omp.f = decl.make_function(IFunc::stack_omp, typeart_alloc_stacks_omp.name, alloc_arg_types); + typeart_free_omp.f = decl.make_function(IFunc::free_omp, typeart_free_omp.name, free_arg_types); + + typeart_leave_scope_omp.f = decl.make_function(IFunc::scope_omp, typeart_leave_scope_omp.name, leavescope_arg_types); + + typeart_alloc_omp_mty.f = + decl_alternatives.make_function(IFunc::heap_omp, typeart_alloc_omp_mty.name, alloc_arg_types_mty); + typeart_alloc_stacks_omp_mty.f = + decl_alternatives.make_function(IFunc::stack_omp, typeart_alloc_stacks_omp_mty.name, alloc_arg_types_mty); + + return std::make_unique(functions, functions_alternative); +} + } // namespace typeart diff --git a/lib/passes/instrumentation/TypeARTFunctions.h b/lib/passes/instrumentation/TypeARTFunctions.h index d707a933..e0927ae3 100644 --- a/lib/passes/instrumentation/TypeARTFunctions.h +++ b/lib/passes/instrumentation/TypeARTFunctions.h @@ -14,12 +14,10 @@ #define TYPEART_TYPEARTFUNCTIONS_H #include "InstrumentationHelper.h" +#include "configuration/Configuration.h" +#include "instrumentation/TypeIDProvider.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" - -#include +#include namespace llvm { class Function; @@ -30,49 +28,23 @@ class Module; namespace typeart { class InstrumentationHelper; -enum class IFunc : unsigned { - heap, - stack, - global, - free, - scope, - heap_omp, - stack_omp, - free_omp, - scope_omp, -}; +namespace config { +class Configuration; +} -class TAFunctionQuery { - public: - virtual llvm::Function* getFunctionFor(IFunc id) = 0; - virtual ~TAFunctionQuery() = default; -}; +enum class IFunc : unsigned { heap, stack, global, free, scope, heap_omp, stack_omp, free_omp, scope_omp, type }; -class TAFunctions : public TAFunctionQuery { - // densemap has problems with IFunc - using FMap = std::unordered_map; - FMap typeart_callbacks; +IFunc ifunc_for_function(IFunc general_type, llvm::Value* value); +class TAFunctionQuery { public: - TAFunctions(); - - llvm::Function* getFunctionFor(IFunc id) override; - void putFunctionFor(IFunc id, llvm::Function* f); + [[nodiscard]] virtual llvm::Function* getFunctionFor( + IFunc id, TypeSerializationImplementation impl = TypeSerializationImplementation::FILE) const = 0; + virtual ~TAFunctionQuery() = default; }; -class TAFunctionDeclarator { - llvm::Module& module; - // [[maybe_unused]] InstrumentationHelper& instr; - TAFunctions& typeart_functions; - llvm::StringMap function_map; - - public: - TAFunctionDeclarator(llvm::Module& m, InstrumentationHelper& instr, TAFunctions& typeart_func); - 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; -}; +std::unique_ptr declare_instrumentation_functions(llvm::Module& m, + const config::Configuration& configuration); } // namespace typeart diff --git a/lib/passes/instrumentation/TypeIDProvider.cpp b/lib/passes/instrumentation/TypeIDProvider.cpp new file mode 100644 index 00000000..fcfb0e26 --- /dev/null +++ b/lib/passes/instrumentation/TypeIDProvider.cpp @@ -0,0 +1,509 @@ +#include "TypeIDProvider.h" + +#include "TypeDB.h" +#include "TypeDatabase.h" +#include "TypeInterface.h" +#include "configuration/Configuration.h" +#include "instrumentation/TypeARTFunctions.h" +#include "support/ConfigurationBase.h" +#include "support/Logger.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace typeart { + +void TypeRegistry::registerModule(const ModuleData&) { +} + +class TypeRegistryNoOp final : public TypeRegistry { + public: + llvm::Value* getOrRegister(llvm::Value* type_id_const) override { + return type_id_const; + } +}; + +namespace helper { + +void replace_whitespace_with_underscore(std::string& s) { + std::replace_if(s.begin(), s.end(), [](unsigned char c) { return std::isspace(c); }, '_'); +} + +inline int get_type_id(llvm::Value* type_id_const) { + auto* constant_int = llvm::dyn_cast(type_id_const); + assert(constant_int && "Expected llvm::ConstantInt"); + if (constant_int == nullptr) { + return TYPEART_UNKNOWN_TYPE; + } + assert(constant_int->getBitWidth() <= 32 && "Type ID is too wide"); + const int type_id = static_cast(constant_int->getSExtValue()); + return type_id; +} + +template +inline std::string concat(Args&&... args) { + const auto str = (std::string{} + ... + std::string{std::forward(args)}); + return str; +} + +template +inline std::string create_prefixed_name(Args&&... args) { + std::string name = concat("_typeart_", std::forward(args)...); + replace_whitespace_with_underscore(name); + return name; +} + +} // namespace helper + +namespace typedb { + +struct GlobalTypeData { + struct TypeData { + llvm::Constant* type_struct; + llvm::GlobalVariable* type; + llvm::Constant* name; + llvm::Constant* offset; + llvm::Constant* count; + }; + llvm::StringMap global_type_data; + + inline bool has_type_name(llvm::StringRef name) const { +#if LLVM_VERSION_MAJOR > 17 + return global_type_data.contains(name); +#else + return global_type_data.find(name) != global_type_data.end(); +#endif + } + + inline const TypeData& get_type(llvm::StringRef name) const { +#if LLVM_VERSION_MAJOR > 17 + return global_type_data.at(name); +#else + return global_type_data.find(name)->second; +#endif + } +}; + +struct GlobalTypeCallback { + llvm::Module* module_; + const TAFunctionQuery* f_query_; + llvm::StringRef ctor_function_name{"__typeart_init_module_type_globals"}; + + private: + bool has_function() const { + auto func = module_->getFunction(ctor_function_name); + return func != nullptr; + } + + llvm::BasicBlock* make_type_callback() const { + using namespace llvm; + const auto makeCtorFuncBody = [&]() -> BasicBlock* { + auto& c = module_->getContext(); + FunctionType* ctorType = FunctionType::get(llvm::Type::getVoidTy(c), false); + Function* ctorFunction = Function::Create(ctorType, Function::PrivateLinkage, ctor_function_name, module_); + BasicBlock* entry = BasicBlock::Create(c, "entry", ctorFunction); + auto* ret_inst = ReturnInst::Create(c); +#if LLVM_VERSION_MAJOR > 17 + ret_inst->insertInto(entry, entry->getFirstInsertionPt()); +#else + entry->getInstList().push_back(ret_inst); +#endif + + llvm::appendToGlobalCtors(*module_, ctorFunction, 0, nullptr); + + return entry; + }; + + auto* func = module_->getFunction(ctor_function_name); + if (func == nullptr) { + return makeCtorFuncBody(); + } + return &func->getEntryBlock(); + } + + llvm::BasicBlock* get_entry() { + auto* func = module_->getFunction(ctor_function_name); + if (func == nullptr) { + return make_type_callback(); + } + return &func->getEntryBlock(); + } + + public: + GlobalTypeCallback(llvm::Module* module, const TAFunctionQuery* f_query) : module_(module), f_query_(f_query) { + } + + void insert(llvm::Constant* global) { + auto* block = get_entry(); + for (auto& inst : *block) { + if (auto* call_base = llvm::dyn_cast(&inst)) { + auto* argument = call_base->getArgOperand(0); + if (global == argument) { + LOG_DEBUG("Skipping, already contained"); + return; + } + } + } + llvm::IRBuilder<> IRB{&*block->getFirstInsertionPt()}; + + IRB.CreateCall(f_query_->getFunctionFor(IFunc::type), llvm::ArrayRef{global}); + } +}; + +enum class IGlobalType : short { + type_id, + name, + extent, + num_members, + member_offsets, + member_types, + member_count, + type_flag, + ptr +}; + +struct TypeHelper { + llvm::IRBuilder<>& ir_build_; + explicit TypeHelper(llvm::IRBuilder<>& ir_build) : ir_build_(ir_build) { + } + + llvm::Type* get_type_for(IGlobalType type, bool as_array = false) { + switch (type) { + case IGlobalType::type_id: + case IGlobalType::extent: + return ir_build_.getInt32Ty(); + case IGlobalType::type_flag: + case IGlobalType::num_members: + return ir_build_.getInt16Ty(); + case IGlobalType::member_offsets: + case IGlobalType::member_types: + case IGlobalType::member_count: { + if (as_array) { + return ir_build_.getInt16Ty(); + } +#if LLVM_VERSION_MAJOR < 15 + return ir_build_.getInt8PtrTy(); +#else + return ir_build_.getPtrTy(); +#endif + } + case IGlobalType::name: + case IGlobalType::ptr: +#if LLVM_VERSION_MAJOR < 15 + return ir_build_.getInt8PtrTy(); +#else + return ir_build_.getPtrTy(); +#endif + } + llvm_unreachable("Should not be reached disk"); + } + + llvm::Constant* get_constant_for(IGlobalType type, size_t value) { + switch (type) { + case IGlobalType::type_id: + case IGlobalType::extent: + return ir_build_.getInt32(value); + case IGlobalType::type_flag: + case IGlobalType::num_members: + case IGlobalType::member_offsets: + case IGlobalType::member_count: + return ir_build_.getInt16(value); + default: + break; + } + return ir_build_.getInt32(value); + } + + llvm::Constant* get_constant_nullptr() { + return llvm::ConstantPointerNull::get(llvm::dyn_cast(get_type_for(IGlobalType::ptr))); + } +}; + +struct GlobalTypeRegistrar { + private: + llvm::Module* module_; + const TypeDatabase* type_db_; + llvm::IRBuilder<> ir_build; + GlobalTypeCallback type_callback; + llvm::StructType* struct_layout_type_; + GlobalTypeData global_types_; + TypeHelper types_helper; + const bool builtin_emit_name{false}; + + void declare_layout() { + auto& context = module_->getContext(); + struct_layout_type_ = llvm::StructType::create(context, "struct._typeart_struct_layout_t"); + struct_layout_type_->setBody({ + types_helper.get_type_for(IGlobalType::type_id), // int type_id + types_helper.get_type_for(IGlobalType::extent), // uint32 extent + types_helper.get_type_for(IGlobalType::num_members), // uint16 num_members + types_helper.get_type_for(IGlobalType::type_flag), // uint16 type_flag + types_helper.get_type_for(IGlobalType::name), // const char* name + types_helper.get_type_for(IGlobalType::member_offsets), // const uint16* offsets + types_helper.get_type_for(IGlobalType::member_count), // const uint16* count + types_helper.get_type_for(IGlobalType::member_types), // const typeart_struct_layout_t** member_types + + }); + } + + llvm::GlobalVariable* create_global( + llvm::StringRef name, llvm::Type* type, llvm::Constant* init = nullptr, + llvm::GlobalVariable::LinkageTypes link_type = llvm::GlobalValue::WeakODRLinkage) const { + // TODO: https://llvm.org/docs/LangRef.html#linkage w.r.t. forward declared types + auto* global_struct = + new llvm::GlobalVariable(*module_, type, true, link_type, init, helper::create_prefixed_name(name)); + return global_struct; + } + + llvm::Constant* make_gep(llvm::Type* type, llvm::GlobalVariable* global) { + auto* i32_zero_const = llvm::ConstantInt::get(ir_build.getInt32Ty(), 0); + return llvm::ConstantExpr::getInBoundsGetElementPtr( + type, global, llvm::ArrayRef{i32_zero_const, i32_zero_const}); + } + + llvm::Constant* create_global_constant_string(llvm::StringRef name) { + // TODO think about linkage + // auto* name_str = ir_build.CreateGlobalStringPtr(name, helper::create_prefixed_name("typename_", name), 0, + // module_); + auto* global_string = + ir_build.CreateGlobalString(name, helper::create_prefixed_name("typename_", name), 0, module_); + global_string->setConstant(true); + global_string->setLinkage(llvm::GlobalValue::WeakODRLinkage); + return make_gep(global_string->getValueType(), global_string); + } + + llvm::Constant* create_global_array_ptr(const llvm::StringRef name, llvm::ArrayRef values) { + if (values.empty()) { + LOG_DEBUG("No values for global array, returning nullptr") + return types_helper.get_constant_nullptr(); + } + + std::vector constants; + constants.reserve(values.size()); + for (uint64_t val : values) { + constants.push_back(types_helper.get_constant_for(IGlobalType::member_offsets, val)); + } + + auto* array_ty = llvm::ArrayType::get(types_helper.get_type_for(IGlobalType::member_offsets, true), values.size()); + auto* constant_array = llvm::ConstantArray::get(array_ty, constants); + auto* gv = create_global(name, array_ty, constant_array); + return make_gep(array_ty, gv); + } + + llvm::GlobalVariable* registerGlobalStruct(const std::string& name, int type_id, uint64_t type_size, + uint64_t member_count, llvm::Constant* offset_ptr, + llvm::Constant* members_data_ptr, llvm::Constant* count_ptr, + StructTypeFlag flag = StructTypeFlag::USER_DEFINED) { + const auto name_struct = flag == StructTypeFlag::FWD_DECL ? helper::concat(name, "_fwd") : name; + + llvm::GlobalVariable* global_struct = create_global(name_struct, struct_layout_type_); + global_struct->setConstant(false); + + // In the current scheme, built-ins do not need to produce a name string (Built) + const bool is_builtin = flag == StructTypeFlag::BUILTIN; + const bool emit_builtin_typename = is_builtin && builtin_emit_name; + llvm::Constant* name_str = (emit_builtin_typename || !is_builtin) ? create_global_constant_string(name) + : types_helper.get_constant_nullptr(); + + std::vector members = { + types_helper.get_constant_for(IGlobalType::type_id, type_id), + types_helper.get_constant_for(IGlobalType::extent, type_size), + types_helper.get_constant_for(IGlobalType::member_count, member_count), + types_helper.get_constant_for(IGlobalType::type_flag, + static_cast(flag)), // TODO: use real type + name_str, // + offset_ptr, // + count_ptr, // + members_data_ptr}; + llvm::Constant* init = llvm::ConstantStruct::get(struct_layout_type_, members); + global_struct->setInitializer(init); + + global_types_.global_type_data.try_emplace( + name, GlobalTypeData::TypeData{init, global_struct, name_str, offset_ptr, count_ptr}); + + return global_struct; + } + + llvm::GlobalVariable* registerTypeStruct(const StructTypeInfo* type_struct) { + const auto name = type_struct->name; + const auto type_size = type_struct->extent; + + if (type_struct->flag == StructTypeFlag::FWD_DECL) { + LOG_DEBUG("Type is forward decl " << name) + // return registerGlobalStructDecl(name); + } + + llvm::Constant* offset_ptr = create_global_array_ptr(helper::concat("offsets_", name), type_struct->offsets); + llvm::Constant* count_ptr = create_global_array_ptr(helper::concat("counts_", name), type_struct->array_sizes); + + llvm::Constant* members_array; + llvm::Type* ptr_type{nullptr}; // TODO: make this unqual? + std::vector member_types{}; + + for (auto member_type_id : type_struct->member_types) { + llvm::Constant* member = getOrRegister(member_type_id); + if (ptr_type == nullptr) { + ptr_type = member->getType(); + } + member_types.emplace_back(member); + } + + const auto member_count = type_struct->member_types.size(); + if (ptr_type != nullptr) { + assert(member_count == type_struct->num_members); + llvm::ArrayType* member_array_ty = llvm::ArrayType::get(ptr_type, member_count); + llvm::Constant* init = llvm::ConstantArray::get(member_array_ty, member_types); + members_array = create_global(helper::concat("member_types_", name), member_array_ty, init); + } else { + llvm::Constant* null_member = types_helper.get_constant_nullptr(); + members_array = null_member; + } + + return registerGlobalStruct(name, type_struct->type_id, type_size, member_count, offset_ptr, members_array, + count_ptr, type_struct->flag); + } + + llvm::GlobalVariable* registerBuiltin(int type_id) { + auto type_name = type_db_->getTypeName(type_id); + helper::replace_whitespace_with_underscore(type_name); + StructTypeInfo type_struct{type_id, type_name, type_db_->getTypeSize(type_id), 1, {}, + {}, {}, StructTypeFlag::BUILTIN}; + return registerTypeStruct(&type_struct); + } + + llvm::GlobalVariable* registerUserDefined(int type_id) { + const auto* const type_struct = type_db_->getStructInfo(type_id); + if (type_struct == nullptr) { + LOG_WARNING("Struct info is nullptr for id " << type_id) + } + return registerTypeStruct(type_struct); + } + + public: + GlobalTypeRegistrar(llvm::Module* m, const TypeDatabase* type_db, const TAFunctionQuery* f_query) + : module_(m), + type_db_(type_db), + ir_build(m->getContext()), + type_callback(module_, f_query), + types_helper(ir_build) { + declare_layout(); + } + + const TypeDatabase& db() const { + return *type_db_; + } + + llvm::Constant* getOrRegister(int type_id) { + const auto name = type_db_->getTypeName(type_id); + LOG_DEBUG(name << " aka " << helper::create_prefixed_name(name)) + return module_->getOrInsertGlobal( + helper::create_prefixed_name(name), struct_layout_type_, [&]() -> llvm::GlobalVariable* { + LOG_DEBUG("Registering << " << type_id << " " << name << " aka " << helper::create_prefixed_name(name)) + const bool is_builtin = type_db_->isBuiltinType(type_id); + if (is_builtin) { + auto* global = registerBuiltin(type_id); + type_callback.insert(global); + return global; + } + auto* global = registerUserDefined(type_id); + const auto fwd_decl = StructTypeFlag::FWD_DECL == type_db_->getStructInfo(type_id)->flag; + if (!fwd_decl) { + LOG_DEBUG("Registering forward declared variable " << *global) + } + type_callback.insert(global); + return global; + }); + } +}; // namespace typedb +} // namespace typedb + +class TypeRegistryGlobals final : public TypeRegistry { + // llvm::Module* module_; + typedb::GlobalTypeRegistrar registrar_; + + public: + TypeRegistryGlobals(llvm::Module& m, const TypeDatabase* type_db, const TAFunctionQuery* f_query) + : registrar_(&m, type_db, f_query) { + } + + void registerModule(const ModuleData& m) override { + for (const auto& type : m.types_list) { + if (builtins::BuiltInQuery::is_builtin_type(type.type_id)) { + continue; + } + if (!registrar_.db().isValid(type.type_id)) { + continue; + } + LOG_DEBUG("Registering type_id " << type.type_id) + /*const auto* type_id =*/registrar_.getOrRegister(type.type_id); + } + } + + llvm::Value* getOrRegister(llvm::Value* type_id_const) override { + return registrar_.getOrRegister(helper::get_type_id(type_id_const)); + } +}; + +class TypeRegistryAlternatives final : public TypeRegistry { + TypeRegistryGlobals globals; + TypeRegistryNoOp noops; + + public: + TypeRegistryAlternatives(llvm::Module& m, const TypeDatabase* type_db, const TAFunctionQuery* f_query) + : globals(m, type_db, f_query) { + } + + void registerModule(const ModuleData& m) override { + globals.registerModule(m); + } + + llvm::Value* getOrRegister(llvm::Value* type_id_const) override { + if (builtins::BuiltInQuery::is_builtin_type(helper::get_type_id(type_id_const))) { + return noops.getOrRegister(type_id_const); + } + return globals.getOrRegister(type_id_const); + } +}; + +std::unique_ptr get_type_id_handler(llvm::Module& m, const TypeDatabase* type_db, + const config::Configuration& configuration, + const TAFunctionQuery* f_query) { + TypeSerializationImplementation impl = configuration[config::ConfigStdArgs::type_serialization]; +#if LLVM_VERSION_MAJOR < 15 + if (impl != typeart::TypeSerializationImplementation::FILE) { + LOG_WARNING("Unsupported type serialization mode for LLVM-" << LLVM_VERSION_MAJOR) + } + // using llvm-14 would require opaque pointer mode for globals + return std::make_unique(); +#else + switch (impl) { + case typeart::TypeSerializationImplementation::FILE: + return std::make_unique(); + case typeart::TypeSerializationImplementation::HYBRID: + return std::make_unique(m, type_db, f_query); + default: + return std::make_unique(m, type_db, f_query); + } +#endif +} + +} // namespace typeart \ No newline at end of file diff --git a/lib/passes/instrumentation/TypeIDProvider.h b/lib/passes/instrumentation/TypeIDProvider.h new file mode 100644 index 00000000..e0467edc --- /dev/null +++ b/lib/passes/instrumentation/TypeIDProvider.h @@ -0,0 +1,39 @@ +#ifndef LIB_PASSES_INSTRUMENTATION_MODULETYPEREGISTRY +#define LIB_PASSES_INSTRUMENTATION_MODULETYPEREGISTRY + +// #include "TypeARTFunctions.h" +// #include "instrumentation/TypeARTFunctions.h" +#include "typegen/TypeGenerator.h" +#include "typelib/TypeDatabase.h" + +#include +#include + +namespace llvm { +class Value; +class Module; +} // namespace llvm + +namespace typeart { + +enum class TypeSerializationImplementation : uint8_t { FILE, INLINE, HYBRID }; + +namespace config { +class Configuration; +} +class TAFunctionQuery; + +class TypeRegistry { + public: + [[nodiscard]] virtual llvm::Value* getOrRegister(llvm::Value* type_id_const) = 0; + virtual void registerModule(const ModuleData&); + virtual ~TypeRegistry() = default; +}; + +std::unique_ptr get_type_id_handler(llvm::Module& m, const TypeDatabase* type_db, + const config::Configuration& configuration, + const TAFunctionQuery* f_query); + +} // namespace typeart + +#endif /* LIB_PASSES_INSTRUMENTATION_MODULETYPEREGISTRY */ diff --git a/lib/passes/typegen/TypeGenerator.cpp b/lib/passes/typegen/TypeGenerator.cpp index 176aa30c..2401bda2 100644 --- a/lib/passes/typegen/TypeGenerator.cpp +++ b/lib/passes/typegen/TypeGenerator.cpp @@ -55,10 +55,11 @@ int TypeIDGenerator::reserveNextTypeId() { } const TypeDatabase& TypeIDGenerator::getTypeDatabase() const { - return *this->typeDB.get(); + return *this->typeDB; } -void TypeIDGenerator::registerModule(const ModuleData&) { +bool TypeIDGenerator::registerModule(ModuleData&) { + return false; } } // namespace typeart::types diff --git a/lib/passes/typegen/TypeGenerator.h b/lib/passes/typegen/TypeGenerator.h index 977c228e..20d1c501 100644 --- a/lib/passes/typegen/TypeGenerator.h +++ b/lib/passes/typegen/TypeGenerator.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef TYPEART_TYPEGENERATOR_H -#define TYPEART_TYPEGENERATOR_H +#ifndef LIB_PASSES_TYPEGEN_TYPEGENERATOR +#define LIB_PASSES_TYPEGEN_TYPEGENERATOR #include "analysis/MemOpData.h" #include "typelib/TypeDatabase.h" @@ -25,6 +25,7 @@ #include #include #include +#include namespace llvm { class Type; @@ -40,13 +41,16 @@ struct TypeIdentifier final { std::uint64_t num_elements{1}; // > 1 for array-like type allocation }; +using TypeIdentifierList = std::vector; + struct ModuleData { llvm::Module* module; + TypeIdentifierList types_list{}; }; class TypeGenerator { public: - virtual void registerModule(const ModuleData&) = 0; + virtual bool registerModule(ModuleData&) = 0; [[nodiscard]] virtual TypeIdentifier getOrRegisterType(const MallocData&) = 0; [[nodiscard]] virtual TypeIdentifier getOrRegisterType(const AllocaData&) = 0; [[nodiscard]] virtual TypeIdentifier getOrRegisterType(const GlobalData&) = 0; @@ -64,4 +68,4 @@ std::unique_ptr make_typegen(std::string_view file, TypegenImplem } // namespace typeart -#endif // TYPEART_TYPEGENERATOR_H +#endif /* LIB_PASSES_TYPEGEN_TYPEGENERATOR */ diff --git a/lib/passes/typegen/TypeIDGenerator.h b/lib/passes/typegen/TypeIDGenerator.h index 6d00a726..8e6e271b 100644 --- a/lib/passes/typegen/TypeIDGenerator.h +++ b/lib/passes/typegen/TypeIDGenerator.h @@ -34,7 +34,7 @@ class TypeIDGenerator : public TypeGenerator { public: explicit TypeIDGenerator(std::string file_, std::unique_ptr database_of_types); - virtual void registerModule(const ModuleData&) override; + virtual bool registerModule(ModuleData&) override; [[nodiscard]] virtual const TypeDatabase& getTypeDatabase() const override; diff --git a/lib/passes/typegen/dimeta/DimetaTypeGen.cpp b/lib/passes/typegen/dimeta/DimetaTypeGen.cpp index ac14ecb8..39c57c7a 100644 --- a/lib/passes/typegen/dimeta/DimetaTypeGen.cpp +++ b/lib/passes/typegen/dimeta/DimetaTypeGen.cpp @@ -101,8 +101,10 @@ void remove_pointer_level(const llvm::AllocaInst* alloc, dimeta::LocatedType& va // If the alloca instruction is not a pointer, but the located_type has a pointer-like qualifier, we remove it. // Workaround for inlining issue, see test typemapping/05_milc_inline_metadata.c // TODO Should be removed if dimeta fixes it. - if (!alloc->getAllocatedType()->isPointerTy()) { - LOG_DEBUG("Alloca is not a pointer") + // Further refinement, array-like allocas to pointers stay untouched (second condition): + // this will cause MPI handle arrays (typedef "ptr to opaque struct") to be considered a pointer + if (!alloc->getAllocatedType()->isPointerTy() && !alloc->getAllocatedType()->isArrayTy()) { + LOG_DEBUG("Alloca is not a pointer type: " << *alloc->getAllocatedType()) const auto remove_pointer_level = [](auto& qual) { auto pointer_like_iter = llvm::find_if(qual, [](auto qualifier) { @@ -488,7 +490,7 @@ class DimetaTypeManager final : public TypeIDGenerator { workaround::remove_pointer_level(alloc, val.value()); const auto type_id = getOrRegister(val->type, false); const auto array_size_val = array_size(val->type); - LOG_DEBUG(array_size_val) + LOG_DEBUG("Array size of alloca " << array_size_val) return {type_id, array_size_val}; } } else if (auto* global = llvm::dyn_cast(type)) { @@ -502,19 +504,23 @@ class DimetaTypeManager final : public TypeIDGenerator { return {TYPEART_UNKNOWN_TYPE, 0}; } - void registerModule(const ModuleData& module) override { + bool registerModule(ModuleData& module) override { using namespace dimeta; // std::optional compile_unit_types(const llvm::Module*) LOG_DEBUG("Register module types") auto cu_types_list = dimeta::compile_unit_types(module.module).value_or(dimeta::CompileUnitTypeList{}); + std::vector cu_types; for (const auto& cu : cu_types_list) { const QualifiedTypeList& list = cu.types; for (const auto& cu_type : list) { - getOrRegister(cu_type); + cu_types.emplace_back(TypeIdentifier{getOrRegister(cu_type)}); } } + const bool has_cu_types = !cu_types.empty(); + module.types_list = std::move(cu_types); LOG_DEBUG("Done: Register module types") + return has_cu_types; } TypeIdentifier getOrRegisterType(const MallocData& data) override { diff --git a/lib/runtime/AccessCountPrinter.h b/lib/runtime/AccessCountPrinter.h index 525e84c7..d7cf343b 100644 --- a/lib/runtime/AccessCountPrinter.h +++ b/lib/runtime/AccessCountPrinter.h @@ -17,14 +17,9 @@ #include "support/Logger.h" #include "support/Table.h" -#include -#include #include #include #include -#include -#include -#include #include namespace typeart::softcounter { @@ -55,7 +50,6 @@ void serialize(const Recorder& r, std::ostringstream& buf) { return; } else { // const auto memory_use = memory::estimate(r.getMaxStackAllocs(), r.getMaxHeapAllocs(), r.getGlobalAllocs()); - Table overview_table("Alloc Stats from softcounters"); overview_table.wrap_length_ = true; overview_table.put(Row::make("Total heap", r.getHeapAllocs(), r.getHeapArray())); diff --git a/lib/runtime/AccessCounter.h b/lib/runtime/AccessCounter.h index ba4a6ad6..086c73a6 100644 --- a/lib/runtime/AccessCounter.h +++ b/lib/runtime/AccessCounter.h @@ -14,20 +14,14 @@ #define TYPEART_ACCESSCOUNTER_H #include "RuntimeData.h" -#include "RuntimeInterface.h" #include #include #include -#include -#include #include #include -#include #include -#include #include -#include #include #include #include diff --git a/lib/runtime/AllocMapWrapper.h b/lib/runtime/AllocMapWrapper.h index 6c6fc8ec..2500be6c 100644 --- a/lib/runtime/AllocMapWrapper.h +++ b/lib/runtime/AllocMapWrapper.h @@ -17,6 +17,7 @@ #include #include +#include namespace typeart { namespace mixin { diff --git a/lib/runtime/AllocationTracking.cpp b/lib/runtime/AllocationTracking.cpp index 54735548..c22c2072 100644 --- a/lib/runtime/AllocationTracking.cpp +++ b/lib/runtime/AllocationTracking.cpp @@ -171,8 +171,7 @@ AllocState AllocationTracker::doAlloc(const void* addr, int typeId, size_t count FreeState AllocationTracker::doFreeHeap(const void* addr, const void* retAddr) { if (unlikely(addr == nullptr)) { - LOG_ERROR("Free on nullptr " - << "(" << retAddr << ")"); + LOG_ERROR("Free on nullptr " << "(" << retAddr << ")"); return FreeState::ADDR_SKIPPED | FreeState::NULL_PTR; } @@ -233,56 +232,104 @@ std::optional AllocationTracker::findBaseAlloc(const void* a void __typeart_alloc(const void* addr, int typeId, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - typeart::RuntimeSystem::get().allocTracker.onAlloc(addr, typeId, count, retAddr); + typeart::RuntimeSystem::get().allocation_tracker().onAlloc(addr, typeId, count, retAddr); } void __typeart_alloc_stack(const void* addr, int typeId, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - typeart::RuntimeSystem::get().allocTracker.onAllocStack(addr, typeId, count, retAddr); + typeart::RuntimeSystem::get().allocation_tracker().onAllocStack(addr, typeId, count, retAddr); } void __typeart_alloc_global(const void* addr, int typeId, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - typeart::RuntimeSystem::get().allocTracker.onAllocGlobal(addr, typeId, count, retAddr); + typeart::RuntimeSystem::get().allocation_tracker().onAllocGlobal(addr, typeId, count, retAddr); } void __typeart_free(const void* addr) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - typeart::RuntimeSystem::get().allocTracker.onFreeHeap(addr, retAddr); + typeart::RuntimeSystem::get().allocation_tracker().onFreeHeap(addr, retAddr); } void __typeart_leave_scope(int alloca_count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - typeart::RuntimeSystem::get().allocTracker.onLeaveScope(alloca_count, retAddr); + typeart::RuntimeSystem::get().allocation_tracker().onLeaveScope(alloca_count, retAddr); } void __typeart_alloc_omp(const void* addr, int typeId, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - typeart::RuntimeSystem::get().allocTracker.onAlloc(addr, typeId, count, retAddr); - typeart::RuntimeSystem::get().recorder.incOmpContextHeap(); + auto& rt = typeart::RuntimeSystem::get(); + rt.allocation_tracker().onAlloc(addr, typeId, count, retAddr); + rt.recorder.incOmpContextHeap(); } void __typeart_alloc_stack_omp(const void* addr, int typeId, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - typeart::RuntimeSystem::get().allocTracker.onAllocStack(addr, typeId, count, retAddr); - typeart::RuntimeSystem::get().recorder.incOmpContextStack(); + auto& rt = typeart::RuntimeSystem::get(); + rt.allocation_tracker().onAllocStack(addr, typeId, count, retAddr); + rt.recorder.incOmpContextStack(); } void __typeart_free_omp(const void* addr) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - typeart::RuntimeSystem::get().allocTracker.onFreeHeap(addr, retAddr); - typeart::RuntimeSystem::get().recorder.incOmpContextFree(); + auto& rt = typeart::RuntimeSystem::get(); + rt.allocation_tracker().onFreeHeap(addr, retAddr); + rt.recorder.incOmpContextFree(); } void __typeart_leave_scope_omp(int alloca_count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - typeart::RuntimeSystem::get().allocTracker.onLeaveScope(alloca_count, retAddr); + typeart::RuntimeSystem::get().allocation_tracker().onLeaveScope(alloca_count, retAddr); +} + +void __typeart_alloc_mty(const void* addr, const void* info, size_t count) { + TYPEART_RUNTIME_GUARD; + const void* retAddr = __builtin_return_address(0); + const auto type_id = reinterpret_cast(info)->type_id; + auto& rt = typeart::RuntimeSystem::get(); + assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); + rt.allocation_tracker().onAlloc(addr, type_id, count, retAddr); +} + +void __typeart_alloc_stack_mty(const void* addr, const void* info, size_t count) { + TYPEART_RUNTIME_GUARD; + const void* retAddr = __builtin_return_address(0); + const auto type_id = reinterpret_cast(info)->type_id; + auto& rt = typeart::RuntimeSystem::get(); + assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); + rt.allocation_tracker().onAllocStack(addr, type_id, count, retAddr); +} + +void __typeart_alloc_global_mty(const void* addr, const void* info, size_t count) { + TYPEART_RUNTIME_GUARD; + const void* retAddr = __builtin_return_address(0); + const auto type_id = reinterpret_cast(info)->type_id; + auto& rt = typeart::RuntimeSystem::get(); + assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); + rt.allocation_tracker().onAllocGlobal(addr, type_id, count, retAddr); +} + +void __typeart_alloc_omp_mty(const void* addr, const void* info, size_t count) { + TYPEART_RUNTIME_GUARD; + const void* retAddr = __builtin_return_address(0); + const auto type_id = reinterpret_cast(info)->type_id; + auto& rt = typeart::RuntimeSystem::get(); + assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); + rt.allocation_tracker().onAlloc(addr, type_id, count, retAddr); +} + +void __typeart_alloc_stack_omp_mty(const void* addr, const void* info, size_t count) { + TYPEART_RUNTIME_GUARD; + const void* retAddr = __builtin_return_address(0); + const auto type_id = reinterpret_cast(info)->type_id; + auto& rt = typeart::RuntimeSystem::get(); + assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); + rt.allocation_tracker().onAllocStack(addr, type_id, count, retAddr); } diff --git a/lib/runtime/CMakeLists.txt b/lib/runtime/CMakeLists.txt index 0e030c5f..5d04cfbb 100644 --- a/lib/runtime/CMakeLists.txt +++ b/lib/runtime/CMakeLists.txt @@ -22,6 +22,7 @@ set(RUNTIME_LIB_SOURCES RuntimeInterface.h TypeResolution.cpp AllocationTracking.cpp + GlobalTypeDefCallbacks.cpp AllocationTracking.h TypeResolution.h Runtime.cpp @@ -48,6 +49,7 @@ target_link_libraries( $<$:MPI::MPI_CXX> $<$:phpmap::phpmap> $<$:absl::btree> + $<$:absl::flat_hash_map> $<$:sf::pointer> $<$>:Threads::Threads> ) diff --git a/lib/runtime/CallbackInterface.h b/lib/runtime/CallbackInterface.h index fa1371c9..6ca76206 100644 --- a/lib/runtime/CallbackInterface.h +++ b/lib/runtime/CallbackInterface.h @@ -36,6 +36,15 @@ void __typeart_alloc_omp(const void* addr, int type_id, size_t count); void __typeart_free_omp(const void* addr); void __typeart_alloc_stack_omp(const void* addr, int type_id, size_t count); void __typeart_leave_scope_omp(int alloca_count); + +// Called for inlined type definitions mode +void __typeart_alloc_mty(const void* addr, const void* info, size_t count); +void __typeart_alloc_global_mty(const void* addr, const void* info, size_t count); +void __typeart_alloc_stack_mty(const void* addr, const void* info, size_t count); +void __typeart_register_type(const void* type); + +void __typeart_alloc_global_mty_omp(const void* addr, const void* info, size_t count); +void __typeart_alloc_stack_mty_omp(const void* addr, const void* info, size_t count); #ifdef __cplusplus } #endif diff --git a/lib/runtime/GlobalTypeDefCallbacks.cpp b/lib/runtime/GlobalTypeDefCallbacks.cpp new file mode 100644 index 00000000..77812f5b --- /dev/null +++ b/lib/runtime/GlobalTypeDefCallbacks.cpp @@ -0,0 +1,116 @@ +#include "GlobalTypeDefCallbacks.h" + +#include "CallbackInterface.h" +#include "Runtime.h" +#include "RuntimeData.h" +#include "TypeInterface.h" +#include "support/Logger.h" +#include "typelib/TypeDatabase.h" + +#include +#include +#include +#include + +namespace typeart { + +#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 TYPEART_RUNTIME_GUARD \ + typeart::RTGuard GUARDNAME; \ + if (!GUARDNAME.shouldTrack()) { \ + return; \ + } + +class GlobalTypeTranslator::Impl { + TypeDatabase& type_db_; + RuntimeT::TypeLookupMapT& translator_map_; + int struct_count{0}; + + public: + explicit Impl(TypeDatabase& db, RuntimeT::TypeLookupMapT& translator_map) + : type_db_(db), translator_map_(translator_map) { + } + + int next_type_id(const GlobalTypeInfo* type) { + // a fwd_decl and the decl must have the same type_id: + { + const auto& struct_list = type_db_.getStructList(); + for (const auto& type_in_db : struct_list) { + if (type_in_db.name == type->name) { + return type_in_db.type_id; + } + } + } + const int id = static_cast(TYPEART_NUM_RESERVED_IDS) + struct_count; + ++struct_count; + return id; + } + + int register_t(const GlobalTypeInfo* type) { // NOLINT(misc-no-recursion) + if (unlikely(type == nullptr)) { + LOG_ERROR("Type descriptor is NULL, is it a weak extern global due to fwd decl?"); + return TYPEART_UNKNOWN_TYPE; + } + + if (auto element = translator_map_.find(type); element != translator_map_.end()) { + return element->second; + } + + const bool built_in = builtins::BuiltInQuery::is_builtin_type(type->type_id); + if (built_in) { + translator_map_.try_emplace(type, type->type_id); + return type->type_id; + } + + StructTypeInfo type_descriptor; + type_descriptor.type_id = next_type_id(type); + type_descriptor.name = type->name; + type_descriptor.extent = type->extent; + type_descriptor.num_members = type->num_members; + type_descriptor.flag = static_cast(type->flag); + + type_descriptor.array_sizes.reserve(type->num_members); + type_descriptor.offsets.reserve(type->num_members); + type_descriptor.member_types.reserve(type->num_members); + for (uint32_t i = 0; i < type->num_members; ++i) { + const auto member_id = register_t(type->member_types[i]); + const auto array_size = type->array_sizes[i]; + const auto offset = type->offsets[i]; + type_descriptor.array_sizes.emplace_back(array_size); + type_descriptor.offsets.emplace_back(offset); + type_descriptor.member_types.emplace_back(member_id); + } + + const bool fwd_decl = type_descriptor.flag == StructTypeFlag::FWD_DECL; + type_db_.registerStruct(type_descriptor, not fwd_decl); + translator_map_.try_emplace(type, type_descriptor.type_id); + + return type_descriptor.type_id; + } +}; + +GlobalTypeTranslator::GlobalTypeTranslator(TypeDatabase& db) : pImpl(std::make_unique(db, translator_map)) { +} + +GlobalTypeTranslator::~GlobalTypeTranslator() = default; + +void GlobalTypeTranslator::register_type(const void* type) { + const auto* info_struct = reinterpret_cast(type); + const auto type_id = pImpl->register_t(info_struct); + LOG_DEBUG("Type id reset: " << info_struct->name << " " << info_struct->type_id << " vs. " << type_id) + const_cast(info_struct)->type_id = type_id; +} + +} // namespace typeart + +void __typeart_register_type(const void* type_ptr) { + TYPEART_RUNTIME_GUARD; + if (unlikely(type_ptr == nullptr)) { + LOG_FATAL("type_ptr is NULL\n"); + return; + } + typeart::RuntimeSystem::get().type_translator().register_type(type_ptr); +} diff --git a/lib/runtime/GlobalTypeDefCallbacks.h b/lib/runtime/GlobalTypeDefCallbacks.h new file mode 100644 index 00000000..b59d93d4 --- /dev/null +++ b/lib/runtime/GlobalTypeDefCallbacks.h @@ -0,0 +1,44 @@ +#ifndef LIB_RUNTIME_GLOBALTYPEDEFCALLBACKS +#define LIB_RUNTIME_GLOBALTYPEDEFCALLBACKS + +#include "RuntimeData.h" +#include "TypeInterface.h" +#include "support/Logger.h" + +namespace typeart { + +class TypeDatabase; + +class GlobalTypeTranslator final { + private: + RuntimeT::TypeLookupMapT translator_map; + class Impl; + std::unique_ptr pImpl; + + public: + explicit GlobalTypeTranslator(TypeDatabase& db); + ~GlobalTypeTranslator(); + + void register_type(const void* type); + + [[nodiscard]] inline const RuntimeT::TypeLookupMapT& get_translator_map() const { + return translator_map; + } + + [[nodiscard]] inline int get_type_id_for(MemAddr addr) const { + if (auto element = translator_map.find(addr); element != translator_map.end()) { + return element->second; + } + LOG_WARNING("Unknown type for address " << addr) + return TYPEART_UNKNOWN_TYPE; + } + + GlobalTypeTranslator(const GlobalTypeTranslator&) = delete; + GlobalTypeTranslator& operator=(const GlobalTypeTranslator&) = delete; + GlobalTypeTranslator(GlobalTypeTranslator&&) noexcept = delete; + GlobalTypeTranslator& operator=(GlobalTypeTranslator&&) noexcept = delete; +}; + +} // namespace typeart + +#endif /* LIB_RUNTIME_GLOBALTYPEDEFCALLBACKS */ diff --git a/lib/runtime/Runtime.cpp b/lib/runtime/Runtime.cpp index 49786879..441f41cc 100644 --- a/lib/runtime/Runtime.cpp +++ b/lib/runtime/Runtime.cpp @@ -19,13 +19,10 @@ #include "TypeInterface.h" #include "support/ConfigurationBase.h" #include "support/Logger.h" -// #include "llvm/Support/raw_ostream.h" #include #include -#include #include -#include #include namespace typeart { @@ -36,7 +33,7 @@ std::string toString(const void* memAddr, int typeId, size_t count, size_t typeS bool heap) { std::string buf; llvm::raw_string_ostream s(buf); - const auto name = typeart::RuntimeSystem::get().typeResolution.db().getTypeName(typeId); + const auto name = typeart::RuntimeSystem::get().database().getTypeName(typeId); if ((typeId == TYPEART_VOID) && heap) { count /= typeSize; } @@ -45,7 +42,7 @@ std::string toString(const void* memAddr, int typeId, size_t count, size_t typeS } std::string toString(const void* memAddr, int typeId, size_t count, const void* calledFrom, bool heap) { - const auto typeSize = typeart::RuntimeSystem::get().typeResolution.db().getTypeSize(typeId); + const auto typeSize = typeart::RuntimeSystem::get().database().getTypeSize(typeId); return toString(memAddr, typeId, count, typeSize, calledFrom, heap); } @@ -64,11 +61,12 @@ inline void printTraceStart() { static constexpr const char* defaultTypeFileName = config::ConfigStdArgValues::types; -RuntimeSystem::RuntimeSystem() : rtScopeInit(), typeResolution(typeDB, recorder), allocTracker(typeDB, recorder) { +RuntimeSystem::RuntimeSystem() + : typeResolution_(typeDB_, recorder), allocTracker_(typeDB_, recorder), type_translator_(typeDB_) { debug::printTraceStart(); auto loadTypes = [this](const std::string& file, std::error_code& ec) -> bool { - auto loaded = io::load(&typeDB, file); + auto loaded = io::load(&typeDB_, file); ec = loaded.getError(); return !static_cast(ec); }; @@ -88,7 +86,7 @@ RuntimeSystem::RuntimeSystem() : rtScopeInit(), typeResolution(typeDB, recorder) if (!loadTypes(type_file, error)) { LOG_FATAL("Failed to load recorded types from " << config::EnvironmentStdArgs::types << "=" << type_file << " .Reason: " << error.message()); - std::exit(EXIT_FAILURE); // TODO: Error handling + // std::exit(EXIT_FAILURE); // TODO: Error handling } } else { if (!loadTypes(defaultTypeFileName, error)) { @@ -102,7 +100,7 @@ RuntimeSystem::RuntimeSystem() : rtScopeInit(), typeResolution(typeDB, recorder) } std::stringstream ss; - const auto& typeList = typeDB.getStructList(); + const auto& typeList = typeDB_.getStructList(); for (const auto& structInfo : typeList) { ss << structInfo.name << ", "; } diff --git a/lib/runtime/Runtime.h b/lib/runtime/Runtime.h index d0e52036..b17aaf43 100644 --- a/lib/runtime/Runtime.h +++ b/lib/runtime/Runtime.h @@ -10,11 +10,12 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef TYPEART_RUNTIME_H -#define TYPEART_RUNTIME_H +#ifndef LIB_RUNTIME_RUNTIME +#define LIB_RUNTIME_RUNTIME #include "AccessCounter.h" #include "AllocationTracking.h" +#include "GlobalTypeDefCallbacks.h" #include "TypeDB.h" #include "TypeResolution.h" @@ -44,7 +45,7 @@ struct RuntimeSystem { rtScope = true; } - void reset() { + void reset() const { // Reset rtScope to old value. rtScope = rtScopeWasSet; } @@ -54,15 +55,43 @@ struct RuntimeSystem { }; RTScopeInitializer rtScopeInit; - TypeDB typeDB{}; + TypeDB typeDB_{}; + TypeResolution typeResolution_; + AllocationTracker allocTracker_; + GlobalTypeTranslator type_translator_; public: Recorder recorder{}; - TypeResolution typeResolution; - AllocationTracker allocTracker; - static thread_local bool rtScope; + const TypeDB& database() const { + return typeDB_; + } + + TypeResolution& get_type_resolution() { + return typeResolution_; + } + + AllocationTracker& allocation_tracker() { + return allocTracker_; + } + + GlobalTypeTranslator& type_translator() { + return type_translator_; + } + + const GlobalTypeTranslator& type_translator() const { + return type_translator_; + } + + const TypeResolution& type_resolution() const { + return typeResolution_; + } + + const AllocationTracker& allocation_tracker() const { + return allocTracker_; + } + static RuntimeSystem& get() { // As opposed to a global variable, a singleton + instantiation during // the first callback/query avoids some problems when @@ -97,4 +126,4 @@ struct RTGuard final { } // namespace typeart -#endif // TYPEART_RUNTIME_H +#endif /* LIB_RUNTIME_RUNTIME */ diff --git a/lib/runtime/RuntimeData.h b/lib/runtime/RuntimeData.h index 998ae803..6253655e 100644 --- a/lib/runtime/RuntimeData.h +++ b/lib/runtime/RuntimeData.h @@ -21,10 +21,12 @@ #ifdef TYPEART_PHMAP #error TypeART-RT: Set ABSL and PHMAP, mutually exclusive. #endif + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #pragma GCC diagnostic ignored "-Wshadow" #include "absl/container/btree_map.h" +#include "absl/container/flat_hash_map.h" #pragma GCC diagnostic pop #endif @@ -33,10 +35,12 @@ #error TypeART-RT: Set ABSL and PHMAP, mutually exclusive. #endif #include "parallel_hashmap/btree.h" +#include "parallel_hashmap/phmap.h" #endif #if !defined(TYPEART_PHMAP) && !defined(TYPEART_ABSEIL) #include +#include #endif #ifdef USE_SAFEPTR @@ -46,7 +50,14 @@ #include "safe_ptr.h" #endif +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define __SANITIZE_ADDRESS__ +#endif +#endif + #include // size_t +#include #include namespace typeart { @@ -59,20 +70,42 @@ struct PointerInfo final { MemAddr debug{nullptr}; }; +struct GlobalTypeInfo { + std::int32_t type_id; + const std::uint32_t extent; + const std::uint16_t num_members; + const std::uint16_t flag; + + const char* name; + const std::uint16_t* offsets; + const std::uint16_t* array_sizes; + const GlobalTypeInfo** member_types; +}; + struct RuntimeT { using Stack = std::vector; static constexpr auto StackReserve{512U}; static constexpr char StackName[] = "std::vector"; #ifdef TYPEART_PHMAP - using PointerMapBaseT = phmap::btree_map; + using PointerMapBaseT = phmap::btree_map; + template + using HashmapT = phmap::flat_hash_map; static constexpr char MapName[] = "phmap::btree_map"; #endif #ifdef TYPEART_ABSEIL - using PointerMapBaseT = absl::btree_map; + using PointerMapBaseT = absl::btree_map; + template +#ifdef __SANITIZE_ADDRESS__ + using HashmapT = std::unordered_map; +#else + using HashmapT = absl::flat_hash_map; +#endif static constexpr char MapName[] = "absl::btree_map"; #endif #if !defined(TYPEART_PHMAP) && !defined(TYPEART_ABSEIL) - using PointerMapBaseT = std::map; + using PointerMapBaseT = std::map; + template + using HashmapT = std::unordered_map; static constexpr char MapName[] = "std::map"; #endif #ifdef USE_SAFEPTR @@ -82,10 +115,11 @@ struct RuntimeT { using PointerMap = PointerMapBaseT; static constexpr bool has_safe_map{false}; #endif - using MapEntry = PointerMapBaseT::value_type; - using MappedType = PointerMapBaseT::mapped_type; - using MapKey = PointerMapBaseT::key_type; - using StackEntry = Stack::value_type; + using MapEntry = PointerMapBaseT::value_type; + using MappedType = PointerMapBaseT::mapped_type; + using MapKey = PointerMapBaseT::key_type; + using StackEntry = Stack::value_type; + using TypeLookupMapT = HashmapT; }; } // namespace typeart diff --git a/lib/runtime/TypeResolution.cpp b/lib/runtime/TypeResolution.cpp index 0047a643..8552d326 100644 --- a/lib/runtime/TypeResolution.cpp +++ b/lib/runtime/TypeResolution.cpp @@ -16,16 +16,14 @@ #include "Runtime.h" #include "RuntimeData.h" #include "RuntimeInterface.h" +#include "TypeDB.h" #include "TypeInterface.h" #include "support/Logger.h" #include "support/System.h" -#include "llvm/Support/raw_ostream.h" - #include #include #include -#include #include #include @@ -274,22 +272,23 @@ TypeResolution::TypeArtStatus TypeResolution::getStructInfo(int type_id, const S return TYPEART_INVALID_ID; } -const TypeDB& TypeResolution::db() const { - return type_database; -} +// const TypeDB& TypeResolution::db() const { +// return type_database; +// } namespace detail { // inline typeart_status query_type(const void* addr, int* type, size_t* count) { // auto alloc = typeart::RuntimeSystem::get().allocTracker.findBaseAlloc(addr); // typeart::RuntimeSystem::get().recorder.incUsedInRequest(addr); // if (alloc) { -// return typeart::RuntimeSystem::get().typeResolution.getTypeInfo(addr, alloc->first, alloc->second, type, count); +// return typeart::RuntimeSystem::get().getTypeResolution().getTypeInfo(addr, alloc->first, alloc->second, type, +// count); // } // return TYPEART_UNKNOWN_ADDRESS; // } inline typeart_status query_type(const void* addr, typeart_type_info& info) { - auto alloc = typeart::RuntimeSystem::get().allocTracker.findBaseAlloc(addr); + auto alloc = typeart::RuntimeSystem::get().allocation_tracker().findBaseAlloc(addr); typeart::RuntimeSystem::get().recorder.incUsedInRequest(addr); if (alloc) { typeart_base_type_info base; @@ -299,8 +298,8 @@ inline typeart_status query_type(const void* addr, typeart_type_info& info) { info.base_type_info = base; info.address = addr; - const auto result = typeart::RuntimeSystem::get().typeResolution.getTypeInfo(addr, alloc->first, alloc->second, - &info.type_id, &info.count); + const auto result = typeart::RuntimeSystem::get().get_type_resolution().getTypeInfo( + addr, alloc->first, alloc->second, &info.type_id, &info.count); typeart::RuntimeSystem::get().recorder.incTypeQuery(base.type_id); return result; @@ -310,7 +309,7 @@ inline typeart_status query_type(const void* addr, typeart_type_info& info) { 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(type_id, &struct_info); + typeart_status status = typeart::RuntimeSystem::get().get_type_resolution().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(); @@ -367,7 +366,7 @@ typeart_status typeart_get_containing_type(typeart_type_info type, typeart_base_ containing_type->count = type.base_type_info.count; containing_type->address = type.base_type_info.address; const typeart::PointerInfo info{type.base_type_info.type_id, type.base_type_info.count}; - const auto result = typeart::RuntimeSystem::get().typeResolution.getContainingTypeInfo( + const auto result = typeart::RuntimeSystem::get().type_resolution().getContainingTypeInfo( type.address, containing_type->address, info, &containing_type->count, byte_offset); return result; @@ -376,7 +375,7 @@ typeart_status typeart_get_containing_type(typeart_type_info type, typeart_base_ typeart_status typeart_get_subtype(const typeart_struct_layout* container_layout, const void* base_addr, size_t offset, typeart_base_type_info* subtype_info, size_t* subtype_byte_offset) { typeart::RTGuard guard; - auto status = typeart::RuntimeSystem::get().typeResolution.getSubTypeInfo( + auto status = typeart::RuntimeSystem::get().get_type_resolution().getSubTypeInfo( base_addr, offset, *container_layout, &subtype_info->type_id, &subtype_info->address, subtype_byte_offset, &subtype_info->count); return status; @@ -389,7 +388,7 @@ typeart_status typeart_resolve_type_id(int type_id, typeart_struct_layout* struc typeart_status typeart_get_return_address(const void* addr, const void** return_addr) { typeart::RTGuard guard; - auto alloc = typeart::RuntimeSystem::get().allocTracker.findBaseAlloc(addr); + auto alloc = typeart::RuntimeSystem::get().allocation_tracker().findBaseAlloc(addr); if (alloc) { *return_addr = alloc.value().second.debug; @@ -463,45 +462,45 @@ typeart_status_t typeart_free_source_location(typeart_source_location* source_lo const char* typeart_get_type_name(int type_id) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.db().getTypeName(type_id).c_str(); + return typeart::RuntimeSystem::get().database().getTypeName(type_id).c_str(); } bool typeart_is_vector_type(int type_id) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.db().isVectorType(type_id); + return typeart::RuntimeSystem::get().database().isVectorType(type_id); } bool typeart_is_valid_type(int type_id) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.db().isValid(type_id); + return typeart::RuntimeSystem::get().database().isValid(type_id); } bool typeart_is_reserved_type(int type_id) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.db().isReservedType(type_id); + return typeart::RuntimeSystem::get().database().isReservedType(type_id); } bool typeart_is_builtin_type(int type_id) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.db().isBuiltinType(type_id); + return typeart::RuntimeSystem::get().database().isBuiltinType(type_id); } bool typeart_is_struct_type(int type_id) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.db().isStructType(type_id); + return typeart::RuntimeSystem::get().database().isStructType(type_id); } bool typeart_is_userdefined_type(int type_id) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.db().isUserDefinedType(type_id); + return typeart::RuntimeSystem::get().database().isUserDefinedType(type_id); } bool typeart_is_union(int type_id) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.db().isUnion(type_id); + return typeart::RuntimeSystem::get().database().isUnion(type_id); } size_t typeart_get_type_size(int type_id) { typeart::RTGuard guard; - return typeart::RuntimeSystem::get().typeResolution.db().getTypeSize(type_id); + return typeart::RuntimeSystem::get().database().getTypeSize(type_id); } diff --git a/lib/runtime/TypeResolution.h b/lib/runtime/TypeResolution.h index f47ca4b3..edd8ee9c 100644 --- a/lib/runtime/TypeResolution.h +++ b/lib/runtime/TypeResolution.h @@ -16,14 +16,14 @@ #include "AccessCounter.h" #include "RuntimeData.h" #include "RuntimeInterface.h" -#include "TypeDB.h" -#include "TypeInterface.h" #include -#include namespace typeart { +class TypeDB; +struct StructTypeInfo; + struct PointerInfo; class TypeResolution { @@ -50,7 +50,7 @@ class TypeResolution { TypeArtStatus getStructInfo(int type_id, const StructTypeInfo** structInfo) const; - [[nodiscard]] const TypeDB& db() const; + // [[nodiscard]] const TypeDB& db() const; }; } // namespace typeart diff --git a/lib/support/ConfigurationBaseOptions.h b/lib/support/ConfigurationBaseOptions.h index a8fe1e4d..87b889b0 100644 --- a/lib/support/ConfigurationBaseOptions.h +++ b/lib/support/ConfigurationBaseOptions.h @@ -44,5 +44,7 @@ TYPEART_CONFIG_OPTION(analysis_filter_pointer_alloc, "analysis-filter-pointer-al TYPEART_CONFIG_OPTION(analysis_filter_alloca_non_array, "analysis-filter-non-array-alloca", bool, false, "Filter scalar valued allocas.", "ANALYSIS_FILTER_NON_ARRAY_ALLOCA") TYPEART_CONFIG_OPTION(typegen, "typegen", std::string, "dimeta", "Select type layout generator.", "TYPEGEN") +TYPEART_CONFIG_OPTION(type_serialization, "type-serialization", std::string, "file", + "Serialization mode for type representation.", "TYPE_SERIALIZATION") #undef TYPEART_CONFIG_OPTION diff --git a/lib/typelib/TypeDB.cpp b/lib/typelib/TypeDB.cpp index 056cc963..9f262ed0 100644 --- a/lib/typelib/TypeDB.cpp +++ b/lib/typelib/TypeDB.cpp @@ -85,7 +85,7 @@ std::pair, std::error_code> make_database(std::str using namespace builtins; -const std::string unknown_struck_name{"typeart_unknown_struct"}; +const std::string unknown_struct_name{"typeart_unknown_struct"}; void TypeDB::clear() { struct_info_vec.clear(); @@ -115,9 +115,12 @@ bool TypeDB::isPointerType(int type_id) const { bool TypeDB::isUserDefinedType(int type_id) const { const auto* structInfo = getStructInfo(type_id); - LOG_DEBUG(structInfo->name << " " << static_cast(structInfo->flag) << " " - << (static_cast(structInfo->flag) == static_cast(StructTypeFlag::USER_DEFINED)) - << " " << (static_cast(structInfo->flag) == static_cast(StructTypeFlag::UNION))) + if (structInfo != nullptr) { + LOG_DEBUG(structInfo->name << " " << static_cast(structInfo->flag) << " " + << (static_cast(structInfo->flag) == static_cast(StructTypeFlag::USER_DEFINED)) + << " " + << (static_cast(structInfo->flag) == static_cast(StructTypeFlag::UNION))) + } return (structInfo != nullptr) && (static_cast(structInfo->flag) == static_cast(StructTypeFlag::USER_DEFINED) || static_cast(structInfo->flag) == static_cast(StructTypeFlag::UNION)); @@ -133,8 +136,10 @@ bool TypeDB::isVectorType(int type_id) const { bool TypeDB::isUnion(int type_id) const { const auto* structInfo = getStructInfo(type_id); - LOG_DEBUG(structInfo->name << " " << static_cast(structInfo->flag) << " " - << (static_cast(structInfo->flag) == static_cast(StructTypeFlag::UNION))) + if (structInfo != nullptr) { + LOG_DEBUG(structInfo->name << " " << static_cast(structInfo->flag) << " " + << (static_cast(structInfo->flag) == static_cast(StructTypeFlag::UNION))) + } return (structInfo != nullptr) && (static_cast(structInfo->flag) == static_cast(StructTypeFlag::UNION)); } @@ -155,7 +160,7 @@ void TypeDB::registerStruct(const StructTypeInfo& struct_type, bool overwrite) { LOG_ERROR("Type ID is reserved for unknown types. Struct: " << struct_type.name); } else { if (!overwrite) { - LOG_ERROR("Struct type ID already registered for " << struct_type.name << ". Conflicting struct is " + LOG_DEBUG("Struct type ID already registered for " << struct_type.name << ". Conflicting struct is " << getStructInfo(struct_type.type_id)->name); return; } @@ -181,7 +186,7 @@ const std::string& TypeDB::getTypeName(int type_id) const { } } - return unknown_struck_name; + return unknown_struct_name; } size_t TypeDB::getTypeSize(int type_id) const { diff --git a/lib/typelib/TypeDatabase.h b/lib/typelib/TypeDatabase.h index b32b521b..07678ffe 100644 --- a/lib/typelib/TypeDatabase.h +++ b/lib/typelib/TypeDatabase.h @@ -22,7 +22,7 @@ namespace typeart { -enum class StructTypeFlag : int { USER_DEFINED = 1, LLVM_VECTOR = 2, FWD_DECL = 4, UNION = 8 }; +enum class StructTypeFlag : int { USER_DEFINED = 1, LLVM_VECTOR = 2, FWD_DECL = 4, UNION = 8, BUILTIN = 16 }; struct StructTypeInfo { int type_id; diff --git a/scripts/opt-shim.in b/scripts/opt-shim.in index c3dc9af0..bd1659ef 100644 --- a/scripts/opt-shim.in +++ b/scripts/opt-shim.in @@ -67,6 +67,14 @@ function typeart_test_parse_cmd_line_fn() { export TYPEART_ANALYSIS_FILTER_POINTER_ALLOCA="${1#--typeart-analysis-filter-pointer-alloca=}" shift ;; + --typeart-type-serialization=*) + export TYPEART_TYPE_SERIALIZATION="${1#--typeart-type-serialization=}" + shift + ;; + --typeart-config=*) + export TYPEART_CONFIG_FILE="${1#--typeart-config=}" + shift + ;; *) typeart_test_pass_wrapper_more_args+=" $1" shift 1 diff --git a/scripts/typeart-wrapperv2.in b/scripts/typeart-wrapperv2.in index ef0557c8..cefc4091 100644 --- a/scripts/typeart-wrapperv2.in +++ b/scripts/typeart-wrapperv2.in @@ -98,7 +98,9 @@ function typeart_main_driver_fn() { if [ "$?" == 1 ]; then typeart_more_flags+=" ${typeart_ldflags}" fi - + + # export TYPEART_TYPE_SERIALIZATION="${TYPEART_TYPE_SERIALIZATION:-hybrid}" + $typeart_compiler ${typeart_plugin} ${typeart_includes} ${typeart_more_flags} ${typeart_san_flags} $@ } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c6ed9114..ab79a884 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -145,6 +145,7 @@ set(TYPEART_SUITES runtime script typemapping + runtime_inlined_types staging ) diff --git a/test/lit.cfg b/test/lit.cfg index d7cde5df..b199110f 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -43,6 +43,7 @@ if config.asan: config.available_features.add('asan') if config.ubsan: config.available_features.add('ubsan') + # config.environment['UBSAN_OPTIONS'] = 'silence_unsigned_overflow=1' if config.tsan: config.available_features.add('tsan') if config.tsan or config.asan or config.ubsan: diff --git a/test/pass/arrays/05_vector.c b/test/pass/arrays/05_vector.c index a688988b..6a4f42b4 100644 --- a/test/pass/arrays/05_vector.c +++ b/test/pass/arrays/05_vector.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %remove %tu_yaml && %c-to-llvm %s | %apply-typeart --typeart-stack=true -S 2>&1 | %filecheck %s +// RUN: %remove %tu_yaml && %c-to-llvm %s | %apply-typeart --typeart-type-serialization=file --typeart-stack=true -S 2>&1 | %filecheck %s // clang-format on typedef float float2 __attribute__((ext_vector_type(2))); diff --git a/test/pass/arrays/07_avx.c b/test/pass/arrays/07_avx.c index 600ebed3..b9f26ec1 100644 --- a/test/pass/arrays/07_avx.c +++ b/test/pass/arrays/07_avx.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %remove %tu_yaml && %c-to-llvm -mavx %s | %opt -O2 -S | %apply-typeart --typeart-stack=true -S 2>&1 | %filecheck %s +// RUN: %remove %tu_yaml && %c-to-llvm -mavx %s | %opt -O2 -S | %apply-typeart --typeart-type-serialization=file --typeart-stack=true -S 2>&1 | %filecheck %s // clang-format on #include diff --git a/test/pass/filter/08_amg_box_algebra_mock.c b/test/pass/filter/08_amg_box_algebra_mock.c index 2519c118..ef4e1992 100644 --- a/test/pass/filter/08_amg_box_algebra_mock.c +++ b/test/pass/filter/08_amg_box_algebra_mock.c @@ -150,7 +150,7 @@ int hypre_MinUnionBoxes(hypre_BoxArray* boxes) { break; } /*switch(i) */ - } /* for (i= 0; i< 5; i++) */ + } /* for (i= 0; i< 5; i++) */ hypre_TFree(rotated_box); hypre_UnionBoxes(boxes); @@ -233,7 +233,7 @@ int hypre_MinUnionBoxes(hypre_BoxArray* boxes) { break; } /* switch(array) */ - } /* if (array != 5) */ + } /* if (array != 5) */ hypre_BoxArrayArrayDestroy(rotated_array); diff --git a/test/pass/filter/09_milc_gauge_stuff_mock.c b/test/pass/filter/09_milc_gauge_stuff_mock.c index 3b3a747f..ff743da0 100644 --- a/test/pass/filter/09_milc_gauge_stuff_mock.c +++ b/test/pass/filter/09_milc_gauge_stuff_mock.c @@ -127,9 +127,9 @@ void make_loop_table() { loop_num[iloop] = count; } /* end reflection*/ - } /* end permutation if block */ - } /* end permutation */ - } /* end iloop */ + } /* end permutation if block */ + } /* end permutation */ + } /* end iloop */ /* print out the loop coefficients */ printf("loop coefficients: nloop rep loop_coeff multiplicity\n"); diff --git a/test/pass/inline_types/01_simple_malloc_int.c b/test/pass/inline_types/01_simple_malloc_int.c new file mode 100644 index 00000000..69c16ab5 --- /dev/null +++ b/test/pass/inline_types/01_simple_malloc_int.c @@ -0,0 +1,30 @@ +// clang-format off +// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S 2>&1 | %filecheck %s + +// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=hybrid -S 2>&1 | %filecheck %s --check-prefix HYBRID + +// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=file -S 2>&1 | %filecheck %s --check-prefix FILE + +// REQUIRES: llvm-18 || llvm-19 +// clang-format on + +#include +void test() { + int* p = (int*)malloc(42 * sizeof(int)); +} +// CHECK: TypeArtPass [Heap] +// CHECK-NEXT: Malloc{{[ ]*}}:{{[ ]*}}1 +// CHECK-NEXT: Free{{[ ]*}}:{{[ ]*}}0 +// CHECK-NEXT: Alloca{{[ ]*}}:{{[ ]*}}0 + +// CHECK: %struct._typeart_struct_layout_t = type { i32, i32, i16, i16, ptr, ptr, ptr, ptr } +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} ptr @malloc +// CHECK-NEXT: call void @__typeart_alloc_mty(ptr [[POINTER]], ptr {{.*}}, i64 42) + +// HYBRID-NOT: %struct._typeart_struct_layout_t = type { +// HYBRID: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} ptr @malloc +// HYBRID-NEXT: call void @__typeart_alloc(ptr [[POINTER]], i32 13, i64 42) + +// FILE-NOT: %struct._typeart_struct_layout_t = type { +// FILE: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} ptr @malloc +// FILE-NEXT: call void @__typeart_alloc(ptr [[POINTER]], i32 13, i64 42) diff --git a/test/pass/inline_types/02_calloc_realloc.c b/test/pass/inline_types/02_calloc_realloc.c new file mode 100644 index 00000000..6c568d70 --- /dev/null +++ b/test/pass/inline_types/02_calloc_realloc.c @@ -0,0 +1,31 @@ +// clang-format off +// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S 2>&1 | %filecheck %s --check-prefix=REALLOC +// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S 2>&1 | %filecheck %s + +// REQUIRES: llvm-18 || llvm-19 +// clang-format on +#include + +int main() { + double* pd = calloc(10, sizeof(double)); + + pd = realloc(pd, 20 * sizeof(double)); + + return 0; +} + +// clang-format off + +// CHECK: TypeArtPass [Heap] +// CHECK-NEXT: Malloc{{[ ]*}}:{{[ ]*}}2 +// CHECK-NEXT: Free{{[ ]*}}:{{[ ]*}}0 +// CHECK-NEXT: Alloca{{[ ]*}}:{{[ ]*}}0 + +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} ptr @calloc(i64{{( noundef)?}} [[SIZE:[0-9]+]], i64{{( noundef)?}} 8) +// CHECK-NEXT: call void @__typeart_alloc_mty(ptr [[POINTER]], ptr {{.*}}, i64 [[SIZE]]) + +// REALLOC: __typeart_free(ptr [[POINTER:%[0-9a-z]+]]) +// REALLOC-NEXT: [[POINTER2:%[0-9a-z]+]] = call{{( align [0-9]+)?}} ptr @realloc(ptr{{( noundef)?}} [[POINTER]], i64{{( noundef)?}} 160) +// REALLOC-NEXT: __typeart_alloc_mty(ptr [[POINTER2]], ptr {{.*}}, i64 20) + +// clang-format on diff --git a/test/pass/inline_types/03_simple_malloc_struct.c b/test/pass/inline_types/03_simple_malloc_struct.c new file mode 100644 index 00000000..9cec9b30 --- /dev/null +++ b/test/pass/inline_types/03_simple_malloc_struct.c @@ -0,0 +1,39 @@ +// clang-format off +// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S 2>&1 | %filecheck %s + +// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=hybrid -S 2>&1 | %filecheck %s --check-prefix HYBRID + +// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=file -S 2>&1 | %filecheck %s --check-prefix FILE + +// REQUIRES: llvm-18 || llvm-19 +// clang-format on +#include +typedef struct ms { + int a; + double b; +} mystruct; + +void test() { + mystruct* m = (mystruct*)malloc(sizeof(mystruct)); + free(m); +} +// CHECK: TypeArtPass [Heap] +// CHECK-NEXT: Malloc{{[ ]*}}:{{[ ]*}}1 +// CHECK-NEXT: Free{{[ ]*}}:{{[ ]*}}1 +// CHECK-NEXT: Alloca{{[ ]*}}:{{[ ]*}}0 + +// CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} ptr @malloc +// CHECK-NEXT: call void @__typeart_alloc_mty(ptr [[POINTER]], ptr {{.*}}, i64 1) + +// CHECK: call void @free(ptr{{( noundef)?}} [[POINTER:%[0-9a-z]+]]) +// CHECK-NEXT: call void @__typeart_free(ptr [[POINTER]]) + +// HYBRID: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} ptr @malloc +// HYBRID-NOT: call void @__typeart_alloc(ptr [[POINTER]] +// HYBRID: call void @free(ptr{{( noundef)?}} [[POINTER:%[0-9a-z]+]]) +// HYBRID-NEXT: call void @__typeart_free(ptr [[POINTER]]) + +// FILE: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} ptr @malloc +// FILE: call void @__typeart_alloc(ptr [[POINTER]], i32 +// FILE: call void @free(ptr{{( noundef)?}} [[POINTER:%[0-9a-z]+]]) +// FILE-NEXT: call void @__typeart_free(ptr [[POINTER]]) diff --git a/test/pass/inline_types/04_fwd_decl.cpp b/test/pass/inline_types/04_fwd_decl.cpp new file mode 100644 index 00000000..01ad31c8 --- /dev/null +++ b/test/pass/inline_types/04_fwd_decl.cpp @@ -0,0 +1,30 @@ +// RUN: %cpp-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S | %filecheck %s + +// CHECK: @_typeart__ZTS6Domain_fwd = weak_odr global %struct._typeart_struct_layout_t { i32 256, + +// REQUIRES: llvm-18 || llvm-19 + +class Domain { + public: + Domain(int ranks, double other); + + int getRanks() const { + return m_ranks; + } + + double getOther() const { + return m_other; + } + + private: + int m_ranks; + double m_other; +}; + +int main(int argc, char* argv[]) { + Domain* dom; + + dom = new Domain(argc, 1.2); + + return dom->getRanks(); +} diff --git a/test/pass/malloc_free/05_simple_malloc_struct.c b/test/pass/malloc_free/05_simple_malloc_struct.c index d33405d6..9b2f33ab 100644 --- a/test/pass/malloc_free/05_simple_malloc_struct.c +++ b/test/pass/malloc_free/05_simple_malloc_struct.c @@ -1,5 +1,5 @@ // clang-format off -// RUN: %remove %tu_yaml && %c-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %remove %tu_yaml && %c-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on #include typedef struct ms { diff --git a/test/pass/misc/05_make_all_callbacks.c b/test/pass/misc/05_make_all_callbacks.c index 0316c9fd..b4201d01 100644 --- a/test/pass/misc/05_make_all_callbacks.c +++ b/test/pass/misc/05_make_all_callbacks.c @@ -3,10 +3,13 @@ #include "../../../lib/runtime/CallbackInterface.h" int main(void) { - int count = 0; - int type_id = 10; - size_t extent = 0; - void* addr = NULL; + int count = 0; + int type_id = 10; + size_t extent = 0; + void* addr = NULL; + const void* info_ptr = NULL; + const void* type_ptr = NULL; + __typeart_alloc(addr, type_id, extent); __typeart_alloc_global(addr, type_id, extent); __typeart_alloc_stack(addr, type_id, extent); @@ -18,6 +21,14 @@ int main(void) { __typeart_alloc_stack_omp(addr, type_id, extent); __typeart_free_omp(addr); __typeart_leave_scope_omp(count); + + __typeart_alloc_mty(addr, info_ptr, count); + __typeart_alloc_global_mty(addr, info_ptr, count); + __typeart_alloc_stack_mty(addr, info_ptr, count); + __typeart_register_type(type_ptr); + __typeart_alloc_global_mty_omp(addr, info_ptr, count); + __typeart_alloc_stack_mty_omp(addr, info_ptr, count); + return 0; } diff --git a/test/pass/misc/07_config_file.c b/test/pass/misc/07_config_file.c index 1e9a48ad..b2386ebf 100644 --- a/test/pass/misc/07_config_file.c +++ b/test/pass/misc/07_config_file.c @@ -1,20 +1,19 @@ // RUN: %c-to-llvm %s | %apply-typeart --typeart-config=%S/07_typeart_config_stack.yml 2>&1 | %filecheck %s // REQUIRES: llvm-14 -// XFAIL: * - #include void test() { int* p = (int*)malloc(42 * sizeof(int)); } -// CHECK: types: {{.*}} +// CHECK: types: 07_config_file.c.yaml // CHECK-NEXT: heap: false // CHECK-NEXT: stack: true // CHECK-NEXT: global: false // CHECK-NEXT: stats: {{.*}} // CHECK-NEXT: stack-lifetime: false // CHECK-NEXT: typegen: {{dimeta|ir}} +// CHECK-NEXT: type-serialization: inline // CHECK-NEXT: filter: false // CHECK-NEXT: call-filter: // CHECK-NEXT: implementation: std diff --git a/test/pass/misc/07_typeart_config_stack.yml b/test/pass/misc/07_typeart_config_stack.yml index 06534720..2a3e2526 100644 --- a/test/pass/misc/07_typeart_config_stack.yml +++ b/test/pass/misc/07_typeart_config_stack.yml @@ -3,8 +3,10 @@ types: "types_config.yaml" heap: false stack: true global: false +stats: true stack-lifetime: false typegen: "dimeta" +type-serialization: inline filter: false call-filter: implementation: "std" diff --git a/test/pass/misc/08_config_file_default.c b/test/pass/misc/08_config_file_default.c index f5bcf213..6e908b29 100644 --- a/test/pass/misc/08_config_file_default.c +++ b/test/pass/misc/08_config_file_default.c @@ -1,5 +1,7 @@ // RUN: %c-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// REQUIRES: !llvm-14 + // CHECK-NOT: {{(Error|Fatal)}} // CHECK: types: {{.*}}.yaml @@ -9,6 +11,7 @@ // CHECK-NEXT: stats: true // CHECK-NEXT: stack-lifetime: true // CHECK-NEXT: typegen: {{dimeta|ir}} +// CHECK-NEXT: type-serialization: hybrid // CHECK-NEXT: filter: false // CHECK-NEXT: call-filter: // CHECK-NEXT: implementation: std diff --git a/test/pass/misc/09_config_file_cl.c b/test/pass/misc/09_config_file_cl.c index f27503e4..21b7fa14 100644 --- a/test/pass/misc/09_config_file_cl.c +++ b/test/pass/misc/09_config_file_cl.c @@ -7,8 +7,6 @@ // Priority control with command line args vs. config file contents. -// XFAIL: * - #include void test() { int x = 0; diff --git a/test/pass/new_delete/03_inv_struct.cpp b/test/pass/new_delete/03_inv_struct.cpp index 09986c9b..ce7354f7 100644 --- a/test/pass/new_delete/03_inv_struct.cpp +++ b/test/pass/new_delete/03_inv_struct.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on // CHECK: TypeArtPass [Heap] diff --git a/test/pass/new_delete/04_inv_struct_array.cpp b/test/pass/new_delete/04_inv_struct_array.cpp index da17ee42..a96e625c 100644 --- a/test/pass/new_delete/04_inv_struct_array.cpp +++ b/test/pass/new_delete/04_inv_struct_array.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on // CHECK: TypeArtPass [Heap] diff --git a/test/pass/new_delete/05_struct_array.cpp b/test/pass/new_delete/05_struct_array.cpp index 7d6b7b3f..ecc2b8b0 100644 --- a/test/pass/new_delete/05_struct_array.cpp +++ b/test/pass/new_delete/05_struct_array.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on // CHECK: TypeArtPass [Heap] 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 dca95502..707ae822 100644 --- a/test/pass/new_delete/06_struct_array_def_dest.cpp +++ b/test/pass/new_delete/06_struct_array_def_dest.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on // CHECK: TypeArtPass [Heap] 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 fa6f3961..68ea898a 100644 --- a/test/pass/new_delete/07_struct_array_userdef_dest.cpp +++ b/test/pass/new_delete/07_struct_array_userdef_dest.cpp @@ -1,12 +1,12 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // Wrong size is calculated due to using Znam call, instead of bitcast to struct.S1* // REQUIRES: dimeta // clang-format on struct S1 { int x; - ~S1(){}; + ~S1() {}; }; // CHECK: call{{.*}} {{i8\*|ptr}} @_Znam(i64{{( noundef)?}} 16) diff --git a/test/pass/new_delete/09_inv_struct_delete.cpp b/test/pass/new_delete/09_inv_struct_delete.cpp index 0e27e635..a1d0eeab 100644 --- a/test/pass/new_delete/09_inv_struct_delete.cpp +++ b/test/pass/new_delete/09_inv_struct_delete.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on // 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 4ebd4309..a4c84555 100644 --- a/test/pass/new_delete/10_inv_struct_array_delete.cpp +++ b/test/pass/new_delete/10_inv_struct_array_delete.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on // CHECK: TypeArtPass [Heap] diff --git a/test/pass/new_delete/11_new_nothrow.cpp b/test/pass/new_delete/11_new_nothrow.cpp index 3af6ca0a..f3e6662a 100644 --- a/test/pass/new_delete/11_new_nothrow.cpp +++ b/test/pass/new_delete/11_new_nothrow.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on #include diff --git a/test/pass/new_delete/12_new_aligned.cpp b/test/pass/new_delete/12_new_aligned.cpp index 62a7ec57..ea5e6fd5 100644 --- a/test/pass/new_delete/12_new_aligned.cpp +++ b/test/pass/new_delete/12_new_aligned.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on #define __cpp_aligned_new 1 diff --git a/test/pass/new_delete/13_new_aligned_nothrow.cpp b/test/pass/new_delete/13_new_aligned_nothrow.cpp index ff785cf4..c552a975 100644 --- a/test/pass/new_delete/13_new_aligned_nothrow.cpp +++ b/test/pass/new_delete/13_new_aligned_nothrow.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on #ifndef __cpp_aligned_new diff --git a/test/pass/new_delete/15_array_cookie.cpp b/test/pass/new_delete/15_array_cookie.cpp index d1ec95fb..6d326b7c 100644 --- a/test/pass/new_delete/15_array_cookie.cpp +++ b/test/pass/new_delete/15_array_cookie.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on @@ -10,7 +10,7 @@ struct S1 { int x; - ~S1(){}; + ~S1() {}; }; // CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} {{i8\*|ptr}} @_Znam(i64{{( noundef)?}} 16) diff --git a/test/pass/new_delete/16_array_cookie_padded.cpp b/test/pass/new_delete/16_array_cookie_padded.cpp index ab9452f7..84921c67 100644 --- a/test/pass/new_delete/16_array_cookie_padded.cpp +++ b/test/pass/new_delete/16_array_cookie_padded.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // clang-format on // CHECK: TypeArtPass [Heap] @@ -9,7 +9,7 @@ struct alignas(16) S1 { int x; - ~S1(){}; + ~S1() {}; }; // CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} {{i8\*|ptr}} @_Znam(i64{{( noundef)?}} 48) 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 4669cdfc..fc926355 100644 --- a/test/pass/new_delete/17_array_cookie_dynamic_size.cpp +++ b/test/pass/new_delete/17_array_cookie_dynamic_size.cpp @@ -10,7 +10,7 @@ struct S1 { int x; - ~S1(){}; + ~S1() {}; }; // CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} i8* @_Znam(i64{{( noundef)?}} [[ALLOC:%[0-9a-z]+]]) diff --git a/test/pass/new_delete/18_array_cookie_delete.cpp b/test/pass/new_delete/18_array_cookie_delete.cpp index 4fdaff6e..b169ec0c 100644 --- a/test/pass/new_delete/18_array_cookie_delete.cpp +++ b/test/pass/new_delete/18_array_cookie_delete.cpp @@ -9,7 +9,7 @@ struct S1 { int x; - ~S1(){}; + ~S1() {}; }; // CHECK: [[MEM:%[0-9a-z]+]] = getelementptr inbounds i8, {{i8\*|ptr}} [[ARR:%[0-9a-z]+]], i64 -8 diff --git a/test/pass/new_delete/19_array_cookie_dynamic_size_opaque.cpp b/test/pass/new_delete/19_array_cookie_dynamic_size_opaque.cpp index 0174641d..48ede9f1 100644 --- a/test/pass/new_delete/19_array_cookie_dynamic_size_opaque.cpp +++ b/test/pass/new_delete/19_array_cookie_dynamic_size_opaque.cpp @@ -1,5 +1,5 @@ // clang-format off -// RUN: %cpp-to-llvm %s | %apply-typeart -S 2>&1 | %filecheck %s +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s // REQUIRES: llvm-18 || llvm-19 // clang-format on @@ -10,7 +10,7 @@ struct S1 { int x; - ~S1(){}; + ~S1() {}; }; // CHECK: [[MEM:%[0-9a-z]+]] = call{{.*}} ptr @_Znam(i64{{( noundef)?}} [[ALLOC:%[0-9a-z]+]]) diff --git a/test/pass/new_delete/20_no_array_cookie_lulesh_ad.llin b/test/pass/new_delete/20_no_array_cookie_lulesh_ad.llin index 03309760..43d30f97 100644 --- a/test/pass/new_delete/20_no_array_cookie_lulesh_ad.llin +++ b/test/pass/new_delete/20_no_array_cookie_lulesh_ad.llin @@ -1,4 +1,4 @@ -; RUN: %apply-typeart -S < %s | %filecheck %s +; RUN: %apply-typeart --typeart-type-serialization=file -S < %s | %filecheck %s ; REQUIRES: llvm-18 || llvm-19 ; llvm-reduce on lulesh.cc with culprit chunk.hpp:allocateData() where pattern is similar to array cookie. diff --git a/test/runtime/07_simple_struct_type_check.c b/test/runtime/07_simple_struct_type_check.c index 9aeda8b3..c04f5b79 100644 --- a/test/runtime/07_simple_struct_type_check.c +++ b/test/runtime/07_simple_struct_type_check.c @@ -1,4 +1,6 @@ -// RUN: %run %s --typeart-analysis-filter-non-array-alloca=true --compile_flags %dimeta_def 2>&1 | %filecheck %s +// clang-format off +// RUN: %run %s --typeart-analysis-filter-non-array-alloca=true --typeart-type-serialization=file --compile_flags "%dimeta_def -DIGNORE_ID=1" 2>&1 | %filecheck %s +// clang-format on #include "../struct_defs.h" #include "util.h" @@ -17,8 +19,12 @@ int main(int argc, char** argv) { s_int* a = malloc(sizeof(s_int)); // CHECK: Ok check_struct(a, "struct.s_int_t", 1); - // CHECK: Ok +// CHECK: Ok +#if IGNORE_ID == 1 + fprintf(stderr, "Ok\n"); +#else check(a, get_struct_id(0), 1, 0); +#endif // CHECK: Ok check(a, TYPEART_INT_32, 1, 1); // CHECK: Error: Unknown address @@ -30,8 +36,12 @@ int main(int argc, char** argv) { s_builtins* b = malloc(sizeof(s_builtins)); // CHECK: Ok check_struct(b, "struct.s_builtins_t", 1); - // CHECK: Ok +// CHECK: Ok +#if IGNORE_ID == 1 + fprintf(stderr, "Ok\n"); +#else check(b, get_struct_id(1), 1, 0); +#endif // CHECK: Ok check(b, TYPEART_INT_32, 1, 1); // CHECK: Error: Type mismatch @@ -53,8 +63,12 @@ int main(int argc, char** argv) { s_arrays* c = malloc(sizeof(s_arrays)); // CHECK: Ok check_struct(c, "struct.s_arrays_t", 1); - // CHECK: Ok +// CHECK: Ok +#if IGNORE_ID == 1 + fprintf(stderr, "Ok\n"); +#else check(c, get_struct_id(2), 1, 0); +#endif // CHECK: Ok check(c, TYPEART_INT_32, 3, 1); // CHECK: Ok @@ -78,8 +92,12 @@ int main(int argc, char** argv) { s_ptrs* d = malloc(sizeof(s_ptrs)); // CHECK: Ok check_struct(d, "struct.s_ptrs_t", 1); - // CHECK: Ok +// CHECK: Ok +#if IGNORE_ID == 1 + fprintf(stderr, "Ok\n"); +#else check(d, get_struct_id(3), 1, 0); +#endif // CHECK: Ok check(d, TYPEART_INT_8_TEST, 1, 1); // CHECK: Ok @@ -97,8 +115,12 @@ int main(int argc, char** argv) { s_mixed_simple* e = malloc(sizeof(s_mixed_simple)); // CHECK: Ok check_struct(e, "struct.s_mixed_simple_t", 1); - // CHECK: Ok +// CHECK: Ok +#if IGNORE_ID == 1 + fprintf(stderr, "Ok\n"); +#else check(e, get_struct_id(4), 1, 0); +#endif // CHECK: Ok check(e, TYPEART_INT_32, 1, 1); // CHECK: Ok diff --git a/test/runtime/08_recursive_struct_type_check.c b/test/runtime/08_recursive_struct_type_check.c index ff4004bf..618ca496 100644 --- a/test/runtime/08_recursive_struct_type_check.c +++ b/test/runtime/08_recursive_struct_type_check.c @@ -1,4 +1,5 @@ -// RUN: %run %s --typeart-analysis-filter-non-array-alloca=true 2>&1 | %filecheck %s +// RUN: %run %s --typeart-analysis-filter-non-array-alloca=true --compile_flags -DIGNORE_ID=1 2>&1 | %filecheck %s +// RUN: %run %s --typeart-analysis-filter-non-array-alloca=true --typeart-type-serialization=file 2>&1 | %filecheck %s #include "../struct_defs.h" #include "util.h" @@ -6,6 +7,9 @@ #include #include +// #define IGNORE_ID 1 + +// CHECK: [Trace] TypeART Runtime Trace int main(int argc, char** argv) { s_int s; @@ -14,7 +18,11 @@ int main(int argc, char** argv) { // CHECK: Ok check_struct(a, "struct.s_ptr_to_self_t", 1); // CHECK: Ok +#if IGNORE_ID == 1 + fprintf(stderr, "Ok\n"); +#else check(a, get_struct_id(0), 1, 0); +#endif // CHECK: Ok check(a, TYPEART_POINTER, 1, 1); // CHECK: Ok @@ -29,11 +37,19 @@ int main(int argc, char** argv) { // CHECK: Ok check_struct(b, "struct.s_struct_member_t", 1); // CHECK: Ok +#if IGNORE_ID == 1 + fprintf(stderr, "Ok\n"); +#else check(b, get_struct_id(1), 1, 0); +#endif // CHECK: Ok check(b, TYPEART_INT_32, 1, 1); - // CHECK: Ok +// CHECK: Ok +#if IGNORE_ID == 1 + fprintf(stderr, "Ok\n"); +#else check(&b->b, get_struct_id(0), 1, 0); +#endif // CHECK: Ok check(&b->b, TYPEART_POINTER, 1, 1); // CHECK: Ok @@ -48,7 +64,11 @@ int main(int argc, char** argv) { // CHECK: Ok check_struct(c, "struct.s_aos_t", 1); // CHECK: Ok +#if IGNORE_ID == 1 + fprintf(stderr, "Ok\n"); +#else check(c, get_struct_id(2), 1, 0); +#endif // CHECK: Ok check(c, TYPEART_INT_32, 1, 1); // CHECK: Ok diff --git a/test/runtime/22_threads_stack.cpp b/test/runtime/22_threads_stack.cpp index f42c522e..ae48015f 100644 --- a/test/runtime/22_threads_stack.cpp +++ b/test/runtime/22_threads_stack.cpp @@ -1,5 +1,6 @@ // clang-format off -// RUN: %run %s --thread 2>&1 | %filecheck %s --check-prefix=CHECK-TSAN +// : %run %s --thread 2>&1 | %filecheck %s --check-prefix=CHECK-TSAN +// export TYPEART_TYPE_SERIALIZATION=file // RUN: %run %s --thread 2>&1 | %filecheck %s // REQUIRES: thread // clang-format on diff --git a/test/runtime/30_omp_concurrent_w.cpp b/test/runtime/30_omp_concurrent_w.cpp index 80690450..70bfc12b 100644 --- a/test/runtime/30_omp_concurrent_w.cpp +++ b/test/runtime/30_omp_concurrent_w.cpp @@ -44,32 +44,31 @@ int main(int argc, char** argv) { #pragma omp parallel sections num_threads(3) { #pragma omp section - {repeat_alloc(beg, h1); -} + { repeat_alloc(beg, h1); } #pragma omp section -{ repeat_alloc(h2, e); } + { repeat_alloc(h2, e); } #pragma omp section -{ repeat_alloc(h1, h2); } -} + { repeat_alloc(h1, h2); } + } #pragma omp parallel sections num_threads(3) -{ + { #pragma omp section - { repeat_dealloc(beg, h1); } + { repeat_dealloc(beg, h1); } #pragma omp section - { repeat_dealloc(h2, e); } + { repeat_dealloc(h2, e); } #pragma omp section - { repeat_dealloc(h1, h2); } -} + { repeat_dealloc(h1, h2); } + } -// CHECK-TSAN-NOT: ThreadSanitizer + // CHECK-TSAN-NOT: ThreadSanitizer -// CHECK-NOT: Error + // CHECK-NOT: Error -// CHECK: Allocation type detail (heap, stack, global) -// CHECK: 24 : 300 , 0 , 0 , double + // CHECK: Allocation type detail (heap, stack, global) + // CHECK: 24 : 300 , 0 , 0 , double -// CHECK: Free allocation type detail (heap, stack) -// CHECK: 24 : 300 , 0 , double -return 0; + // CHECK: Free allocation type detail (heap, stack) + // CHECK: 24 : 300 , 0 , double + return 0; } diff --git a/test/runtime/41_array_cookie.cpp b/test/runtime/41_array_cookie.cpp index 6db9fbe8..8b7951b1 100644 --- a/test/runtime/41_array_cookie.cpp +++ b/test/runtime/41_array_cookie.cpp @@ -4,7 +4,7 @@ struct S1 { int x; - ~S1(){}; + ~S1() {}; }; int main() { diff --git a/test/runtime/44_typedb.cpp b/test/runtime/44_typedb.cpp index d6db3b8c..64bbaed1 100644 --- a/test/runtime/44_typedb.cpp +++ b/test/runtime/44_typedb.cpp @@ -1,5 +1,8 @@ +// RUN: export TYPEART_TYPE_SERIALIZATION=file // RUN: %run %s --compile_flags "-std=c++17" -o -O3 2>&1 | %filecheck %s +// TODO fails for inline/hybrid + #include "../../lib/runtime/RuntimeInterface.h" #include "../../lib/typelib/TypeDatabase.h" #include "TypeInterface.h" diff --git a/test/runtime/49_default_types_udef.c b/test/runtime/49_default_types_udef.c index 712cab21..cd35a0e0 100644 --- a/test/runtime/49_default_types_udef.c +++ b/test/runtime/49_default_types_udef.c @@ -1,3 +1,4 @@ +// RUN: export TYPEART_TYPE_SERIALIZATION=file // RUN: %run %s --clean_types 2>&1 | %filecheck %s struct Datastruct { diff --git a/test/runtime_inlined_types/01_simple_malloc_int.c b/test/runtime_inlined_types/01_simple_malloc_int.c new file mode 100644 index 00000000..913e281e --- /dev/null +++ b/test/runtime_inlined_types/01_simple_malloc_int.c @@ -0,0 +1,17 @@ +// clang-format off +// RUN: export TYPEART_TYPE_SERIALIZATION=inline +// RUN: %wrapper-cc -O1 %s -o %s.exe +// RUN: %s.exe 2>&1 | %filecheck %s + +// REQUIRES: llvm-18 || llvm-19 +// clang-format on + +#include +int main(void) { + int* p = (int*)malloc(42 * sizeof(int)); + free(p); + return 0; +} + +// CHECK: Allocation type detail (heap, stack, global) +// CHECK-NEXT: 13 : 1 , 0 , 0 , int \ No newline at end of file diff --git a/test/runtime_inlined_types/02_simple_malloc_int_multi_tu.c b/test/runtime_inlined_types/02_simple_malloc_int_multi_tu.c new file mode 100644 index 00000000..884df737 --- /dev/null +++ b/test/runtime_inlined_types/02_simple_malloc_int_multi_tu.c @@ -0,0 +1,32 @@ +// clang-format off +// RUN: export TYPEART_TYPE_SERIALIZATION=inline + +// : %cpp-to-llvm -DTYPEART_TU_ONE %s | %apply-typeart -typeart-instumentation=true -S > %s_1.ll +// : %cpp-to-llvm %s | %apply-typeart -typeart-instumentation=true -S > %s.ll + +// RUN: %wrapper-cc -c -O1 %s -DTYPEART_TU_ONE -o %s_1.o +// RUN: %wrapper-cc -c -O1 %s -o %s.o +// RUN: %wrapper-cc -O1 %s.o %s_1.o -o %s.exe +// RUN: %s.exe 2>&1 | %filecheck %s + +// REQUIRES: llvm-18 || llvm-19 +// clang-format on + +#include +#ifdef TYPEART_TU_ONE +void allocate() { + int* p = (int*)malloc(33 * sizeof(int)); + free(p); +} +#else +void allocate(); +int main(void) { + allocate(); + int* p = (int*)malloc(42 * sizeof(int)); + free(p); + return 0; +} +#endif + +// CHECK: Allocation type detail (heap, stack, global) +// CHECK-NEXT: 13 : 2 , 0 , 0 , int \ No newline at end of file diff --git a/test/runtime_inlined_types/03_simple_malloc_struct.c b/test/runtime_inlined_types/03_simple_malloc_struct.c new file mode 100644 index 00000000..112b8a78 --- /dev/null +++ b/test/runtime_inlined_types/03_simple_malloc_struct.c @@ -0,0 +1,24 @@ +// clang-format off +// RUN: export TYPEART_TYPE_SERIALIZATION=inline +// RUN: %wrapper-cc -O1 %s -o %s.exe +// RUN: %s.exe 2>&1 | %filecheck %s + +// REQUIRES: llvm-18 || llvm-19 +// clang-format on + +#include + +struct DataHolder { + double a; + float b; + int c; +}; + +int main(void) { + struct DataHolder* p = (struct DataHolder*)malloc(2 * sizeof(struct DataHolder)); + free(p); + return 0; +} + +// CHECK: Allocation type detail (heap, stack, global) +// CHECK-NEXT: 256 : 1 , 0 , 0 , DataHolder diff --git a/test/runtime_inlined_types/04_malloc_struct.c b/test/runtime_inlined_types/04_malloc_struct.c new file mode 100644 index 00000000..836560c1 --- /dev/null +++ b/test/runtime_inlined_types/04_malloc_struct.c @@ -0,0 +1,29 @@ +// clang-format off +// RUN: export TYPEART_TYPE_SERIALIZATION=inline +// RUN: %wrapper-cc -O1 %s -o %s.exe +// RUN: %s.exe 2>&1 | %filecheck %s + +// REQUIRES: llvm-18 || llvm-19 +// clang-format on + +#include + +struct DataNested { + struct DataNested* nested_pointer; +}; + +struct DataHolder { + double a; + float b; + int c; + struct DataNested nested; +}; + +int main(void) { + struct DataHolder* p = (struct DataHolder*)malloc(2 * sizeof(struct DataHolder)); + free(p); + return 0; +} + +// CHECK: Allocation type detail (heap, stack, global) +// CHECK-NEXT: 256 : 1 , 0 , 0 , DataHolder diff --git a/test/script/07_wrapper_demo.sh b/test/script/07_wrapper_demo.sh index ba0c09fd..70ea98de 100755 --- a/test/script/07_wrapper_demo.sh +++ b/test/script/07_wrapper_demo.sh @@ -4,8 +4,6 @@ # RUN: %s %t %S %wrapper-mpicc run-demo | %filecheck %s --check-prefix check-working # RUN: %s %t %S %wrapper-mpicc run-demo_broken | %filecheck %s --check-prefix check-broken -# RUN: %s %t %S %wrapper-mpicc runtoy | %filecheck %s --check-prefix check-toy - # REQUIRES: mpicc # UNSUPPORTED: sanitizer @@ -23,8 +21,6 @@ cd "$1" || exit 1 make clean MPICC="$3" make "$4" -exit 0 - # make sure "target" worked: if [ $? -gt 0 ]; then clean_up "$1" diff --git a/test/script/12_ir_viewer.sh b/test/script/12_ir_viewer.sh index d38fbfb2..37a9601d 100755 --- a/test/script/12_ir_viewer.sh +++ b/test/script/12_ir_viewer.sh @@ -30,21 +30,21 @@ exists 12_ir_viewer_target_stack.ll # CHECK: 1 # CHECK: 1 # CHECK: 1 -# CHECK: 1 +# : 1 exists 12_ir_viewer_target_base.ll exists 12_ir_viewer_target_heap.ll exists 12_ir_viewer_target_opt.ll exists 12_ir_viewer_target_stack.ll -exists 12_ir_viewer_target-types-ir-viewer.yaml +#exists 12_ir_viewer_target-types-ir-viewer.yaml "$python_interp" $1 -c 12_ir_viewer_target.c # CHECK: 0 # CHECK: 0 # CHECK: 0 # CHECK: 0 -# CHECK: 0 +# : 0 exists 12_ir_viewer_target_base.ll exists 12_ir_viewer_target_heap.ll exists 12_ir_viewer_target_opt.ll exists 12_ir_viewer_target_stack.ll -exists 12_ir_viewer_target-types-ir-viewer.yaml +#exists 12_ir_viewer_target-types-ir-viewer.yaml diff --git a/test/typemapping/01_simple_struct.c b/test/typemapping/01_simple_struct.c index e1c974b5..142932e8 100644 --- a/test/typemapping/01_simple_struct.c +++ b/test/typemapping/01_simple_struct.c @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %c-to-llvm %s | %apply-typeart +// RUN: %c-to-llvm %s | %apply-typeart --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // Note: This test assumes standard alignment on a 64bit system. Non-standard alignment may lead to failure. diff --git a/test/typemapping/02_recursive_struct.c b/test/typemapping/02_recursive_struct.c index 7bc6c430..39c60ac0 100644 --- a/test/typemapping/02_recursive_struct.c +++ b/test/typemapping/02_recursive_struct.c @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %c-to-llvm %s | %apply-typeart +// RUN: %c-to-llvm %s | %apply-typeart --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // Note: This test assumes standard alignment on a 64bit system. Non-standard alignment may lead to failure. diff --git a/test/typemapping/04_milc_mock.c b/test/typemapping/04_milc_mock.c index 9c1c1f46..6cc7b69a 100644 --- a/test/typemapping/04_milc_mock.c +++ b/test/typemapping/04_milc_mock.c @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %c-to-llvm %s | %apply-typeart +// RUN: %c-to-llvm %s | %apply-typeart --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s #include diff --git a/test/typemapping/06_anon_struct.c b/test/typemapping/06_anon_struct.c index 9dcdbd4e..e4bd1ed9 100644 --- a/test/typemapping/06_anon_struct.c +++ b/test/typemapping/06_anon_struct.c @@ -1,4 +1,4 @@ -// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // REQUIRES: dimeta diff --git a/test/typemapping/07_no_ebo_heap_multi_inheritance.cpp b/test/typemapping/07_no_ebo_heap_multi_inheritance.cpp index f1f7e8bf..30be6006 100644 --- a/test/typemapping/07_no_ebo_heap_multi_inheritance.cpp +++ b/test/typemapping/07_no_ebo_heap_multi_inheritance.cpp @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s struct Base { diff --git a/test/typemapping/08_ebo_only_heap_multi_inheritance.cpp b/test/typemapping/08_ebo_only_heap_multi_inheritance.cpp index 9c9e8cea..5b434580 100644 --- a/test/typemapping/08_ebo_only_heap_multi_inheritance.cpp +++ b/test/typemapping/08_ebo_only_heap_multi_inheritance.cpp @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s struct Base { diff --git a/test/typemapping/09_stack_class_inheritance_virtual.cpp b/test/typemapping/09_stack_class_inheritance_virtual.cpp index 4b0009c4..90ca8ffa 100644 --- a/test/typemapping/09_stack_class_inheritance_virtual.cpp +++ b/test/typemapping/09_stack_class_inheritance_virtual.cpp @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // REQUIRES: dimeta diff --git a/test/typemapping/10_multi_inheritance_virtual.cpp b/test/typemapping/10_multi_inheritance_virtual.cpp index 1a303dac..057006dd 100644 --- a/test/typemapping/10_multi_inheritance_virtual.cpp +++ b/test/typemapping/10_multi_inheritance_virtual.cpp @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // REQUIRES: dimeta @@ -8,7 +8,7 @@ class Base { public: double x; - virtual void foo(){}; + virtual void foo() {}; }; class X { diff --git a/test/typemapping/11_void_nullptr.cpp b/test/typemapping/11_void_nullptr.cpp index 1e3d6f30..3e1fbfc4 100644 --- a/test/typemapping/11_void_nullptr.cpp +++ b/test/typemapping/11_void_nullptr.cpp @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // REQUIRES: dimeta diff --git a/test/typemapping/12_complex.cpp b/test/typemapping/12_complex.cpp index a3c93951..23118f36 100644 --- a/test/typemapping/12_complex.cpp +++ b/test/typemapping/12_complex.cpp @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %cpp-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // REQUIRES: dimeta diff --git a/test/typemapping/13_complex.c b/test/typemapping/13_complex.c index 532bbd52..9e5f5416 100644 --- a/test/typemapping/13_complex.c +++ b/test/typemapping/13_complex.c @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // REQUIRES: llvm-18 || llvm-19 diff --git a/test/typemapping/14_union.c b/test/typemapping/14_union.c index 4deb27de..e496b431 100644 --- a/test/typemapping/14_union.c +++ b/test/typemapping/14_union.c @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // REQUIRES: llvm-18 || llvm-19 diff --git a/test/typemapping/15_wchar.c b/test/typemapping/15_wchar.c index 4ee69b72..75ac4682 100644 --- a/test/typemapping/15_wchar.c +++ b/test/typemapping/15_wchar.c @@ -1,5 +1,5 @@ // RUN: %remove %tu_yaml -// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true +// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s // REQUIRES: llvm-18 || llvm-19 diff --git a/test/typemapping/16_mpi_dtype.c b/test/typemapping/16_mpi_dtype.c new file mode 100644 index 00000000..182da9d0 --- /dev/null +++ b/test/typemapping/16_mpi_dtype.c @@ -0,0 +1,24 @@ +// clang-format off +// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true -S | %filecheck %s +// RUN: %c-to-llvm %s | %apply-typeart --typeart-type-serialization=inline --typeart-stack=true -S | %filecheck %s --check-prefix inline +// RUN: %c-to-llvm %s | %apply-typeart --typeart-type-serialization=hybrid --typeart-stack=true -S | %filecheck %s --check-prefix hybrid + +// REQUIRES: llvm-18 || llvm-19 +// clang-format on +struct ompi_struct_data; +typedef struct ompi_struct_data* MPI_Datatype; + +extern MPI_Datatype MPI_DOUBLE; +extern MPI_Datatype MPI_INT; + +int main(void) { + MPI_Datatype array_of_types[3] = {MPI_DOUBLE, MPI_DOUBLE, MPI_INT}; + + return 0; +} + +// CHECK-NOT: Error +// CHECK: call {{.*}} @__typeart_alloc_stack(ptr {{.*}}, i32 1, i64 3) +// inline: @_typeart_ptr = weak_odr global %struct._typeart_struct_layout_t +// inline: call {{.*}} @__typeart_alloc_stack_mty(ptr {{.*}}, ptr {{.*}}, i64 3) +// hybrid: call {{.*}} @__typeart_alloc_stack(ptr {{.*}}, i32 1, i64 3) From 340bcf6fa8db7a00fc8320614a3dc5a8b1d44d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sat, 22 Nov 2025 20:34:17 +0100 Subject: [PATCH 02/14] Updates for LLVM 21 (#175) --- .github/workflows/basic-ci.yml | 53 +++---- .github/workflows/ext-ci.yml | 135 ++++++++---------- externals/dimeta/CMakeLists.txt | 2 +- lib/passes/TypeARTPass.cpp | 85 ++++++----- lib/passes/instrumentation/TransformUtil.h | 8 +- .../instrumentation/TypeARTFunctions.cpp | 2 + test/runtime/27_omp_softcounter.c | 2 +- 7 files changed, 143 insertions(+), 144 deletions(-) diff --git a/.github/workflows/basic-ci.yml b/.github/workflows/basic-ci.yml index 39044e6b..237686dc 100644 --- a/.github/workflows/basic-ci.yml +++ b/.github/workflows/basic-ci.yml @@ -48,15 +48,12 @@ jobs: steps: - uses: actions/checkout@v5 - - uses: codespell-project/actions-codespell@v2 + - uses: codespell-project/actions-codespell@v2.2 lit-suite: strategy: fail-fast: false matrix: - os: [ ubuntu-22.04, ubuntu-24.04 ] - llvm-version: [ 14, 18, 19 ] - typeart-typegen-legacy: [ 0, 1 ] preset: - name: ci-thread-safe-safeptr - name: ci-thread-safe @@ -70,44 +67,40 @@ jobs: - name: ci-libcxx libcxx: true skip_test: true - exclude: - - llvm-version: 14 - os: ubuntu-24.04 - - llvm-version: 18 - os: ubuntu-22.04 - - llvm-version: 18 - typeart-typegen-legacy: 1 - - llvm-version: 19 - os: ubuntu-22.04 - - llvm-version: 19 - typeart-typegen-legacy: 1 - - runs-on: ${{ matrix.os }} + platform: + - { os: ubuntu-22.04, llvm-version: 14, typeart-typegen-legacy: 0 } + - { os: ubuntu-22.04, llvm-version: 14, typeart-typegen-legacy: 1 } + - { os: ubuntu-24.04, llvm-version: 18, typeart-typegen-legacy: 0 } + - { os: ubuntu-24.04, llvm-version: 19, typeart-typegen-legacy: 0 } + - { os: ubuntu-24.04, llvm-version: 20, typeart-typegen-legacy: 0 } + - { os: ubuntu-24.04, llvm-version: 21, typeart-typegen-legacy: 0 } + + runs-on: ${{ matrix.platform.os }} steps: - uses: actions/checkout@v5 - name: LLVM apt - if: ${{ matrix.llvm-version == 19 }} + if: ${{ matrix.platform.llvm-version >= 19 }} run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" | sudo tee /etc/apt/sources.list.d/llvm-19.list + echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-${{ matrix.platform.llvm-version }} main" | sudo tee /etc/apt/sources.list.d/llvm-${{ matrix.platform.llvm-version }}.list - name: Update apt run: sudo apt-get update - name: Install LLVM - run: sudo apt-get install libllvm${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }}-dev + run: sudo apt-get install libllvm${{ matrix.platform.llvm-version }} llvm-${{ matrix.platform.llvm-version }} llvm-${{ matrix.platform.llvm-version }}-dev - name: Install LLVM OpenMP runtime - run: sudo apt-get install libomp-${{ matrix.llvm-version }}-dev libomp5-${{ matrix.llvm-version }} + run: sudo apt-get install libomp-${{ matrix.platform.llvm-version }}-dev - name: Install Clang - run: sudo apt-get install clang-${{ matrix.llvm-version }} clang-tidy-${{ matrix.llvm-version }} + run: sudo apt-get install clang-${{ matrix.platform.llvm-version }} clang-tidy-${{ matrix.platform.llvm-version }} - name: Install libc++ if: matrix.preset.libcxx - run: sudo apt-get install --no-install-recommends libc++-${{ matrix.llvm-version }}-dev libc++abi-${{ matrix.llvm-version }}-dev + run: sudo apt-get install --no-install-recommends libc++-${{ matrix.platform.llvm-version }}-dev libc++abi-${{ matrix.platform.llvm-version }}-dev - name: Install OpenMPI run: sudo apt-get install libopenmpi-dev openmpi-bin @@ -118,11 +111,11 @@ jobs: - name: Setup env run: | - sudo ln -f -s /usr/bin/clang-${{ matrix.llvm-version }} /usr/bin/clang - sudo ln -f -s /usr/bin/clang++-${{ matrix.llvm-version }} /usr/bin/clang++ - echo "LLVM_CMAKE_DIR=/usr/lib/llvm-${{ matrix.llvm-version }}/cmake" >> $GITHUB_ENV - echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV - echo "TYPEART_TYPEGEN_IR=${{ matrix.typeart-typegen-legacy }}" >> $GITHUB_ENV + sudo ln -f -s /usr/bin/clang-${{ matrix.platform.llvm-version }} /usr/bin/clang + sudo ln -f -s /usr/bin/clang++-${{ matrix.platform.llvm-version }} /usr/bin/clang++ + echo "LLVM_CMAKE_DIR=/usr/lib/llvm-${{ matrix.platform.llvm-version }}/cmake" >> $GITHUB_ENV + echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.platform.llvm-version >= 20 && 18 || matrix.platform.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV + echo "TYPEART_TYPEGEN_IR=${{ matrix.platform.typeart-typegen-legacy }}" >> $GITHUB_ENV - name: Configure TypeART run: cmake -B build --preset ${{ matrix.preset.name }} -DLLVM_DIR=${LLVM_CMAKE_DIR} -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT} @@ -148,7 +141,7 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} path-to-lcov: build/typeart.coverage - flag-name: ${{ matrix.preset.name }}-${{ matrix.llvm-version }}-${{ matrix.typeart-typegen-legacy }} + flag-name: ${{ matrix.preset.name }}-${{ matrix.platform.llvm-version }}-${{ matrix.platform.typeart-typegen-legacy }} parallel: true finish-coverage: @@ -159,4 +152,4 @@ jobs: uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} - parallel-finished: true + parallel-finished: true \ No newline at end of file diff --git a/.github/workflows/ext-ci.yml b/.github/workflows/ext-ci.yml index dffa84f1..45e37ea5 100644 --- a/.github/workflows/ext-ci.yml +++ b/.github/workflows/ext-ci.yml @@ -14,21 +14,18 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-22.04, ubuntu-24.04 ] - llvm-version: [ 14, 18, 19 ] preset: - name: release-counter - name: release-safeptr-counter - name: release-unsafe-counter - exclude: - - llvm-version: 14 - os: ubuntu-24.04 - - llvm-version: 18 - os: ubuntu-22.04 - - llvm-version: 19 - os: ubuntu-22.04 + platform: + - { os: ubuntu-22.04, llvm-version: 14 } + - { os: ubuntu-24.04, llvm-version: 18 } + - { os: ubuntu-24.04, llvm-version: 19 } + - { os: ubuntu-24.04, llvm-version: 20 } + - { os: ubuntu-24.04, llvm-version: 21 } - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.platform.os }} steps: - uses: actions/checkout@v5 @@ -41,29 +38,29 @@ jobs: path: test-bench - name: LLVM apt - if: ${{ matrix.llvm-version == 19 }} + if: ${{ matrix.platform.llvm-version >= 19 }} run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" | sudo tee /etc/apt/sources.list.d/llvm-19.list + echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-${{ matrix.platform.llvm-version }} main" | sudo tee /etc/apt/sources.list.d/llvm-${{ matrix.platform.llvm-version }}.list - name: Update apt run: sudo apt-get update - name: Install LLVM - run: sudo apt-get install libllvm${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }}-dev + run: sudo apt-get install libllvm${{ matrix.platform.llvm-version }} llvm-${{ matrix.platform.llvm-version }} llvm-${{ matrix.platform.llvm-version }}-dev - name: Install Clang - run: sudo apt-get install clang-${{ matrix.llvm-version }} clang-tidy-${{ matrix.llvm-version }} + run: sudo apt-get install clang-${{ matrix.platform.llvm-version }} clang-tidy-${{ matrix.platform.llvm-version }} - name: Install OpenMPI run: sudo apt-get install libopenmpi-dev openmpi-bin - name: Setup env run: | - sudo ln -f -s /usr/bin/clang-${{ matrix.llvm-version }} /usr/bin/clang - sudo ln -f -s /usr/bin/clang++-${{ matrix.llvm-version }} /usr/bin/clang++ - echo "LLVM_CMAKE_DIR=/usr/lib/llvm-${{ matrix.llvm-version }}/cmake" >> $GITHUB_ENV - echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV + sudo ln -f -s /usr/bin/clang-${{ matrix.platform.llvm-version }} /usr/bin/clang + sudo ln -f -s /usr/bin/clang++-${{ matrix.platform.llvm-version }} /usr/bin/clang++ + echo "LLVM_CMAKE_DIR=/usr/lib/llvm-${{ matrix.platform.llvm-version }}/cmake" >> $GITHUB_ENV + echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.platform.llvm-version >= 20 && 18 || matrix.platform.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV - name: Configure TypeART run: cmake -B build --preset ${{ matrix.preset.name }} -DLLVM_DIR=${LLVM_CMAKE_DIR} -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT} @@ -75,58 +72,55 @@ jobs: - name: Setup tests working-directory: test-bench - run: cmake -B build -DLOG_PATH=${GITHUB_WORKSPACE}/test-bench/artifact-${{ matrix.llvm-version }} -DUSE_WRAPPER=ON + run: cmake -B build -DLOG_PATH=${GITHUB_WORKSPACE}/test-bench/artifact-${{ matrix.platform.llvm-version }} -DUSE_WRAPPER=ON - name: Run lulesh working-directory: test-bench/build - run: ctest -V -R lulesh -O lulesh2.0_${{ matrix.llvm-version }}_build.log + run: ctest -V -R lulesh -O lulesh2.0_${{ matrix.platform.llvm-version }}_build.log - name: Run 104.milc working-directory: test-bench/build - run: ctest -V -R 104.milc -O 104.milc_${{ matrix.llvm-version }}_build.log + run: ctest -V -R 104.milc -O 104.milc_${{ matrix.platform.llvm-version }}_build.log - name: Run 122.tachyon working-directory: test-bench/build - run: ctest -V -R 122.tachyon -O 122.tachyon_${{ matrix.llvm-version }}_build.log + run: ctest -V -R 122.tachyon -O 122.tachyon_${{ matrix.platform.llvm-version }}_build.log - name: Run amg2013 working-directory: test-bench/build - run: ctest -V -R amg2013 -O amg2013_${{ matrix.llvm-version }}_build.log + run: ctest -V -R amg2013 -O amg2013_${{ matrix.platform.llvm-version }}_build.log - name: Run tealeaf working-directory: test-bench/build - run: ctest -V -R tealeaf -O tealeaf_${{ matrix.llvm-version }}_build.log + run: ctest -V -R tealeaf -O tealeaf_${{ matrix.platform.llvm-version }}_build.log - name: Prepare artifact run: | mkdir -p artifact mv test-bench/build/*_build.log artifact - mv test-bench/artifact-${{ matrix.llvm-version }}/* artifact + mv test-bench/artifact-${{ matrix.platform.llvm-version }}/* artifact - name: Upload test-bench artifact uses: actions/upload-artifact@v4 with: - name: typeart-ci-ext-${{ matrix.llvm-version }}-${{ matrix.preset.name }} + name: typeart-ci-ext-${{ matrix.platform.llvm-version }}-${{ matrix.preset.name }} path: artifact run-AD-testbench: strategy: fail-fast: false matrix: - os: [ ubuntu-22.04, ubuntu-24.04 ] - llvm-version: [ 14, 18, 19 ] preset: - name: release-counter - name: release-unsafe-counter - exclude: - - llvm-version: 14 - os: ubuntu-24.04 - - llvm-version: 18 - os: ubuntu-22.04 - - llvm-version: 19 - os: ubuntu-22.04 + platform: + - { os: ubuntu-22.04, llvm-version: 14 } + - { os: ubuntu-24.04, llvm-version: 18 } + - { os: ubuntu-24.04, llvm-version: 19 } + - { os: ubuntu-24.04, llvm-version: 20 } + - { os: ubuntu-24.04, llvm-version: 21 } - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.platform.os }} steps: - uses: actions/checkout@v5 @@ -140,29 +134,29 @@ jobs: path: ad-test-bench - name: LLVM apt - if: ${{ matrix.llvm-version == 19 }} + if: ${{ matrix.platform.llvm-version >= 19 }} run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" | sudo tee /etc/apt/sources.list.d/llvm-19.list + echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-${{ matrix.platform.llvm-version }} main" | sudo tee /etc/apt/sources.list.d/llvm-${{ matrix.platform.llvm-version }}.list - name: Update apt run: sudo apt-get update - name: Install LLVM - run: sudo apt-get install libllvm${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }}-dev + run: sudo apt-get install libllvm${{ matrix.platform.llvm-version }} llvm-${{ matrix.platform.llvm-version }} llvm-${{ matrix.platform.llvm-version }}-dev - name: Install Clang - run: sudo apt-get install clang-${{ matrix.llvm-version }} clang-tidy-${{ matrix.llvm-version }} + run: sudo apt-get install clang-${{ matrix.platform.llvm-version }} clang-tidy-${{ matrix.platform.llvm-version }} - name: Install OpenMPI run: sudo apt-get install libopenmpi-dev openmpi-bin - name: Setup env run: | - sudo ln -f -s /usr/bin/clang-${{ matrix.llvm-version }} /usr/bin/clang - sudo ln -f -s /usr/bin/clang++-${{ matrix.llvm-version }} /usr/bin/clang++ - echo "LLVM_CMAKE_DIR=/usr/lib/llvm-${{ matrix.llvm-version }}/cmake" >> $GITHUB_ENV - echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV + sudo ln -f -s /usr/bin/clang-${{ matrix.platform.llvm-version }} /usr/bin/clang + sudo ln -f -s /usr/bin/clang++-${{ matrix.platform.llvm-version }} /usr/bin/clang++ + echo "LLVM_CMAKE_DIR=/usr/lib/llvm-${{ matrix.platform.llvm-version }}/cmake" >> $GITHUB_ENV + echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.platform.llvm-version >= 20 && 18 || matrix.platform.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV - name: Configure TypeART run: cmake -B build --preset ${{ matrix.preset.name }} -DLLVM_DIR=${LLVM_CMAKE_DIR} -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT} @@ -174,22 +168,22 @@ jobs: - name: Setup AD tests working-directory: ad-test-bench - run: cmake -B build -DLOG_PATH=${GITHUB_WORKSPACE}/ad-test-bench/artifact-${{ matrix.llvm-version }} -DUSE_WRAPPER=ON + run: cmake -B build -DLOG_PATH=${GITHUB_WORKSPACE}/ad-test-bench/artifact-${{ matrix.platform.llvm-version }} -DUSE_WRAPPER=ON - name: Run AD lulesh working-directory: ad-test-bench/build - run: ctest -V -R lulesh -O ad-lulesh2.0_${{ matrix.llvm-version }}_build.log + run: ctest -V -R lulesh -O ad-lulesh2.0_${{ matrix.platform.llvm-version }}_build.log - name: Prepare artifact run: | mkdir -p artifact mv ad-test-bench/build/*_build.log artifact - mv ad-test-bench/artifact-${{ matrix.llvm-version }}/* artifact + mv ad-test-bench/artifact-${{ matrix.platform.llvm-version }}/* artifact - name: Upload AD test-bench artifact uses: actions/upload-artifact@v4 with: - name: typeart-ci-ext-ad-${{ matrix.llvm-version }}-${{ matrix.preset.name }} + name: typeart-ci-ext-ad-${{ matrix.platform.llvm-version }}-${{ matrix.preset.name }} path: artifact run-OMP-testbench: @@ -199,20 +193,17 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-22.04, ubuntu-24.04 ] - llvm-version: [ 14, 18, 19 ] preset: - name: release-counter - name: release-safeptr-counter - exclude: - - llvm-version: 14 - os: ubuntu-24.04 - - llvm-version: 18 - os: ubuntu-22.04 - - llvm-version: 19 - os: ubuntu-22.04 + platform: + - { os: ubuntu-22.04, llvm-version: 14 } + - { os: ubuntu-24.04, llvm-version: 18 } + - { os: ubuntu-24.04, llvm-version: 19 } + - { os: ubuntu-24.04, llvm-version: 20 } + - { os: ubuntu-24.04, llvm-version: 21 } - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.platform.os }} steps: - uses: actions/checkout@v5 @@ -226,32 +217,32 @@ jobs: path: omp-test-bench - name: LLVM apt - if: ${{ matrix.llvm-version == 19 }} + if: ${{ matrix.platform.llvm-version >= 19 }} run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" | sudo tee /etc/apt/sources.list.d/llvm-19.list + echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-${{ matrix.platform.llvm-version }} main" | sudo tee /etc/apt/sources.list.d/llvm-${{ matrix.platform.llvm-version }}.list - name: Update apt run: sudo apt-get update - name: Install LLVM - run: sudo apt-get install libllvm${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }}-dev + run: sudo apt-get install libllvm${{ matrix.platform.llvm-version }} llvm-${{ matrix.platform.llvm-version }} llvm-${{ matrix.platform.llvm-version }}-dev - name: Install Clang - run: sudo apt-get install clang-${{ matrix.llvm-version }} clang-tidy-${{ matrix.llvm-version }} + run: sudo apt-get install clang-${{ matrix.platform.llvm-version }} clang-tidy-${{ matrix.platform.llvm-version }} - name: Install OpenMPI run: sudo apt-get install libopenmpi-dev openmpi-bin - name: Install LLVM OpenMP runtime - run: sudo apt-get install libomp-${{ matrix.llvm-version }}-dev libomp5-${{ matrix.llvm-version }} + run: sudo apt-get install libomp-${{ matrix.platform.llvm-version }}-dev - name: Setup env run: | - sudo ln -f -s /usr/bin/clang-${{ matrix.llvm-version }} /usr/bin/clang - sudo ln -f -s /usr/bin/clang++-${{ matrix.llvm-version }} /usr/bin/clang++ - echo "LLVM_CMAKE_DIR=/usr/lib/llvm-${{ matrix.llvm-version }}/cmake" >> $GITHUB_ENV - echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV + sudo ln -f -s /usr/bin/clang-${{ matrix.platform.llvm-version }} /usr/bin/clang + sudo ln -f -s /usr/bin/clang++-${{ matrix.platform.llvm-version }} /usr/bin/clang++ + echo "LLVM_CMAKE_DIR=/usr/lib/llvm-${{ matrix.platform.llvm-version }}/cmake" >> $GITHUB_ENV + echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.platform.llvm-version >= 20 && 18 || matrix.platform.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV - name: Configure TypeART run: cmake -B build --preset ${{ matrix.preset.name }} -DLLVM_DIR=${LLVM_CMAKE_DIR} -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT} @@ -263,24 +254,24 @@ jobs: - name: Setup tests working-directory: omp-test-bench - run: cmake -B build -DLOG_PATH=${GITHUB_WORKSPACE}/omp-test-bench/artifact-${{ matrix.llvm-version }} -DUSE_WRAPPER=ON + run: cmake -B build -DLOG_PATH=${GITHUB_WORKSPACE}/omp-test-bench/artifact-${{ matrix.platform.llvm-version }} -DUSE_WRAPPER=ON - name: Run lulesh working-directory: omp-test-bench/build - run: ctest -V -R lulesh -O lulesh2.0_${{ matrix.llvm-version }}_build.log + run: ctest -V -R lulesh -O lulesh2.0_${{ matrix.platform.llvm-version }}_build.log - name: Run amg2013 working-directory: omp-test-bench/build - run: ctest -V -R amg2013 -O amg2013_${{ matrix.llvm-version }}_build.log + run: ctest -V -R amg2013 -O amg2013_${{ matrix.platform.llvm-version }}_build.log - name: Prepare artifact run: | mkdir -p artifact mv omp-test-bench/build/*_build.log artifact - mv omp-test-bench/artifact-${{ matrix.llvm-version }}/* artifact + mv omp-test-bench/artifact-${{ matrix.platform.llvm-version }}/* artifact - name: Upload omp-test-bench artifact uses: actions/upload-artifact@v4 with: - name: typeart-ci-ext-omp-${{ matrix.llvm-version }}-${{ matrix.preset.name }} + name: typeart-ci-ext-omp-${{ matrix.platform.llvm-version }}-${{ matrix.preset.name }} path: artifact diff --git a/externals/dimeta/CMakeLists.txt b/externals/dimeta/CMakeLists.txt index faa68f6a..6dcdf0bd 100644 --- a/externals/dimeta/CMakeLists.txt +++ b/externals/dimeta/CMakeLists.txt @@ -1,7 +1,7 @@ FetchContent_Declare( llvm-dimeta GIT_REPOSITORY https://github.com/ahueck/llvm-dimeta - GIT_TAG v0.3.0 + GIT_TAG v0.4.0 GIT_SHALLOW 1 ) diff --git a/lib/passes/TypeARTPass.cpp b/lib/passes/TypeARTPass.cpp index eed4416e..b8cc68d2 100644 --- a/lib/passes/TypeARTPass.cpp +++ b/lib/passes/TypeARTPass.cpp @@ -306,8 +306,12 @@ class TypeArtPass : public llvm::PassInfoMixin { // declareInstrumentationFunctions(*f.getParent()); bool mod{false}; - // auto& c = f.getContext(); +// auto& c = f.getContext(); +#if LLVM_VERSION_MAJOR > 19 + DataLayout dl(f.getParent()->getDataLayout()); +#else DataLayout dl(f.getParent()); +#endif const auto& fData = meminst_finder->getFunctionData(f); const auto& mallocs = fData.mallocs; @@ -378,43 +382,48 @@ bool LegacyTypeArtPass::doFinalization(llvm::Module&) { //..................... llvm::PassPluginLibraryInfo getTypeartPassPluginInfo() { using namespace llvm; - return {LLVM_PLUGIN_API_VERSION, "TypeART", LLVM_VERSION_STRING, [](PassBuilder& pass_builder) { - pass_builder.registerPipelineStartEPCallback([](auto& MPM, OptimizationLevel) { - auto parameters = - typeart::util::pass::parsePassParameters(typeart::config::pass::parse_typeart_config, - "typeart", "typeart"); - if (!parameters) { - LOG_FATAL("Error parsing heap params: " << parameters.takeError()) - return; - } - MPM.addPass(typeart::pass::TypeArtPass(typeart::pass::TypeArtPass(parameters.get()))); - }); - pass_builder.registerOptimizerLastEPCallback([](auto& MPM, OptimizationLevel) { - auto parameters = typeart::util::pass::parsePassParameters( - typeart::config::pass::parse_typeart_config, "typeart", - "typeart"); - if (!parameters) { - LOG_FATAL("Error parsing stack params: " << parameters.takeError()) - return; - } - MPM.addPass(typeart::pass::TypeArtPass(typeart::pass::TypeArtPass(parameters.get()))); - }); - pass_builder.registerPipelineParsingCallback( - [](StringRef name, ModulePassManager& module_pm, ArrayRef) { - if (typeart::util::pass::checkParametrizedPassName(name, "typeart")) { - auto parameters = typeart::util::pass::parsePassParameters( - typeart::config::pass::parse_typeart_config, name, "typeart"); - if (!parameters) { - LOG_FATAL("Error parsing params: " << parameters.takeError()) - return false; - } - module_pm.addPass(typeart::pass::TypeArtPass(parameters.get())); - return true; - } - LOG_FATAL("Not a valid parametrized pass name: " << name) - return false; - }); - }}; + return { + LLVM_PLUGIN_API_VERSION, "TypeART", LLVM_VERSION_STRING, [](PassBuilder& pass_builder) { + pass_builder.registerPipelineStartEPCallback([](auto& MPM, OptimizationLevel) { + auto parameters = typeart::util::pass::parsePassParameters( + typeart::config::pass::parse_typeart_config, "typeart", "typeart"); + if (!parameters) { + LOG_FATAL("Error parsing heap params: " << parameters.takeError()) + return; + } + MPM.addPass(typeart::pass::TypeArtPass(typeart::pass::TypeArtPass(parameters.get()))); + }); +#if LLVM_VERSION_MAJOR > 19 + pass_builder.registerOptimizerLastEPCallback([](auto& MPM, OptimizationLevel, ThinOrFullLTOPhase) { +#else + pass_builder.registerOptimizerLastEPCallback([](auto& MPM, OptimizationLevel) { +#endif + auto parameters = typeart::util::pass::parsePassParameters( + typeart::config::pass::parse_typeart_config, "typeart", + "typeart"); + if (!parameters) { + LOG_FATAL("Error parsing stack params: " << parameters.takeError()) + return; + } + MPM.addPass(typeart::pass::TypeArtPass(typeart::pass::TypeArtPass(parameters.get()))); + }); + pass_builder.registerPipelineParsingCallback([](StringRef name, ModulePassManager& module_pm, + ArrayRef) { + if (typeart::util::pass::checkParametrizedPassName(name, "typeart")) { + auto parameters = + typeart::util::pass::parsePassParameters(typeart::config::pass::parse_typeart_config, name, "typeart"); + if (!parameters) { + LOG_FATAL("Error parsing params: " << parameters.takeError()) + return false; + } + module_pm.addPass(typeart::pass::TypeArtPass(parameters.get())); + return true; + } + LOG_FATAL("Not a valid parametrized pass name: " << name) + return false; + }); + } + }; } extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() { diff --git a/lib/passes/instrumentation/TransformUtil.h b/lib/passes/instrumentation/TransformUtil.h index 056e5927..b6d38ef3 100644 --- a/lib/passes/instrumentation/TransformUtil.h +++ b/lib/passes/instrumentation/TransformUtil.h @@ -36,9 +36,13 @@ struct StackCounter { void addStackHandling(StackOpCounter& allocCounts) const { using namespace llvm; - // LOG_DEBUG("Add alloca counter") - // counter = 0 at beginning of function +// LOG_DEBUG("Add alloca counter") +// counter = 0 at beginning of function +#if LLVM_VERSION_MAJOR > 19 + IRBuilder<> CBuilder(&target_function->getEntryBlock(), target_function->getEntryBlock().getFirstNonPHIIt()); +#else IRBuilder<> CBuilder(target_function->getEntryBlock().getFirstNonPHI()); +#endif auto* counter = CBuilder.CreateAlloca(instrumentation_helper->getTypeFor(IType::stack_count), nullptr, "__ta_alloca_counter"); CBuilder.CreateStore(instrumentation_helper->getConstantFor(IType::stack_count), counter); diff --git a/lib/passes/instrumentation/TypeARTFunctions.cpp b/lib/passes/instrumentation/TypeARTFunctions.cpp index 5ddfa462..2953957a 100644 --- a/lib/passes/instrumentation/TypeARTFunctions.cpp +++ b/lib/passes/instrumentation/TypeARTFunctions.cpp @@ -189,7 +189,9 @@ llvm::Function* TAFunctionDeclarator::make_function(IFunc func_id, llvm::StringR #endif for (Argument& arg : function->args()) { if (arg.getType()->isPointerTy()) { +#if LLVM_VERSION_MAJOR < 20 arg.addAttr(Attribute::NoCapture); +#endif arg.addAttr(Attribute::ReadOnly); arg.addAttr(Attribute::NoFree); } diff --git a/test/runtime/27_omp_softcounter.c b/test/runtime/27_omp_softcounter.c index b559198d..e2ffc1f1 100644 --- a/test/runtime/27_omp_softcounter.c +++ b/test/runtime/27_omp_softcounter.c @@ -4,7 +4,7 @@ // RUN: %run %s -o -O2 --omp --typeart-filter=true 2>&1 | %filecheck %s // RUN: %run %s --omp --typeart-filter=true 2>&1 | %filecheck %s -// REQUIRES: openmp && softcounter && !llvm-18 && !llvm-19 +// REQUIRES: openmp && softcounter && llvm-14 // clang-format on #include From 2351c3e6a41aec59ac8f8cd8f1ad752c748e1e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Tue, 25 Nov 2025 13:10:35 +0100 Subject: [PATCH 03/14] Release updates (#176) --- CMakeLists.txt | 2 +- README.md | 206 ++++++++++++++++------------- lib/runtime/RuntimeInterface.h | 2 +- lib/runtime/TypeResolution.cpp | 12 +- test/runtime/38_resolve_struct.c | 2 +- test/runtime/53_get_type.c | 4 +- test/runtime/54_get_type_illegal.c | 4 +- 7 files changed, 126 insertions(+), 106 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 392a35cd..09fc3856 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) project(typeart - VERSION 2.1 + VERSION 2.2 HOMEPAGE_URL https://github.com/tudasc/TypeART DESCRIPTION "LLVM-based type and memory allocation tracking sanitizer" ) diff --git a/README.md b/README.md index b76861fc..b15ae9d0 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,12 @@ ## What is TypeART? -TypeART \[[TA18](#ref-typeart-2018); [TA20](#ref-typeart-2020); [TA22](#ref-typeart-2022)\] is a type and memory -allocation tracking sanitizer based on the [LLVM](https://llvm.org) compiler toolchain for C/C++ (OpenMP) codes. It includes an LLVM compiler pass plugin for instrumentation and a runtime library to monitor memory allocations during program execution. +TypeART \[[TA18](#ref-typeart-2018); [TA20](#ref-typeart-2020); [TA22](#ref-typeart-2022); [TA24](#ref-typeart-2024)\] is a type and memory +allocation tracking sanitizer based on the [LLVM](https://llvm.org) compiler toolchain for C/C++ (OpenMP) codes. It pairs a compiler plugin (for instrumentation) with a runtime library to track memory type, size, and location of heap, stack and global allocations. -TypeART instruments heap, stack, and global variable allocations with callbacks to its runtime, capturing: -(1) the memory address, (2) the type-layout information of the allocation (e.g., built-ins, user-defined structs) and (3) number of elements. ## Why use it? -TypeART provides type-related information of allocations in your program to help verify some property, and to help -generate diagnostics if it doesn't hold. - Low-level C APIs often rely on `void*` pointers for generic types, requiring users to manually specify type and size - a process prone to errors. Examples for type unsafe APIs include the Message-Passing Interface (MPI), checkpointing libraries and numeric solver libraries. TypeART simplifies verification, ensuring, for example, that a `void*` argument corresponds to an array of expected type `T` with length `n`. @@ -62,28 +57,26 @@ its [project page](https://itc.rwth-aachen.de/must/). Using TypeART involves two phases: -1. Compilation: Compile your code with Clang/LLVM using the TypeART LLVM pass plugin. The plugin (1) serializes static type information to a file and (2) instruments relevant allocations. See [Section 1.1](#11-compiling-a-target-code). -2. Execution: Run the instrumented program with a TypeART runtime client, which uses the callback data to perform analysis facilitating the static type information. See [Section 1.2](#12-executing-an-instrumented-target-code). +1. Compilation, see [Section 1.1](#11-compiling-a-target-code): Compile your code with Clang/LLVM using the TypeART LLVM pass plugin. The plugin (1) serializes static type information and (2) instruments relevant allocations. +2. Execution, see [Section 1.2](#12-executing-an-instrumented-target-code): Run the instrumented program with a TypeART runtime client, which uses the callback data to perform analysis facilitating the static type information. -### 1.1 Compiling a target code -TypeART’s LLVM compiler pass plugins instrument allocations and serialize static type layouts into a YAML file (default: `typeart-types.yaml`). We provide compiler wrapper scripts (available in the bin folder of the TypeART installation) for Clang and MPI. By default, these wrappers instrument heap, stack, and global allocations, while MPI wrappers filter allocations unrelated to MPI calls (see [Section 1.1.4](#114-filtering-allocations)). +### 1.1 Compiling a target code -*Note*: Currently, the compilation must be serialized, e.g., `make -j 1`, to ensure consistent type information across translation units. +TypeART’s LLVM compiler pass plugins instrument allocations and serialize static type layouts. We provide compiler wrapper scripts (available in the bin folder of the TypeART installation) for Clang and MPI. By default, these wrappers instrument heap, stack, and global allocations, while MPI wrappers filter allocations unrelated to MPI calls (see [Section 1.1.4](#114-filtering-allocations)). #### 1.1.1 Building with TypeART -A typical compile invocation may first compile code to object files and then link with any libraries: +Simply replace your compiler variable: -```shell -# Compile: -$> clang++ -O2 $(COMPILE_FLAGS) -c code.cpp -o code.o -# Link: -$> clang++ $(LINK_FLAGS) code.o -o binary -``` +| Variable | TypeART Wrapper | +|----------|-------------------| +| `CXX` | `typeart-clang++` | +| `CC` | `typeart-clang` | +| `MPICC` | `typeart-mpicc` | +| `MPICXX` | `typeart-mpic++` | -With TypeART, the recipe needs to be changed to, e.g., use our provided compiler wrapper, as we rely on the LLVM `opt` -(optimizer) tool to load and apply our TypeART passes to a target code: +The wrappers handle the LLVM pass injection and linking: ```shell # Compile, replace direct clang++ call with wrapper of the TypeART installation: @@ -102,17 +95,15 @@ The wrapper performs the following steps using Clang's `-fpass-plugin`: *Note*: Heap allocations are instrumented before optimizations to prevent loss of type information in some cases. -##### Wrapper usage in CMake build systems +##### CMake projects -For plain Makefiles, the wrapper replaces the GCC/Clang compiler variables, e.g., `CC` or `MPICC`. For CMake, during the -configuration, it is advised to disable the wrapper temporarily. This is due to CMake executing internal compiler -checks, where we do not need TypeART instrumentation: +When using CMake, the wrapper must be disabled during configuration (to pass internal compiler checks) but enabled for the build. ```shell # Temporarily disable wrapper with environment flag TYPEART_WRAPPER=OFF for configuration: $> TYPEART_WRAPPER=OFF cmake -B build -DCMAKE_C_COMPILER=*TypeART bin*/typeart-clang # Compile with typeart-clang: -$> cmake --build build --target install -- -j1 +$> cmake --build build --target install ``` ##### MPI wrapper generation @@ -122,11 +113,11 @@ Here, we rely on detecting the vendor to generate wrappers with appropriate envi 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 | +| 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 | #### 1.1.2 Options for controlling the TypeART pass @@ -141,51 +132,75 @@ Prepending `no-` to boolean flags sets them to false. -| Env. variable | Option name | Default value | Description | -| :----------------------------------------- | ---------------------------------- | :------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `TYPEART_OPTIONS` | | | Set multiple options at once, separated by `;`. | -| `TYPEART_OPTIONS_STACK` | | | Same as above for stack phase only. | -| `TYPEART_OPTIONS_HEAP` | | | Same as above for heap phase only. | -| `TYPEART_TYPES` | `types` | `typeart-types.yaml` | Serialized type layout information of user-defined types. File location and name can also be controlled with the env variable `TYPEART_TYPES`. | -| `TYPEART_HEAP` | `heap` | `true` | Instrument heap allocations | -| `TYPEART_STACK` | `stack` | `false` | Instrument stack and global allocations. Enables instrumentation of global allocations. | -| `TYPEART_STACK_LIFETIME` | `stack-lifetime` | `true` | Instrument stack `llvm.lifetime.start` instead of `alloca` directly | -| `TYPEART_GLOBAL` | `global` | `false` | Instrument global allocations (see stack). | -| `TYPEART_TYPEGEN` | `typegen` | `dimeta` | Values: `dimeta`, `ir`. How serializing of type information is done, see [Section 1.1.3](#113-serialized-type-information). | -| `TYPEART_STATS` | `stats` | `false` | Show instrumentation statistic counters | -| `TYPEART_FILTER` | `filter` | `false` | Filter stack and global allocations. See also [Section 1.1.4](#114-filtering-allocations) | -| `TYPEART_FILTER_IMPLEMENTATION` | `filter-implementation` | `std` | Values: `std`, `none`. See also [Section 1.1.4](#114-filtering-allocations) | -| `TYPEART_FILTER_GLOB` | `filter-glob` | `*MPI_*` | Filter API string target (glob string) | -| `TYPEART_FILTER_GLOB_DEEP` | `filter-glob-deep` | `MPI_*` | Filter values based on specific API: Values passed as ptr are correlated when string matched. | -| `TYPEART_ANALYSIS_FILTER_GLOBAL` | `analysis-filter-global` | `true` | Filter global alloca based on heuristics | -| `TYPEART_ANALYSIS_FILTER_HEAP_ALLOCA` | `analysis-filter-heap-alloca` | `true` | Filter stack alloca that have a store instruction from a heap allocation | -| `TYPEART_ANALYSTS_FILTER_NON_ARRAY_ALLOCA` | `analysis-filter-non-array-alloca` | `false` | Filter scalar valued allocas | -| `TYPEART_ANALYSIS_FILTER_POINTER_ALLOCA` | `analysis-filter-pointer-alloca` | `true` | Filter allocas of pointer types | +| Env. variable | Option name | Default value | Description | +|:-------------------------------------------|------------------------------------|:--------------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `TYPEART_OPTIONS` | | | Set multiple options at once, separated by `;`. | +| `TYPEART_OPTIONS_STACK` | | | Same as above for stack phase only. | +| `TYPEART_OPTIONS_HEAP` | | | Same as above for heap phase only. | +| `TYPEART_TYPES` | `types` | `typeart-types.yaml` | Serialized type layout information of user-defined types. File location and name can also be controlled with the env variable `TYPEART_TYPES`. | +| `TYPEART_HEAP` | `heap` | `true` | Instrument heap allocations | +| `TYPEART_STACK` | `stack` | `false` | Instrument stack and global allocations. Enables instrumentation of global allocations. | +| `TYPEART_STACK_LIFETIME` | `stack-lifetime` | `true` | Instrument stack `llvm.lifetime.start` instead of `alloca` directly | +| `TYPEART_GLOBAL` | `global` | `false` | Instrument global allocations (see stack). | +| `TYPEART_TYPEGEN` | `typegen` | `dimeta` | Values: `dimeta`, `ir`. How serializing of type information is done, see [Section 1.1.3](#113-serialized-type-information). | +| `TYPEART_TYPE_SERIALIZATION` | `type-serialization` | `hybrid` | Values: `file`, `hybrid`, `inline`. How type information are stored (in the executable or externally), see [Section 1.1.3](#113-serialized-type-information). | +| `TYPEART_STATS` | `stats` | `false` | Show instrumentation statistic counters | +| `TYPEART_FILTER` | `filter` | `false` | Filter stack and global allocations. See also [Section 1.1.4](#114-filtering-allocations) | +| `TYPEART_FILTER_IMPLEMENTATION` | `filter-implementation` | `std` | Values: `std`, `none`. See also [Section 1.1.4](#114-filtering-allocations) | +| `TYPEART_FILTER_GLOB` | `filter-glob` | `*MPI_*` | Filter API string target (glob string) | +| `TYPEART_FILTER_GLOB_DEEP` | `filter-glob-deep` | `MPI_*` | Filter values based on specific API: Values passed as ptr are correlated when string matched. | +| `TYPEART_ANALYSIS_FILTER_GLOBAL` | `analysis-filter-global` | `true` | Filter global alloca based on heuristics | +| `TYPEART_ANALYSIS_FILTER_HEAP_ALLOCA` | `analysis-filter-heap-alloca` | `true` | Filter stack alloca that have a store instruction from a heap allocation | +| `TYPEART_ANALYSTS_FILTER_NON_ARRAY_ALLOCA` | `analysis-filter-non-array-alloca` | `false` | Filter scalar valued allocas | +| `TYPEART_ANALYSIS_FILTER_POINTER_ALLOCA` | `analysis-filter-pointer-alloca` | `true` | Filter allocas of pointer types | Additionally, there are two debug environment flags for dumping the LLVM IR per phase (pre heap, heap, opt, stack) to a set of files. | Env. variable | Description | -| :------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | +|:--------------------------------|---------------------------------------------------------------------------------------------------------------------------------| | `TYPEART_WRAPPER_EMIT_IR` | If set, the compiler wrapper will create 4 files for each TypeART phase with the file pattern `${source_basename}_heap.ll` etc. | | `TYPEART_PASS_INTERNAL_EMIT_IR` | Internal pass use only. Toggled by wrapper. | + #### 1.1.3 Serialized type information -After instrumentation, the file `typeart-types.yaml` (`env TYPEART_TYPES`) contains the static type information. Each user-defined type layout is -extracted and an integer `type-id` is attached to it. Built-in types (e.g., float) have pre-defined ids and byte -layouts. To generate these type layouts, TypeART is using either the [LLVM IR type system](https://llvm.org/docs/LangRef.html#type-system) (`typegen=ir`), or using the external library [llvm-dimeta](https://github.com/ahueck/llvm-dimeta) (`typegen=dimeta`) which extracts type information using [LLVM debug metadata](https://llvm.org/docs/SourceLevelDebugging.html). The latter is default, the former only works with LLVM 14. -The TypeART instrumentation callbacks use the `type-id`. The runtime library correlates the allocation with the -respective type (and layout) during execution. Consider the following struct: +The type's layout is then serialized by either storing it as a global variable inside each translation unit (`type-serialization=hybrid` or `inline`), or via an external yaml file (`type-serialization=file`). + +*Note*: With `file` mode (only), the compilation must be serialized, e.g., `make -j 1`, to ensure consistent type information across translation units. -After instrumentation, the `typeart-types.yaml` file (also controlled via the `TYPEART_TYPES` environment variable) stores static type information. -Each user-defined type layout is assigned a unique integer type-id. Built-in types (e.g., float) use predefined type-ids and byte layouts. -During execution, TypeART’s runtime library uses the type-id from callbacks to associate allocations with their type and layout. For example, consider the following C struct: +##### 1.1.3.1 Hybrid and Inline serialization + +Type serialization for each user-defined type (mode `hybrid`) or *all* types (mode `inline`) are stored as (constant) globals with the following format: + +```c +struct GlobalTypeInfo { + std::int32_t type_id; + const std::uint32_t extent; + const std::uint16_t num_members; + const std::uint16_t flag; + const char* name; + const std::uint16_t* offsets; + const std::uint16_t* array_sizes; + const GlobalTypeInfo** member_types; +}; +``` + +Each type is registered at startup with the TypeART runtime using the callback `void __typeart_register_type(const void* type_ptr);`. +The callback adds the type information to the type database (for user queries) and assigns a unique `type-id`. +Each user-defined type layout is assigned a unique integer `type-id` starting at 256. Built-in types (e.g., float) use predefined type-ids (< 256) and byte layouts. +The runtime library correlates the allocation with the respective type (and layout) during execution via the `type-id`. + + +##### 1.1.3.2 File-based serialization +After instrumentation, the file `typeart-types.yaml` (`env TYPEART_TYPES`) contains the static type information. Each user-defined type layout is +extracted and an integer `type-id` is attached to it (similarly to hybrid and inline serialization). +For example, consider the following C struct: ```c struct s1_t { @@ -209,7 +224,8 @@ The TypeART pass may write a `typeart-types.yaml` file with the following conten -##### Limitations of LLVM IR Type System + +##### 1.1.3.3 Side note: Limitations of LLVM IR Type System The list of supported built-in type-ids is defined in [TypeInterface.h](lib/typelib/TypeInterface.h) and reflects the types that TypeART can represent with **LLVM Debug Metadata**. In contrast, when using **LLVM IR Type System**, certain constraints are imposed. For instance, C/C++ types like unsigned integers are unsupported (and represented like signed integers). @@ -245,6 +261,7 @@ callbacks. The library also requires access to the `typeart-types.yaml` file to layouts. To specify its path, you can use the environment variable `TYPEART_TYPES`, e.g.: ```shell +# Only if previously compiled with `serialization-mode=file`, otherwise skip: $> export TYPEART_TYPES=/path/to/typeart-types.yaml # If the TypeART runtime is not resolved, LD_LIBRARY_PATH is set: $> env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(TYPEART_LIBPATH) ./binary @@ -279,7 +296,7 @@ To compile and run the demo targets: ## 2. Building TypeART -TypeART supports LLVM version 14, 18 and 19, and CMake version >= 3.20. +TypeART supports LLVM version 14, 18-21, and CMake version >= 3.20. ### 2.1 Optional software requirements @@ -290,7 +307,7 @@ TypeART supports LLVM version 14, 18 and 19, and CMake version >= 3.20. Other smaller, external dependencies are defined within the [externals folder](externals) (depending on configuration options), see [Section 2.2.1 (Runtime)](#221-cmake-configuration-options-for-users). They are automatically downloaded -during configuration time (internet connection required). +during configuration time. ### 2.2 Building @@ -312,7 +329,7 @@ $> cmake --build build --target install --parallel | Option | Default | Description | -| ---------------------------- | :-----: | -------------------------------------------------------------------------------- | +|------------------------------|:-------:|----------------------------------------------------------------------------------| | `TYPEART_MPI_WRAPPER` | `ON` | Install TypeART MPI wrapper (mpic, mpic++). Requires MPI. | | `TYPEART_USE_LEGACY_WRAPPER` | `OFF` | Use legacy wrapper invoking opt/llc directly instead of Clang's `-fpass-plugin`. | @@ -338,10 +355,10 @@ Default mode is to protect the global data structure with a (shared) mutex. Two -| Option | Default | Description | -|----------------------------------|:--------:|----------------------------------------------------------------------------------------------------------------------------------------------------| -| `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) | +| Option | Default | Description | +|---------------------------------|:-------:|--------------------------------------------------------------------------------------------------------------------------------------------------| +| `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) | @@ -349,12 +366,12 @@ Default mode is to protect the global data structure with a (shared) mutex. Two -| Option | Default | Description | -|------------------------------|:-------:|---------------------------------------------------------------------------------------------------| -| `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 | +| Option | Default | Description | +|-----------------------------|:-------:|--------------------------------------------------------------------------------------------------| +| `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 | @@ -362,12 +379,12 @@ Default mode is to protect the global data structure with a (shared) mutex. Two -| 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) | +| 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) | @@ -378,7 +395,7 @@ Example using CMake [FetchContent](https://cmake.org/cmake/help/latest/module/Fe FetchContent_Declare( typeart GIT_REPOSITORY https://github.com/tudasc/TypeART - GIT_TAG v2.1 + GIT_TAG v2.2 GIT_SHALLOW 1 ) FetchContent_MakeAvailable(typeart) @@ -392,32 +409,35 @@ target_link_libraries(my_project_target PRIVATE typeart::Runtime) [TA18] Hück, Alexander and Lehr, Jan-Patrick and Kreutzer, Sebastian and Protze, Joachim and Terboven, Christian and Bischof, Christian and Müller, Matthias S. - - Compiler-aided type tracking for correctness checking of MPI applications. + "Compiler-aided type tracking for correctness checking of MPI applications." In 2nd International Workshop on Software Correctness for HPC Applications (Correctness), - pages 51–58. IEEE, 2018. + pages 51–58. IEEE, 2018. DOI: 10.1109/Correctness.2018.00011 [TA20] Hück, Alexander and Protze, Joachim and Lehr, Jan-Patrick and Terboven, Christian and Bischof, Christian and Müller, Matthias S. - - Towards compiler-aided correctness checking of adjoint MPI applications. + "Towards compiler-aided correctness checking of adjoint MPI applications." In 4th International Workshop on Software Correctness for HPC Applications (Correctness), - pages 40–48. IEEE/ACM, 2020. + pages 40–48. IEEE/ACM, 2020. DOI: 10.1109/Correctness51934.2020.00010 [TA22] Hück, Alexander and Kreutzer, Sebastian and Protze, Joachim and Lehr, Jan-Patrick and Bischof, Christian and Terboven, Christian and Müller, Matthias S. - - Compiler-Aided Type Correctness of Hybrid MPI-OpenMP Applications. - In IT Professional, vol. 24, no. 2, pages 45–51. IEEE, 2022. + "Compiler-Aided Type Correctness of Hybrid MPI-OpenMP Applications." + In IT Professional, vol. 24, no. 2, pages 45–51. IEEE, 2022. DOI: 10.1109/MITP.2021.3093949 + + + [TA24] + Hück, Alexander and Ziegler, Tim and Schwitanski, Simon and Jenke, Joachim and Bischof, Christian. + "Compiler-Aided Correctness Checking of CUDA-Aware MPI Applications." + In SC24-W: Workshops of the International Conference for High Performance Computing, Networking, Storage and Analysis, + pages 204–213, IEEE/ACM, 2024. DOI: 10.1109/SCW63240.2024.00032 [MU13] Hilbrich, Tobias and Protze, Joachim and Schulz, Martin and de Supinski, Bronis R. and Müller, Matthias S. - - MPI Runtime Error Detection with MUST: Advances in Deadlock Detection. + "MPI Runtime Error Detection with MUST: Advances in Deadlock Detection." In Scientific Programming, vol. 21, no. 3-4, - pages 109–121, 2013. + pages 109–121, 2013. DOI: 10.3233/SPR-130368 diff --git a/lib/runtime/RuntimeInterface.h b/lib/runtime/RuntimeInterface.h index 97e12d20..df01e259 100644 --- a/lib/runtime/RuntimeInterface.h +++ b/lib/runtime/RuntimeInterface.h @@ -138,7 +138,7 @@ typeart_status typeart_get_type(const void* addr, typeart_type_info* type_info); // typeart_status typeart_get_containing_type(const void* addr, int* type_id, size_t* count, const void** base_address, // size_t* byte_offset); -typeart_status typeart_get_containing_type(typeart_type_info type_info, typeart_base_type_info* containing_type, +typeart_status typeart_get_containing_type(const typeart_type_info* type_info, typeart_base_type_info* containing_type, size_t* byte_offset); /** diff --git a/lib/runtime/TypeResolution.cpp b/lib/runtime/TypeResolution.cpp index 8552d326..056b1a6b 100644 --- a/lib/runtime/TypeResolution.cpp +++ b/lib/runtime/TypeResolution.cpp @@ -359,15 +359,15 @@ typeart_status typeart_get_type(const void* addr, typeart_type_info* base_type) return typeart::detail::query_type(addr, *base_type); } -typeart_status typeart_get_containing_type(typeart_type_info type, typeart_base_type_info* containing_type, +typeart_status typeart_get_containing_type(const typeart_type_info* type, typeart_base_type_info* containing_type, size_t* byte_offset) { typeart::RTGuard guard; - containing_type->type_id = type.base_type_info.type_id; - containing_type->count = type.base_type_info.count; - containing_type->address = type.base_type_info.address; - const typeart::PointerInfo info{type.base_type_info.type_id, type.base_type_info.count}; + containing_type->type_id = type->base_type_info.type_id; + containing_type->count = type->base_type_info.count; + containing_type->address = type->base_type_info.address; + const typeart::PointerInfo info{type->base_type_info.type_id, type->base_type_info.count}; const auto result = typeart::RuntimeSystem::get().type_resolution().getContainingTypeInfo( - type.address, containing_type->address, info, &containing_type->count, byte_offset); + type->address, containing_type->address, info, &containing_type->count, byte_offset); return result; } diff --git a/test/runtime/38_resolve_struct.c b/test/runtime/38_resolve_struct.c index 1c3a5cf9..e8130f22 100644 --- a/test/runtime/38_resolve_struct.c +++ b/test/runtime/38_resolve_struct.c @@ -42,7 +42,7 @@ void type_check_containing(const void* addr) { return; } typeart_base_type_info containing; - status = typeart_get_containing_type(info, &containing, &offset); + status = typeart_get_containing_type(&info, &containing, &offset); if (status != TYPEART_OK) { fprintf(stderr, "[Error]: Status not OK: %i for %p\n", status, addr); diff --git a/test/runtime/53_get_type.c b/test/runtime/53_get_type.c index 269d8b0a..67502eee 100644 --- a/test/runtime/53_get_type.c +++ b/test/runtime/53_get_type.c @@ -50,7 +50,7 @@ void type_check_containing(const void* addr) { return; } typeart_base_type_info info_base; - status = typeart_get_containing_type(info, &info_base, &offset); + status = typeart_get_containing_type(&info, &info_base, &offset); if (status != TYPEART_OK) { fprintf(stderr, "[Error]: Status not OK: %i for %p\n", status, addr); @@ -77,7 +77,7 @@ void type_check_sub(const void* addr, size_t offset) { return; } typeart_base_type_info info_base; - status = typeart_get_containing_type(info, &info_base, &offset_containing); + status = typeart_get_containing_type(&info, &info_base, &offset_containing); if (status != TYPEART_OK) { fprintf(stderr, "[Error]: with containing type\n"); return; diff --git a/test/runtime/54_get_type_illegal.c b/test/runtime/54_get_type_illegal.c index aed16b72..42a60276 100644 --- a/test/runtime/54_get_type_illegal.c +++ b/test/runtime/54_get_type_illegal.c @@ -61,7 +61,7 @@ void type_check_containing(const void* addr) { return; } typeart_base_type_info info_base; - status = typeart_get_containing_type(info, &info_base, &offset); + status = typeart_get_containing_type(&info, &info_base, &offset); if (status != TYPEART_OK) { fprintf(stderr, "[Expected]: Status not OK: %s for %p\n", err_code_to_string(status), addr); @@ -88,7 +88,7 @@ void type_check_sub(const void* addr, size_t offset) { return; } typeart_base_type_info info_base; - status = typeart_get_containing_type(info, &info_base, &offset_containing); + status = typeart_get_containing_type(&info, &info_base, &offset_containing); if (status != TYPEART_OK) { fprintf(stderr, "[Error]: with containing type\n"); return; From 5c0c1dab8a1b82496b3c206b40363d71549f4c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Mon, 1 Dec 2025 17:03:30 +0100 Subject: [PATCH 04/14] Readme restructure (#177) --- README.md | 276 +++++++++++++++++++++++++++--------------------------- 1 file changed, 139 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index b15ae9d0..9c7f4784 100644 --- a/README.md +++ b/README.md @@ -8,15 +8,14 @@ allocation tracking sanitizer based on the [LLVM](https://llvm.org) compiler too ## Why use it? -Low-level C APIs often rely on `void*` pointers for generic types, requiring users to manually specify type and size - a process prone to errors. Examples for type unsafe APIs include the Message-Passing Interface (MPI), -checkpointing libraries and numeric solver libraries. -TypeART simplifies verification, ensuring, for example, that a `void*` argument corresponds to an array of expected type `T` with length `n`. +Low-level C APIs often rely on `void*` pointers for generic types, requiring users to specify type and size manually, a process prone to errors. Examples of type-unsafe APIs include the Message-Passing Interface (MPI), checkpointing libraries, and numeric solver libraries. TypeART facilitates verification by ensuring, for example, that a `void*` argument corresponds to an array of expected type `T` with length `n`. + ### Use Case: MUST - A dynamic MPI correctness checker MUST \[[MU13](#ref-must-2013)\], a dynamic MPI correctness checker, detects issues like deadlocks or mismatched MPI datatypes. For more details, visit its [project page](https://www.hpc.rwth-aachen.de/must/). -MUST intercepts MPI calls for analysis but cannot deduce the *effective* type of `void*` buffers in MPI APIs. TypeART addresses this by tracking memory (de-)allocations relevant to MPI communication in user code, allowing MUST to validate type compatibility between MPI buffers and declared datatypes. +MUST intercepts MPI calls for analysis but cannot deduce the *effective* type of `void*` buffers in MPI APIs. TypeART addresses this by tracking memory allocations relevant to MPI communication in user code, allowing MUST to validate type compatibility between MPI buffers and declared datatypes. #### Type checking for MPI calls @@ -40,41 +39,55 @@ its [project page](https://itc.rwth-aachen.de/must/). * [1. Using TypeART](#1-using-typeart) * [1.1 Compiling a target code](#11-compiling-a-target-code) - * [1.1.1 Building with TypeART](#111-building-with-typeart) - * [1.1.2 Options for TypeART passes and compiler wrapper](#112-options-for-typeart-passes-and-compiler-wrapper) - * [1.1.3 Serialized type information](#113-serialized-type-information) - * [1.1.4 Filtering allocations](#114-filtering-allocations) * [1.2 Executing an instrumented target code](#12-executing-an-instrumented-target-code) * [1.3 Example: MPI demo](#13-example-mpi-demo) -* [2. Building TypeART](#2-building-typeart) - * [2.1 Optional software requirements](#21-optional-software-requirements) - * [2.2 Building](#22-building) - * [2.2.1 CMake configuration: Options for users](#221-cmake-configuration-options-for-users) -* [3. Consuming TypeART](#3-consuming-typeart) +* [2. TypeART compiler pass](#2-typeart-compiler-pass) + * [2.1 Options for controlling the TypeART pass](#21-options-for-controlling-the-typeart-pass) + * [2.2 Serialized type information](#22-serialized-type-information) + * [2.3 Filtering allocations](#23-filtering-allocations) +* [3. Building TypeART](#3-building-typeart) + * [3.1 Optional software requirements](#31-optional-software-requirements) + * [3.2 Building](#32-building) + * [3.3 CMake configuration: Options for users](#33-cmake-configuration-options-for-users) +* [4. Consuming TypeART](#4-consuming-typeart) * [References](#references) ## 1. Using TypeART Using TypeART involves two phases: -1. Compilation, see [Section 1.1](#11-compiling-a-target-code): Compile your code with Clang/LLVM using the TypeART LLVM pass plugin. The plugin (1) serializes static type information and (2) instruments relevant allocations. -2. Execution, see [Section 1.2](#12-executing-an-instrumented-target-code): Run the instrumented program with a TypeART runtime client, which uses the callback data to perform analysis facilitating the static type information. +1. Compilation, see [Section 1.1](#11-compiling-a-target-code): Compile code with Clang/LLVM using the TypeART LLVM pass plugin via the compiler wrapper script. The plugin (1) serializes static type information and (2) instruments relevant allocations. +2. Execution, see [Section 1.2](#12-executing-an-instrumented-target-code): Run the instrumented program. The TypeART runtime tracks all memory allocations. Clients can query the runtime for type information regarding a memory pointer at relevant points during program execution. + +``` ++----Compiler----+ +-----------------------------------+ +| typeart-mpicc +----+--->| TypeART-instrumented Application | ++----------------+ | +--+-----+-------------------+------+ + ^ Static | | | + | Type v v v + +----+----+ Info Alloc/Free Intercepted API + | Sources | | +-----------+ +-------------+ + +---------+ | | TypeART |+--------+ Correctness | + +--->| Runtime || Query | Tool | + | |+------->| (ex. MUST) | + +-----------+ +-------------+ +``` ### 1.1 Compiling a target code -TypeART’s LLVM compiler pass plugins instrument allocations and serialize static type layouts. We provide compiler wrapper scripts (available in the bin folder of the TypeART installation) for Clang and MPI. By default, these wrappers instrument heap, stack, and global allocations, while MPI wrappers filter allocations unrelated to MPI calls (see [Section 1.1.4](#114-filtering-allocations)). +The TypeART LLVM compiler pass instruments allocations and serializes static type layouts. Compiler wrapper scripts are provided (available in the `bin` directory of the installation) for Clang and MPI. By default, these wrappers instrument heap, stack, and global allocations. MPI wrappers additionally filter allocations unrelated to MPI calls (see [Section 2.3](#23-filtering-allocations)). -#### 1.1.1 Building with TypeART +#### Building with TypeART -Simply replace your compiler variable: +Replace the compiler variable as follows: -| Variable | TypeART Wrapper | -|----------|-------------------| -| `CXX` | `typeart-clang++` | -| `CC` | `typeart-clang` | -| `MPICC` | `typeart-mpicc` | -| `MPICXX` | `typeart-mpic++` | +| Variable | TypeART Wrapper | Equivalent to | +|----------|-------------------|---------------| +| `CXX` | `typeart-clang++` | `clang++` | +| `CC` | `typeart-clang` | `clang` | +| `MPICC` | `typeart-mpicc` | `mpicc` | +| `MPICXX` | `typeart-mpic++` | `mpic++` | The wrappers handle the LLVM pass injection and linking: @@ -85,74 +98,83 @@ $> typeart-clang++ -O2 $(COMPILE_FLAGS) -c code.cpp -o code.o $> typeart-clang++ $(LINK_FLAGS) code.o -o binary ``` -The wrapper performs the following steps using Clang's `-fpass-plugin`: - -1. Compiles the code to LLVM IR retaining original compile flags. -2. Applies heap instrumentation with TypeART (before optimizations). -3. Optimizes the code using provided -O flag. -4. Applies stack and global instrumentation with TypeART (after optimizations). -5. Links the TypeART runtime library with the provided linker flags. - -*Note*: Heap allocations are instrumented before optimizations to prevent loss of type information in some cases. - ##### CMake projects -When using CMake, the wrapper must be disabled during configuration (to pass internal compiler checks) but enabled for the build. +When using CMake, disable the wrapper during configuration (to pass internal compiler checks) but enable it for the build step. ```shell # Temporarily disable wrapper with environment flag TYPEART_WRAPPER=OFF for configuration: -$> TYPEART_WRAPPER=OFF cmake -B build -DCMAKE_C_COMPILER=*TypeART bin*/typeart-clang +$> TYPEART_WRAPPER=OFF cmake -B build -DCMAKE_C_COMPILER=/path/to/typeart-clang # Compile with typeart-clang: $> cmake --build build --target install ``` -##### MPI wrapper generation +### 1.2 Executing an instrumented target code -The wrappers `typeart-mpicc` and `typeart-mpic++` are generated for compiling MPI codes with TypeART. -Here, 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: +Execute the target binary directly. -| 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 | +```shell +# Ensure the TypeART runtime is in the library path: +$> env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(TYPEART_LIBPATH) ./binary +``` + + +### 1.3 Example: MPI demo +The folder [demo](demo) contains an example of MPI-related type errors that can be detected using TypeART. The target code is instrumented with TypeART, and executed by preloading the MPI-related check library implemented +in [tool.c](demo/tool.c). The tool library uses the TypeART [runtime query interface](lib/runtime/RuntimeInterface.h). +It overloads the required MPI calls and checks that the passed `void*` buffer corresponds to the MPI derived datatype. -#### 1.1.2 Options for controlling the TypeART pass +To compile and run the demo targets: -The pass behavior can be configured with the environment flags as listed below. The TypeART pass prioritizes environment flags (if set) over the default configuration option. +- Makefile + ```shell + # Valid MPI demo: + $> MPICC=*TypeART prefix*/bin/typeart-mpicc make run-demo + # Type-error MPI demo: + $> MPICC=*TypeART prefix*/bin/typeart-mpicc make run-demo_broken + ``` +- CMake, likewise: + ```shell + $> TYPEART_WRAPPER=OFF cmake -S demo -B build_demo -DCMAKE_C_COMPILER=*TypeART prefix*/bin/typeart-mpicc + $> cmake --build build_demo --target run-demo + $> cmake --build build_demo --target run-demo_broken + ``` + + +## 2 TypeART compiler pass -In particular, `TYPEART_OPTIONS` can be set to globally modify the TypeART pass (stack/heap specific options exist). -The format requires the option names separated by a semicolon, e.g., `TYPEART_OPTIONS="filter-glob=API_*;no-stats"` sets the filter glob target to `API_*` and deactivates stats printing of the TypeART pass. -Prepending `no-` to boolean flags sets them to false. +### 2.1 Options for controlling the TypeART pass -**Note**: Single environment options are prioritized over `TYPEART_OPTIONS`. +Pass behavior is configured via the environment flags listed below. The TypeART pass prioritizes environment flags (if set) over default configuration options. + +Specifically, `TYPEART_OPTIONS` can globally modify the TypeART pass (stack/heap specific options exist). The format requires option names separated by a semicolon, e.g., `TYPEART_OPTIONS="filter-glob=API_*;no-stats"` sets the filter glob target to `API_*` and deactivates stats printing. Prepending `no-` to boolean flags sets them to `false`. + +**Note**: Single environment options take precedence over `TYPEART_OPTIONS`. -| Env. variable | Option name | Default value | Description | -|:-------------------------------------------|------------------------------------|:--------------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `TYPEART_OPTIONS` | | | Set multiple options at once, separated by `;`. | -| `TYPEART_OPTIONS_STACK` | | | Same as above for stack phase only. | -| `TYPEART_OPTIONS_HEAP` | | | Same as above for heap phase only. | -| `TYPEART_TYPES` | `types` | `typeart-types.yaml` | Serialized type layout information of user-defined types. File location and name can also be controlled with the env variable `TYPEART_TYPES`. | -| `TYPEART_HEAP` | `heap` | `true` | Instrument heap allocations | -| `TYPEART_STACK` | `stack` | `false` | Instrument stack and global allocations. Enables instrumentation of global allocations. | -| `TYPEART_STACK_LIFETIME` | `stack-lifetime` | `true` | Instrument stack `llvm.lifetime.start` instead of `alloca` directly | -| `TYPEART_GLOBAL` | `global` | `false` | Instrument global allocations (see stack). | -| `TYPEART_TYPEGEN` | `typegen` | `dimeta` | Values: `dimeta`, `ir`. How serializing of type information is done, see [Section 1.1.3](#113-serialized-type-information). | -| `TYPEART_TYPE_SERIALIZATION` | `type-serialization` | `hybrid` | Values: `file`, `hybrid`, `inline`. How type information are stored (in the executable or externally), see [Section 1.1.3](#113-serialized-type-information). | -| `TYPEART_STATS` | `stats` | `false` | Show instrumentation statistic counters | -| `TYPEART_FILTER` | `filter` | `false` | Filter stack and global allocations. See also [Section 1.1.4](#114-filtering-allocations) | -| `TYPEART_FILTER_IMPLEMENTATION` | `filter-implementation` | `std` | Values: `std`, `none`. See also [Section 1.1.4](#114-filtering-allocations) | -| `TYPEART_FILTER_GLOB` | `filter-glob` | `*MPI_*` | Filter API string target (glob string) | -| `TYPEART_FILTER_GLOB_DEEP` | `filter-glob-deep` | `MPI_*` | Filter values based on specific API: Values passed as ptr are correlated when string matched. | -| `TYPEART_ANALYSIS_FILTER_GLOBAL` | `analysis-filter-global` | `true` | Filter global alloca based on heuristics | -| `TYPEART_ANALYSIS_FILTER_HEAP_ALLOCA` | `analysis-filter-heap-alloca` | `true` | Filter stack alloca that have a store instruction from a heap allocation | -| `TYPEART_ANALYSTS_FILTER_NON_ARRAY_ALLOCA` | `analysis-filter-non-array-alloca` | `false` | Filter scalar valued allocas | -| `TYPEART_ANALYSIS_FILTER_POINTER_ALLOCA` | `analysis-filter-pointer-alloca` | `true` | Filter allocas of pointer types | +| Env. variable | Option name | Default value | Description | +|:-------------------------------------------|------------------------------------|:--------------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `TYPEART_OPTIONS` | | | Set multiple options at once, separated by `;`. | +| `TYPEART_OPTIONS_STACK` | | | Same as above for stack phase only. | +| `TYPEART_OPTIONS_HEAP` | | | Same as above for heap phase only. | +| `TYPEART_TYPES` | `types` | `typeart-types.yaml` | Serialized type layout information of user-defined types. File location and name can also be controlled with the env variable `TYPEART_TYPES`. | +| `TYPEART_HEAP` | `heap` | `true` | Instrument heap allocations | +| `TYPEART_STACK` | `stack` | `false` | Instrument stack and global allocations. Enables instrumentation of global allocations. | +| `TYPEART_STACK_LIFETIME` | `stack-lifetime` | `true` | Instrument stack `llvm.lifetime.start` instead of `alloca` directly | +| `TYPEART_GLOBAL` | `global` | `false` | Instrument global allocations (see stack). | +| `TYPEART_TYPEGEN` | `typegen` | `dimeta` | Values: `dimeta`, `ir`. How serializing of type information is done, see [Section 2.2](#22-serialized-type-information). | +| `TYPEART_TYPE_SERIALIZATION` | `type-serialization` | `hybrid` | Values: `file`, `hybrid`, `inline`. How type information are stored (in the executable or externally), see [Section 2.2](#22-serialized-type-information). | +| `TYPEART_STATS` | `stats` | `false` | Show instrumentation statistic counters | +| `TYPEART_FILTER` | `filter` | `false` | Filter stack and global allocations. See also [Section 2.3](#23-filtering-allocations) | +| `TYPEART_FILTER_IMPLEMENTATION` | `filter-implementation` | `std` | Values: `std`, `none`. See also [Section 2.3](#23-filtering-allocations) | +| `TYPEART_FILTER_GLOB` | `filter-glob` | `*MPI_*` | Filter API string target (glob string) | +| `TYPEART_FILTER_GLOB_DEEP` | `filter-glob-deep` | `MPI_*` | Filter values based on specific API: Values passed as ptr are correlated when string matched. | +| `TYPEART_ANALYSIS_FILTER_GLOBAL` | `analysis-filter-global` | `true` | Filter global alloca based on heuristics | +| `TYPEART_ANALYSIS_FILTER_HEAP_ALLOCA` | `analysis-filter-heap-alloca` | `true` | Filter stack alloca that have a store instruction from a heap allocation | +| `TYPEART_ANALYSTS_FILTER_NON_ARRAY_ALLOCA` | `analysis-filter-non-array-alloca` | `false` | Filter scalar valued allocas | +| `TYPEART_ANALYSIS_FILTER_POINTER_ALLOCA` | `analysis-filter-pointer-alloca` | `true` | Filter allocas of pointer types | Additionally, there are two debug environment flags for dumping the LLVM IR per phase (pre heap, heap, opt, stack) to a set of files. @@ -164,17 +186,16 @@ Additionally, there are two debug environment flags for dumping the LLVM IR per -#### 1.1.3 Serialized type information +### 2.2 Serialized type information -To generate these type layouts, TypeART is using either the [LLVM IR type system](https://llvm.org/docs/LangRef.html#type-system) (`typegen=ir`), or using the external library [llvm-dimeta](https://github.com/ahueck/llvm-dimeta) (`typegen=dimeta`) which extracts type information using [LLVM debug metadata](https://llvm.org/docs/SourceLevelDebugging.html). -The latter is default, the former only works with LLVM 14. +TypeART uses either the [LLVM IR type system](https://llvm.org/docs/LangRef.html#type-system) (`typegen=ir`) or the external library [llvm-dimeta](https://github.com/ahueck/llvm-dimeta) (`typegen=dimeta`), which extracts type information using [LLVM debug metadata](https://llvm.org/docs/SourceLevelDebugging.html). The latter is the default; the former is compatible only with LLVM 14. -The type's layout is then serialized by either storing it as a global variable inside each translation unit (`type-serialization=hybrid` or `inline`), or via an external yaml file (`type-serialization=file`). +The layout is serialized either as a global variable inside each translation unit (`type-serialization=hybrid` or `inline`) or via an external YAML file (`type-serialization=file`). -*Note*: With `file` mode (only), the compilation must be serialized, e.g., `make -j 1`, to ensure consistent type information across translation units. +**Note**: In `file` mode, compilation must be serialized (e.g., `make -j 1`) to ensure consistent type information across translation units. -##### 1.1.3.1 Hybrid and Inline serialization +#### 2.2.1 Hybrid and Inline serialization Type serialization for each user-defined type (mode `hybrid`) or *all* types (mode `inline`) are stored as (constant) globals with the following format: @@ -184,20 +205,18 @@ struct GlobalTypeInfo { const std::uint32_t extent; const std::uint16_t num_members; const std::uint16_t flag; - const char* name; + const char* type_name; const std::uint16_t* offsets; const std::uint16_t* array_sizes; const GlobalTypeInfo** member_types; }; ``` -Each type is registered at startup with the TypeART runtime using the callback `void __typeart_register_type(const void* type_ptr);`. -The callback adds the type information to the type database (for user queries) and assigns a unique `type-id`. -Each user-defined type layout is assigned a unique integer `type-id` starting at 256. Built-in types (e.g., float) use predefined type-ids (< 256) and byte layouts. -The runtime library correlates the allocation with the respective type (and layout) during execution via the `type-id`. +Each type is registered at startup with the TypeART runtime using the callback `void __typeart_register_type(const void* type_ptr);`. This adds the type information to the type database (for user queries) and assigns a unique `type-id`. +Each user-defined type layout is assigned a unique integer `type-id` starting at 256. Built-in types (e.g., `float`) use predefined type-ids (\< 256) and byte layouts. The runtime library correlates the allocation with the respective type (and layout) during execution via the `type-id`. -##### 1.1.3.2 File-based serialization +#### 2.2.2 File-based serialization After instrumentation, the file `typeart-types.yaml` (`env TYPEART_TYPES`) contains the static type information. Each user-defined type layout is extracted and an integer `type-id` is attached to it (similarly to hybrid and inline serialization). For example, consider the following C struct: @@ -224,16 +243,23 @@ The TypeART pass may write a `typeart-types.yaml` file with the following conten +Executing a target binary requires access to the `typeart-types.yaml` file to correlate the type-id with actual type layouts. Specify the path using the environment variable `TYPEART_TYPES`: + +```bash +$> export TYPEART_TYPES=/path/to/typeart-types.yaml +# If the TypeART runtime is not resolved, LD_LIBRARY_PATH is set: +$> env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(TYPEART_LIBPATH) ./binary +``` -##### 1.1.3.3 Side note: Limitations of LLVM IR Type System +#### 2.2.3 Side note: Limitations of LLVM IR Type System The list of supported built-in type-ids is defined in [TypeInterface.h](lib/typelib/TypeInterface.h) and reflects the types that TypeART can represent with **LLVM Debug Metadata**. In contrast, when using **LLVM IR Type System**, certain constraints are imposed. For instance, C/C++ types like unsigned integers are unsupported (and represented like signed integers). -#### 1.1.4 Filtering allocations +### 2.3 Filtering allocations -To improve performance, a translation unit-local (TU) data-flow filter for global and stack variables exist. It follows the LLVM IR use-def chain. If the allocation provably never reaches the target API, it can be filtered. Otherwise, it is instrumented. Use the option `filter` to filter and `filter-glob=` (default: `*MPI_*`) to target the correct API. +To improve performance, a translation unit-local (TU) data-flow filter for global and stack variables exist. It follows the LLVM IR use-def chain. If the allocation provably never reaches the target API, it can be filtered. Otherwise, it is instrumented. Use the option `filter` to enable filtering and `filter-glob=` (default: `*MPI_*`) to specify the API. Consider the following example. @@ -250,55 +276,16 @@ void foo() { } ``` -1. The filter can remove `a`, as the aliasing pointer `x` is never part of an MPI call. -2. `b` is instrumented as the aliasing pointer `y` is part of an MPI call. -3. `c` is instrumented as we cannot reason about the body of `foo_bar`. - -### 1.2 Executing an instrumented target code - -To execute the instrumented code, the TypeART runtime library (or a derivative) has to be loaded to accept the -callbacks. The library also requires access to the `typeart-types.yaml` file to correlate the `type-id` with the actual type -layouts. To specify its path, you can use the environment variable `TYPEART_TYPES`, e.g.: - -```shell -# Only if previously compiled with `serialization-mode=file`, otherwise skip: -$> export TYPEART_TYPES=/path/to/typeart-types.yaml -# If the TypeART runtime is not resolved, LD_LIBRARY_PATH is set: -$> env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(TYPEART_LIBPATH) ./binary -``` +1. `a` is filtered because the aliasing pointer `x` is never part of an MPI call. +2. `b` is instrumented because the aliasing pointer `y` is part of an MPI call. +3. `c` is instrumented because the body of `foo_bar` cannot be reasoned about. -An example for pre-loading a TypeART-based library in the context of MPI is found in the demo, -see [Section 1.3](#13-example-mpi-demo). - -### 1.3 Example: MPI demo - -The folder [demo](demo) contains an example of MPI-related type errors that can be detected using TypeART. The code is -compiled with our instrumentation, and executed by preloading the MPI-related check library implemented -in [tool.c](demo/tool.c). The check library uses the TypeART [runtime query interface](lib/runtime/RuntimeInterface.h). -It overloads the required MPI calls and checks that the passed `void*` buffer is correct w.r.t. the MPI derived -datatype. - -To compile and run the demo targets: - -- Makefile - ```shell - # Valid MPI demo: - $> MPICC=*TypeART prefix*/bin/typeart-mpicc make run-demo - # Type-error MPI demo: - $> MPICC=*TypeART prefix*/bin/typeart-mpicc make run-demo_broken - ``` -- CMake, likewise: - ```shell - $> TYPEART_WRAPPER=OFF cmake -S demo -B build_demo -DCMAKE_C_COMPILER=*TypeART prefix*/bin/typeart-mpicc - $> cmake --build build_demo --target run-demo - $> cmake --build build_demo --target run-demo_broken - ``` -## 2. Building TypeART +## 3. Building TypeART TypeART supports LLVM version 14, 18-21, and CMake version >= 3.20. -### 2.1 Optional software requirements +### 3.1 Optional software requirements - MPI library: (soft requirement) Needed for the MPI compiler wrappers, tests, the [demo](demo), our [MPI interceptor library](lib/mpi_interceptor), and for logging with our TypeART runtime library within an MPI @@ -306,10 +293,10 @@ TypeART supports LLVM version 14, 18-21, and CMake version >= 3.20. - OpenMP-enabled Clang compiler: Needed for some tests. Other smaller, external dependencies are defined within the [externals folder](externals) (depending on configuration -options), see [Section 2.2.1 (Runtime)](#221-cmake-configuration-options-for-users). They are automatically downloaded +options), see [Section 3.3 (Runtime)](#33-cmake-configuration-options-for-users). They are automatically downloaded during configuration time. -### 2.2 Building +### 3.2 Building TypeART uses CMake to build, cf. [GitHub CI build file](.github/workflows/basic-ci.yml) for a complete recipe to build. Example build recipe (debug build, installs to default prefix @@ -322,7 +309,7 @@ $> cmake -B build $> cmake --build build --target install --parallel ``` -#### 2.2.1 CMake configuration: Options for users +### 3.3 CMake configuration: Options for users ##### Binaries (scripts) @@ -362,7 +349,7 @@ Default mode is to protect the global data structure with a (shared) mutex. Two -##### LLVM passes +##### LLVM pass @@ -388,7 +375,22 @@ Default mode is to protect the global data structure with a (shared) mutex. Two -## 3. Consuming TypeART +#### 3.3.1 CMake Internals + +##### MPI wrapper generation + +The wrappers `typeart-mpicc` and `typeart-mpic++` are generated for compiling MPI codes with TypeART. +The build system detects the vendor to generate wrappers with appropriate environment variables that force the use of the Clang/LLVM compiler. +Detection is supported for OpenMPI, Intel MPI, and MPICH based on `mpi.h` symbols. The following flags are used to set 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 | + + +## 4. Consuming TypeART Example using CMake [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) for consuming the TypeART runtime library. ```cmake From a2c684117eb82a51da0ab4f6e850ab0702e2caeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Wed, 10 Dec 2025 19:22:58 +0100 Subject: [PATCH 05/14] Improve sanitizer handling (#178) --- lib/passes/TypeARTPass.cpp | 25 ++++- lib/passes/analysis/MemInstFinder.cpp | 137 ++++++++++++----------- lib/passes/filter/Matcher.h | 2 +- lib/passes/support/Util.h | 24 ++++ test/pass/filter/24_tysan_compat.cpp | 21 ++++ test/pass/filter/25_tysan_compat_mpi.cpp | 25 +++++ 6 files changed, 163 insertions(+), 71 deletions(-) create mode 100644 test/pass/filter/24_tysan_compat.cpp create mode 100644 test/pass/filter/25_tysan_compat_mpi.cpp diff --git a/lib/passes/TypeARTPass.cpp b/lib/passes/TypeARTPass.cpp index b8cc68d2..3d7a8b3c 100644 --- a/lib/passes/TypeARTPass.cpp +++ b/lib/passes/TypeARTPass.cpp @@ -50,7 +50,9 @@ #include #include +#include #include +#include #include #include #include @@ -283,14 +285,33 @@ class TypeArtPass : public llvm::PassInfoMixin { } } - const auto instrumented_function = llvm::count_if(m.functions(), [&](auto& f) { return runOnFunc(f); }) > 0; + llvm::DenseSet tor_funcs; + { + const auto collect_funcs = [&tor_funcs](const auto* constant) -> bool { + if (llvm::isa(constant)) { + tor_funcs.insert(constant); + } + return false; + }; + + util::for_each_cdtor("llvm.global_ctors", m, collect_funcs); + util::for_each_cdtor("llvm.global_dtors", m, collect_funcs); + } + + const auto instrumented_function = llvm::count_if(m.functions(), [&](auto& f) { + if (tor_funcs.contains(&f)) { + LOG_DEBUG("Function is in LLVM global ctor or dtor " << f.getName()) + return false; + } + return runOnFunc(f); + }) > 0; return instrumented_function || globals_were_instrumented; } bool runOnFunc(llvm::Function& f) { using namespace typeart; - if (f.isDeclaration() || util::starts_with_any_of(f.getName(), "__typeart", "typeart")) { + if (f.isDeclaration() || util::starts_with_any_of(f.getName(), "__typeart", "typeart", "__sanitizer", "__tysan")) { return false; } diff --git a/lib/passes/analysis/MemInstFinder.cpp b/lib/passes/analysis/MemInstFinder.cpp index 27bfb9ec..1260db13 100644 --- a/lib/passes/analysis/MemInstFinder.cpp +++ b/lib/passes/analysis/MemInstFinder.cpp @@ -180,74 +180,75 @@ bool MemInstFinderPass::runOnModule(Module& module) { auto& globals = mOpsCollector.globals; NumDetectedGlobals += globals.size(); if (config[config::ConfigStdArgs::analysis_filter_global]) { - globals.erase(llvm::remove_if( - globals, - [&](const auto gdata) { // NOLINT - GlobalVariable* global = gdata.global; - const auto name = global->getName(); - - LOG_DEBUG("Analyzing global: " << name); - - if (name.empty()) { - return true; - } - - if (util::starts_with_any_of(name, "llvm.", "__llvm_gcov", "__llvm_gcda", "__profn", "___asan", - "__msan", "__tsan", "__typeart", "_typeart")) { - LOG_DEBUG("Prefixed matched on " << name) - return true; - } - - if (global->hasInitializer()) { - auto* ini = global->getInitializer(); - std::string ini_name = util::dump(*ini); - - if (llvm::StringRef(ini_name).contains("std::ios_base::Init")) { - LOG_DEBUG("std::ios"); - return true; - } - } - - if (global->hasSection()) { - // for instance, filters: - // a) (Coverage) -fprofile-instr-generate -fcoverage-mapping - // b) (PGO) -fprofile-instr-generate - StringRef Section = global->getSection(); - // Globals from llvm.metadata aren't emitted, do not instrument them. - if (Section == "llvm.metadata") { - LOG_DEBUG("metadata"); - return true; - } - // Do not instrument globals from special LLVM sections. - if (Section.find("__llvm") != StringRef::npos || Section.find("__LLVM") != StringRef::npos) { - LOG_DEBUG("llvm section"); - return true; - } - } - - if ((global->getLinkage() == GlobalValue::ExternalLinkage && global->isDeclaration())) { - LOG_DEBUG("Linkage: External"); - return true; - } - - Type* global_type = global->getValueType(); - if (!global_type->isSized()) { - LOG_DEBUG("not sized"); - return true; - } - - if (global_type->isArrayTy()) { - global_type = global_type->getArrayElementType(); - } - if (auto structType = dyn_cast(global_type)) { - if (structType->isOpaque()) { - LOG_DEBUG("Encountered opaque struct " << global_type->getStructName() << " - skipping..."); - return true; - } - } - return false; - }), - globals.end()); + globals.erase( + llvm::remove_if( + globals, + [&](const auto gdata) { // NOLINT + GlobalVariable* global = gdata.global; + const auto name = global->getName(); + + LOG_DEBUG("Analyzing global: " << name); + + if (name.empty()) { + return true; + } + + if (util::starts_with_any_of(name, "llvm.", "__llvm_gcov", "__llvm_gcda", "__profn", "___asan", "__msan", + "__tsan", "__typeart", "_typeart", "__tysan", "__dfsan", "__profc")) { + LOG_DEBUG("Prefixed matched on " << name) + return true; + } + + if (global->hasInitializer()) { + auto* ini = global->getInitializer(); + std::string ini_name = util::dump(*ini); + + if (llvm::StringRef(ini_name).contains("std::ios_base::Init")) { + LOG_DEBUG("std::ios"); + return true; + } + } + + if (global->hasSection()) { + // for instance, filters: + // a) (Coverage) -fprofile-instr-generate -fcoverage-mapping + // b) (PGO) -fprofile-instr-generate + StringRef Section = global->getSection(); + // Globals from llvm.metadata aren't emitted, do not instrument them. + if (Section == "llvm.metadata") { + LOG_DEBUG("metadata"); + return true; + } + // Do not instrument globals from special LLVM sections. + if (Section.find("__llvm") != StringRef::npos || Section.find("__LLVM") != StringRef::npos) { + LOG_DEBUG("llvm section"); + return true; + } + } + + if ((global->getLinkage() == GlobalValue::ExternalLinkage && global->isDeclaration())) { + LOG_DEBUG("Linkage: External"); + return true; + } + + Type* global_type = global->getValueType(); + if (!global_type->isSized()) { + LOG_DEBUG("not sized"); + return true; + } + + if (global_type->isArrayTy()) { + global_type = global_type->getArrayElementType(); + } + if (auto structType = dyn_cast(global_type)) { + if (structType->isOpaque()) { + LOG_DEBUG("Encountered opaque struct " << global_type->getStructName() << " - skipping..."); + return true; + } + } + return false; + }), + globals.end()); const auto beforeCallFilter = globals.size(); NumFilteredGlobals = NumDetectedGlobals - beforeCallFilter; diff --git a/lib/passes/filter/Matcher.h b/lib/passes/filter/Matcher.h index a5d56aaf..d58653ec 100644 --- a/lib/passes/filter/Matcher.h +++ b/lib/passes/filter/Matcher.h @@ -88,7 +88,7 @@ class FunctionOracleMatcher final : public Matcher { if (mem_operations.kind(f_name)) { return MatchResult::ShouldSkip; } - if (util::starts_with_any_of(f_name_ref, "__ubsan", "__asan", "__msan")) { + if (util::starts_with_any_of(f_name_ref, "__ubsan", "__asan", "__msan", "__tysan", "__dfsan", "__tsan")) { return MatchResult::ShouldContinue; } } diff --git a/lib/passes/support/Util.h b/lib/passes/support/Util.h index e3804104..c7b48fa8 100644 --- a/lib/passes/support/Util.h +++ b/lib/passes/support/Util.h @@ -19,11 +19,14 @@ #include "llvm/Demangle/Demangle.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Regex.h" #include "llvm/Support/raw_ostream.h" #include #include +#include +#include #include namespace typeart::util { @@ -202,6 +205,27 @@ inline bool ends_with_any_of(llvm::StringRef lhs, StringTy... rhs) { #endif } +template +void for_each_cdtor(llvm::StringRef name, llvm::Module& module, Matcher&& matching_fn) { + using namespace llvm; + auto* GVCtor = module.getNamedGlobal(name); + if (!GVCtor) { + return; + } + if (Constant* Init = GVCtor->getInitializer()) { + for (Value* OP : Init->operands()) { + auto* const_struct = dyn_cast(OP); + if (!const_struct || const_struct->getNumOperands() < 3) { + continue; + } + + if (matching_fn(const_struct->getOperand(1))) { + return; + } + } + } +} + } // namespace typeart::util #endif /* LIB_UTIL_H_ */ diff --git a/test/pass/filter/24_tysan_compat.cpp b/test/pass/filter/24_tysan_compat.cpp new file mode 100644 index 00000000..2b157e56 --- /dev/null +++ b/test/pass/filter/24_tysan_compat.cpp @@ -0,0 +1,21 @@ +// clang-format off +// RUN: %clang-cpp -O0 -g -fsanitize=type -emit-llvm -o - -c %s | %apply-typeart --typeart-stack=true --typeart-filter=true -S 2>&1 | %filecheck %s +// clang-format on + +// REQUIRES: llvm-20 || llvm-21 + +#include + +int square(float in) { + float num = in * in; + float b = fabs(num); + return 1; +} + +// CHECK: TypeArtPass [Heap & Stack] +// CHECK-NEXT: Malloc : 0 +// CHECK-NEXT: Free : 0 +// CHECK-NEXT: Alloca : 0 +// CHECK-NEXT: Global : 0 + +// CHECK: call void @__tysan_init \ No newline at end of file diff --git a/test/pass/filter/25_tysan_compat_mpi.cpp b/test/pass/filter/25_tysan_compat_mpi.cpp new file mode 100644 index 00000000..656b7ac5 --- /dev/null +++ b/test/pass/filter/25_tysan_compat_mpi.cpp @@ -0,0 +1,25 @@ +// clang-format off +// RUN: %clang-cpp -O0 -g -fsanitize=type -emit-llvm -o - -c %s | %apply-typeart --typeart-stack=true --typeart-filter=true -S 2>&1 | %filecheck %s +// clang-format on + +// REQUIRES: llvm-20 || llvm-21 + +#include + +extern void MPI_mock(void*); + +int square(float in) { + float num = in * in; + float calc = fabs(in) * num; + MPI_mock((void*)&calc); + return 1; +} + +// CHECK: TypeArtPass [Heap & Stack] +// CHECK-NEXT: Malloc : 0 +// CHECK-NEXT: Free : 0 +// CHECK-NEXT: Alloca : 1 +// CHECK-NEXT: Global : 0 + +// CHECK: @__typeart_alloc_stack(ptr %{{[a-zA-Z0-9]+}}, +// CHECK: call void @__tysan_init \ No newline at end of file From 81eaffcebfb4b4f6ae9280c86aff243d5e6218f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Fri, 12 Dec 2025 18:58:06 +0100 Subject: [PATCH 06/14] Global types comdat (#179) --- lib/passes/instrumentation/TypeIDProvider.cpp | 183 +++++++----------- lib/runtime/GlobalTypeDefCallbacks.cpp | 12 ++ test/pass/inline_types/02_calloc_realloc.c | 2 +- .../inline_types/03_simple_malloc_struct.c | 2 +- test/pass/inline_types/04_fwd_decl.cpp | 4 +- .../inline_types/05_malloc_struct_nested.c | 28 +++ .../01_simple_malloc_int.c | 4 +- .../02_simple_malloc_int_multi_tu.c | 4 +- .../03_simple_malloc_struct.c | 2 +- test/runtime_inlined_types/04_malloc_struct.c | 2 +- test/runtime_inlined_types/05_mpi_test.c | 16 ++ .../06_simple_malloc_int_shared.c | 38 ++++ test/typemapping/13_complex.c | 2 +- test/typemapping/14_union.c | 2 +- test/typemapping/15_wchar.c | 2 +- test/typemapping/16_mpi_dtype.c | 4 +- 16 files changed, 181 insertions(+), 126 deletions(-) create mode 100644 test/pass/inline_types/05_malloc_struct_nested.c create mode 100644 test/runtime_inlined_types/05_mpi_test.c create mode 100644 test/runtime_inlined_types/06_simple_malloc_int_shared.c diff --git a/lib/passes/instrumentation/TypeIDProvider.cpp b/lib/passes/instrumentation/TypeIDProvider.cpp index fcfb0e26..b24a46a6 100644 --- a/lib/passes/instrumentation/TypeIDProvider.cpp +++ b/lib/passes/instrumentation/TypeIDProvider.cpp @@ -76,33 +76,6 @@ inline std::string create_prefixed_name(Args&&... args) { namespace typedb { -struct GlobalTypeData { - struct TypeData { - llvm::Constant* type_struct; - llvm::GlobalVariable* type; - llvm::Constant* name; - llvm::Constant* offset; - llvm::Constant* count; - }; - llvm::StringMap global_type_data; - - inline bool has_type_name(llvm::StringRef name) const { -#if LLVM_VERSION_MAJOR > 17 - return global_type_data.contains(name); -#else - return global_type_data.find(name) != global_type_data.end(); -#endif - } - - inline const TypeData& get_type(llvm::StringRef name) const { -#if LLVM_VERSION_MAJOR > 17 - return global_type_data.at(name); -#else - return global_type_data.find(name)->second; -#endif - } -}; - struct GlobalTypeCallback { llvm::Module* module_; const TAFunctionQuery* f_query_; @@ -245,7 +218,6 @@ struct GlobalTypeRegistrar { llvm::IRBuilder<> ir_build; GlobalTypeCallback type_callback; llvm::StructType* struct_layout_type_; - GlobalTypeData global_types_; TypeHelper types_helper; const bool builtin_emit_name{false}; @@ -267,119 +239,108 @@ struct GlobalTypeRegistrar { llvm::GlobalVariable* create_global( llvm::StringRef name, llvm::Type* type, llvm::Constant* init = nullptr, - llvm::GlobalVariable::LinkageTypes link_type = llvm::GlobalValue::WeakODRLinkage) const { - // TODO: https://llvm.org/docs/LangRef.html#linkage w.r.t. forward declared types + llvm::GlobalVariable::LinkageTypes link_type = llvm::GlobalValue::PrivateLinkage) const { auto* global_struct = new llvm::GlobalVariable(*module_, type, true, link_type, init, helper::create_prefixed_name(name)); return global_struct; } - llvm::Constant* make_gep(llvm::Type* type, llvm::GlobalVariable* global) { - auto* i32_zero_const = llvm::ConstantInt::get(ir_build.getInt32Ty(), 0); - return llvm::ConstantExpr::getInBoundsGetElementPtr( - type, global, llvm::ArrayRef{i32_zero_const, i32_zero_const}); - } - - llvm::Constant* create_global_constant_string(llvm::StringRef name) { - // TODO think about linkage - // auto* name_str = ir_build.CreateGlobalStringPtr(name, helper::create_prefixed_name("typename_", name), 0, - // module_); + llvm::Constant* create_global_constant_string(llvm::StringRef name, llvm::StringRef payload) { auto* global_string = - ir_build.CreateGlobalString(name, helper::create_prefixed_name("typename_", name), 0, module_); + ir_build.CreateGlobalString(payload, helper::create_prefixed_name("typename_", name), 0, module_); global_string->setConstant(true); - global_string->setLinkage(llvm::GlobalValue::WeakODRLinkage); - return make_gep(global_string->getValueType(), global_string); + global_string->setLinkage(llvm::GlobalValue::PrivateLinkage); + return global_string; } - llvm::Constant* create_global_array_ptr(const llvm::StringRef name, llvm::ArrayRef values) { - if (values.empty()) { - LOG_DEBUG("No values for global array, returning nullptr") + template + llvm::Constant* create_global_array_from_range(llvm::StringRef global_name, const InputRange& inputs, + llvm::Type* element_type, ConversionFunc&& convert_element) { + if (inputs.empty()) { + LOG_DEBUG("No values for global array, returning nullptr"); return types_helper.get_constant_nullptr(); } std::vector constants; - constants.reserve(values.size()); - for (uint64_t val : values) { - constants.push_back(types_helper.get_constant_for(IGlobalType::member_offsets, val)); + constants.reserve(inputs.size()); + + for (const auto& val : inputs) { + constants.push_back(convert_element(val)); } - auto* array_ty = llvm::ArrayType::get(types_helper.get_type_for(IGlobalType::member_offsets, true), values.size()); + auto* array_ty = llvm::ArrayType::get(element_type, inputs.size()); auto* constant_array = llvm::ConstantArray::get(array_ty, constants); - auto* gv = create_global(name, array_ty, constant_array); - return make_gep(array_ty, gv); - } - - llvm::GlobalVariable* registerGlobalStruct(const std::string& name, int type_id, uint64_t type_size, - uint64_t member_count, llvm::Constant* offset_ptr, - llvm::Constant* members_data_ptr, llvm::Constant* count_ptr, - StructTypeFlag flag = StructTypeFlag::USER_DEFINED) { - const auto name_struct = flag == StructTypeFlag::FWD_DECL ? helper::concat(name, "_fwd") : name; - llvm::GlobalVariable* global_struct = create_global(name_struct, struct_layout_type_); - global_struct->setConstant(false); - - // In the current scheme, built-ins do not need to produce a name string (Built) - const bool is_builtin = flag == StructTypeFlag::BUILTIN; - const bool emit_builtin_typename = is_builtin && builtin_emit_name; - llvm::Constant* name_str = (emit_builtin_typename || !is_builtin) ? create_global_constant_string(name) - : types_helper.get_constant_nullptr(); - - std::vector members = { - types_helper.get_constant_for(IGlobalType::type_id, type_id), - types_helper.get_constant_for(IGlobalType::extent, type_size), - types_helper.get_constant_for(IGlobalType::member_count, member_count), - types_helper.get_constant_for(IGlobalType::type_flag, - static_cast(flag)), // TODO: use real type - name_str, // - offset_ptr, // - count_ptr, // - members_data_ptr}; - llvm::Constant* init = llvm::ConstantStruct::get(struct_layout_type_, members); - global_struct->setInitializer(init); + return create_global(global_name, array_ty, constant_array); + } - global_types_.global_type_data.try_emplace( - name, GlobalTypeData::TypeData{init, global_struct, name_str, offset_ptr, count_ptr}); + llvm::Constant* create_global_array_ptr(const llvm::StringRef name, llvm::ArrayRef values, + IGlobalType type = IGlobalType::member_offsets) { + return create_global_array_from_range(name, values, types_helper.get_type_for(IGlobalType::member_offsets, true), + [&](uint64_t val) { return types_helper.get_constant_for(type, val); }); + } - return global_struct; + llvm::Constant* create_global_member_array_ptr(const llvm::StringRef name, llvm::ArrayRef member_types) { + return create_global_array_from_range(name, member_types, types_helper.get_type_for(IGlobalType::member_types), + [&](int member_id) { return getOrRegister(member_id); }); } llvm::GlobalVariable* registerTypeStruct(const StructTypeInfo* type_struct) { - const auto name = type_struct->name; - const auto type_size = type_struct->extent; + const auto base_name = type_struct->name; + const bool is_fwd = type_struct->flag == StructTypeFlag::FWD_DECL; + const auto link_name = is_fwd ? helper::concat(base_name, "_fwd") : base_name; - if (type_struct->flag == StructTypeFlag::FWD_DECL) { - LOG_DEBUG("Type is forward decl " << name) - // return registerGlobalStructDecl(name); + if (is_fwd) { + LOG_DEBUG("Type is forward decl " << base_name) } - llvm::Constant* offset_ptr = create_global_array_ptr(helper::concat("offsets_", name), type_struct->offsets); - llvm::Constant* count_ptr = create_global_array_ptr(helper::concat("counts_", name), type_struct->array_sizes); + llvm::Constant* offsets_ptr = create_global_array_ptr(helper::concat("offsets_", link_name), type_struct->offsets); + llvm::Constant* counts_ptr = create_global_array_ptr(helper::concat("counts_", link_name), type_struct->array_sizes, + IGlobalType::member_count); + llvm::Constant* members_ptr = + create_global_member_array_ptr(helper::concat("member_types_", link_name), type_struct->member_types); - llvm::Constant* members_array; - llvm::Type* ptr_type{nullptr}; // TODO: make this unqual? - std::vector member_types{}; + const bool is_builtin = type_struct->flag == StructTypeFlag::BUILTIN; + const bool emit_name = !is_builtin || builtin_emit_name; - for (auto member_type_id : type_struct->member_types) { - llvm::Constant* member = getOrRegister(member_type_id); - if (ptr_type == nullptr) { - ptr_type = member->getType(); - } - member_types.emplace_back(member); - } + llvm::Constant* name_str_ptr = + emit_name ? create_global_constant_string(link_name, base_name) : types_helper.get_constant_nullptr(); - const auto member_count = type_struct->member_types.size(); - if (ptr_type != nullptr) { - assert(member_count == type_struct->num_members); - llvm::ArrayType* member_array_ty = llvm::ArrayType::get(ptr_type, member_count); - llvm::Constant* init = llvm::ConstantArray::get(member_array_ty, member_types); - members_array = create_global(helper::concat("member_types_", name), member_array_ty, init); - } else { - llvm::Constant* null_member = types_helper.get_constant_nullptr(); - members_array = null_member; + llvm::GlobalVariable* global_struct = + create_global(link_name, struct_layout_type_, nullptr, llvm::GlobalValue::LinkOnceODRLinkage); + global_struct->setConstant(false); + + std::vector init_fields = { + types_helper.get_constant_for(IGlobalType::type_id, type_struct->type_id), + types_helper.get_constant_for(IGlobalType::extent, type_struct->extent), + types_helper.get_constant_for(IGlobalType::member_count, type_struct->member_types.size()), + types_helper.get_constant_for(IGlobalType::type_flag, static_cast(type_struct->flag)), + name_str_ptr, + offsets_ptr, + counts_ptr, + members_ptr}; + + llvm::Constant* init = llvm::ConstantStruct::get(struct_layout_type_, init_fields); + global_struct->setInitializer(init); + + { + llvm::Comdat* comdat = this->module_->getOrInsertComdat(helper::create_prefixed_name(link_name)); + comdat->setSelectionKind(llvm::Comdat::Any); + global_struct->setComdat(comdat); + + auto add_to_comdat = [&](llvm::Constant* ptr) { + if (auto* global = llvm::dyn_cast_or_null(ptr)) { + global->setComdat(comdat); + } + }; + + add_to_comdat(offsets_ptr); + add_to_comdat(counts_ptr); + add_to_comdat(members_ptr); + add_to_comdat(name_str_ptr); } - return registerGlobalStruct(name, type_struct->type_id, type_size, member_count, offset_ptr, members_array, - count_ptr, type_struct->flag); + return global_struct; } llvm::GlobalVariable* registerBuiltin(int type_id) { diff --git a/lib/runtime/GlobalTypeDefCallbacks.cpp b/lib/runtime/GlobalTypeDefCallbacks.cpp index 77812f5b..e59ec73f 100644 --- a/lib/runtime/GlobalTypeDefCallbacks.cpp +++ b/lib/runtime/GlobalTypeDefCallbacks.cpp @@ -85,6 +85,18 @@ class GlobalTypeTranslator::Impl { } const bool fwd_decl = type_descriptor.flag == StructTypeFlag::FWD_DECL; + { + LOG_DEBUG("StructTypeInfo Dump " << (fwd_decl ? "FWD" : "") << type_descriptor.name); + LOG_DEBUG(" Type_id: " << type_descriptor.type_id); + LOG_DEBUG(" Extent: " << type_descriptor.extent); + LOG_DEBUG(" Num Members: " << type_descriptor.num_members); + LOG_DEBUG(" Flag: " << static_cast(type_descriptor.flag)); + for (uint32_t i = 0; i < type->num_members; ++i) { + LOG_DEBUG(" Member[" << i << "]: " + << "ID=" << type_db_.getTypeName(type_descriptor.member_types[i]) << ", Offset=" + << type_descriptor.offsets[i] << ", ArraySize=" << type_descriptor.array_sizes[i]); + } + } type_db_.registerStruct(type_descriptor, not fwd_decl); translator_map_.try_emplace(type, type_descriptor.type_id); diff --git a/test/pass/inline_types/02_calloc_realloc.c b/test/pass/inline_types/02_calloc_realloc.c index 6c568d70..62bcb636 100644 --- a/test/pass/inline_types/02_calloc_realloc.c +++ b/test/pass/inline_types/02_calloc_realloc.c @@ -2,7 +2,7 @@ // RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S 2>&1 | %filecheck %s --check-prefix=REALLOC // RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S 2>&1 | %filecheck %s -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 // clang-format on #include diff --git a/test/pass/inline_types/03_simple_malloc_struct.c b/test/pass/inline_types/03_simple_malloc_struct.c index 9cec9b30..3d6fde09 100644 --- a/test/pass/inline_types/03_simple_malloc_struct.c +++ b/test/pass/inline_types/03_simple_malloc_struct.c @@ -5,7 +5,7 @@ // RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=file -S 2>&1 | %filecheck %s --check-prefix FILE -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 // clang-format on #include typedef struct ms { diff --git a/test/pass/inline_types/04_fwd_decl.cpp b/test/pass/inline_types/04_fwd_decl.cpp index 01ad31c8..4066ad7e 100644 --- a/test/pass/inline_types/04_fwd_decl.cpp +++ b/test/pass/inline_types/04_fwd_decl.cpp @@ -1,8 +1,8 @@ // RUN: %cpp-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S | %filecheck %s -// CHECK: @_typeart__ZTS6Domain_fwd = weak_odr global %struct._typeart_struct_layout_t { i32 256, +// CHECK: @_typeart__ZTS6Domain_fwd = linkonce_odr global %struct._typeart_struct_layout_t { i32 256, -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 class Domain { public: diff --git a/test/pass/inline_types/05_malloc_struct_nested.c b/test/pass/inline_types/05_malloc_struct_nested.c new file mode 100644 index 00000000..36f880c5 --- /dev/null +++ b/test/pass/inline_types/05_malloc_struct_nested.c @@ -0,0 +1,28 @@ +// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S | %filecheck --match-full-lines %s + +// REQUIRES: !llvm-14 + +#include + +struct DataNested { + struct DataNested* nested_pointer; +}; + +struct DataHolder { + double a; + float b; + int c; + struct DataNested nested; +}; + +int main(void) { + struct DataHolder* p = (struct DataHolder*)malloc(2 * sizeof(struct DataHolder)); + free(p); + return 0; +} + +// clang-format off +// CHECK-DAG: @_typeart_member_types_DataNested = private constant [1 x ptr] [ptr @_typeart_ptr], comdat($_typeart_DataNested) +// CHECK-DAG: @_typeart_DataHolder = linkonce_odr global %struct._typeart_struct_layout_t { i32 256, i32 24, i16 4, i16 1, ptr @_typeart_typename_DataHolder, ptr @_typeart_offsets_DataHolder, ptr @_typeart_counts_DataHolder, ptr @_typeart_member_types_DataHolder }, comdat +// CHECK-DAG: @_typeart_member_types_DataHolder = private constant [4 x ptr] [ptr @_typeart_double, ptr @_typeart_float, ptr @_typeart_int, ptr @_typeart_DataNested], comdat($_typeart_DataHolder) +// CHECK-DAG: @_typeart_typename_DataHolder = private unnamed_addr constant [11 x i8] c"DataHolder\00", comdat($_typeart_DataHolder), align 1 diff --git a/test/runtime_inlined_types/01_simple_malloc_int.c b/test/runtime_inlined_types/01_simple_malloc_int.c index 913e281e..b65ae3ae 100644 --- a/test/runtime_inlined_types/01_simple_malloc_int.c +++ b/test/runtime_inlined_types/01_simple_malloc_int.c @@ -3,7 +3,7 @@ // RUN: %wrapper-cc -O1 %s -o %s.exe // RUN: %s.exe 2>&1 | %filecheck %s -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 // clang-format on #include @@ -14,4 +14,4 @@ int main(void) { } // CHECK: Allocation type detail (heap, stack, global) -// CHECK-NEXT: 13 : 1 , 0 , 0 , int \ No newline at end of file +// CHECK-NEXT: 13 : 1 , 0 , 0 , int diff --git a/test/runtime_inlined_types/02_simple_malloc_int_multi_tu.c b/test/runtime_inlined_types/02_simple_malloc_int_multi_tu.c index 884df737..e05bc3fd 100644 --- a/test/runtime_inlined_types/02_simple_malloc_int_multi_tu.c +++ b/test/runtime_inlined_types/02_simple_malloc_int_multi_tu.c @@ -9,7 +9,7 @@ // RUN: %wrapper-cc -O1 %s.o %s_1.o -o %s.exe // RUN: %s.exe 2>&1 | %filecheck %s -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 // clang-format on #include @@ -29,4 +29,4 @@ int main(void) { #endif // CHECK: Allocation type detail (heap, stack, global) -// CHECK-NEXT: 13 : 2 , 0 , 0 , int \ No newline at end of file +// CHECK-NEXT: 13 : 2 , 0 , 0 , int diff --git a/test/runtime_inlined_types/03_simple_malloc_struct.c b/test/runtime_inlined_types/03_simple_malloc_struct.c index 112b8a78..f7b71efd 100644 --- a/test/runtime_inlined_types/03_simple_malloc_struct.c +++ b/test/runtime_inlined_types/03_simple_malloc_struct.c @@ -3,7 +3,7 @@ // RUN: %wrapper-cc -O1 %s -o %s.exe // RUN: %s.exe 2>&1 | %filecheck %s -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 // clang-format on #include diff --git a/test/runtime_inlined_types/04_malloc_struct.c b/test/runtime_inlined_types/04_malloc_struct.c index 836560c1..c1b763a6 100644 --- a/test/runtime_inlined_types/04_malloc_struct.c +++ b/test/runtime_inlined_types/04_malloc_struct.c @@ -3,7 +3,7 @@ // RUN: %wrapper-cc -O1 %s -o %s.exe // RUN: %s.exe 2>&1 | %filecheck %s -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 // clang-format on #include diff --git a/test/runtime_inlined_types/05_mpi_test.c b/test/runtime_inlined_types/05_mpi_test.c new file mode 100644 index 00000000..ba7416aa --- /dev/null +++ b/test/runtime_inlined_types/05_mpi_test.c @@ -0,0 +1,16 @@ +// RUN: %wrapper-mpicc -g %s -o %s.exe +// RUN: %mpi-exec -np 1 %s.exe 2>&1 | %filecheck %s + +// REQUIRES: mpicc && !llvm-14 + +#include +void MPI_mock(MPI_Datatype*) { +} + +int main(void) { + MPI_Datatype array_of_types[3] = {MPI_DOUBLE, MPI_DOUBLE, MPI_INT}; + MPI_mock(&array_of_types[0]); + return 0; +} + +// CHECK-NOT: Error diff --git a/test/runtime_inlined_types/06_simple_malloc_int_shared.c b/test/runtime_inlined_types/06_simple_malloc_int_shared.c new file mode 100644 index 00000000..51dd3e7b --- /dev/null +++ b/test/runtime_inlined_types/06_simple_malloc_int_shared.c @@ -0,0 +1,38 @@ +// clang-format off +// RUN: export TYPEART_TYPE_SERIALIZATION=inline +// RUN: %wrapper-cc -fPIC -shared -O1 %s -DTYPEART_TU_ONE -o %s_1.so +// RUN: %wrapper-cc -O1 %s %s_1.so -o %s.exe +// RUN: %s.exe 2>&1 | %filecheck %s + +// REQUIRES: !llvm-14 +// clang-format on + +#include + +#ifdef TYPEART_TU_ONE +struct SharedStruct { + int x; + float y; +}; +void* allocate() { + struct SharedStruct* p = (struct SharedStruct*)malloc(33 * sizeof(struct SharedStruct)); + return (void*)p; +} +#else +struct BinaryStruct { + double x; + float y; +}; +void* allocate(); +int main(void) { + void* lib_type = allocate(); + struct BinaryStruct* p = (struct BinaryStruct*)malloc(42 * sizeof(struct BinaryStruct)); + free(p); + free(lib_type); + return 0; +} +#endif + +// CHECK: Allocation type detail (heap, stack, global) +// CHECK-NEXT: 256 : 1 , 0 , 0 , SharedStruct +// CHECK-NEXT: 257 : 1 , 0 , 0 , BinaryStruct diff --git a/test/typemapping/13_complex.c b/test/typemapping/13_complex.c index 9e5f5416..0c766830 100644 --- a/test/typemapping/13_complex.c +++ b/test/typemapping/13_complex.c @@ -2,7 +2,7 @@ // RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 #include diff --git a/test/typemapping/14_union.c b/test/typemapping/14_union.c index e496b431..b6a9d6d7 100644 --- a/test/typemapping/14_union.c +++ b/test/typemapping/14_union.c @@ -2,7 +2,7 @@ // RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 union UnionTy { float a; diff --git a/test/typemapping/15_wchar.c b/test/typemapping/15_wchar.c index 75ac4682..f89735aa 100644 --- a/test/typemapping/15_wchar.c +++ b/test/typemapping/15_wchar.c @@ -2,7 +2,7 @@ // RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true --typeart-type-serialization=file // RUN: cat %tu_yaml | %filecheck %s -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 #include diff --git a/test/typemapping/16_mpi_dtype.c b/test/typemapping/16_mpi_dtype.c index 182da9d0..31c95ebc 100644 --- a/test/typemapping/16_mpi_dtype.c +++ b/test/typemapping/16_mpi_dtype.c @@ -3,7 +3,7 @@ // RUN: %c-to-llvm %s | %apply-typeart --typeart-type-serialization=inline --typeart-stack=true -S | %filecheck %s --check-prefix inline // RUN: %c-to-llvm %s | %apply-typeart --typeart-type-serialization=hybrid --typeart-stack=true -S | %filecheck %s --check-prefix hybrid -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 // clang-format on struct ompi_struct_data; typedef struct ompi_struct_data* MPI_Datatype; @@ -19,6 +19,6 @@ int main(void) { // CHECK-NOT: Error // CHECK: call {{.*}} @__typeart_alloc_stack(ptr {{.*}}, i32 1, i64 3) -// inline: @_typeart_ptr = weak_odr global %struct._typeart_struct_layout_t +// inline: @_typeart_ptr = linkonce_odr global %struct._typeart_struct_layout_t // inline: call {{.*}} @__typeart_alloc_stack_mty(ptr {{.*}}, ptr {{.*}}, i64 3) // hybrid: call {{.*}} @__typeart_alloc_stack(ptr {{.*}}, i32 1, i64 3) From a29c235ca41bae2a68f2eff08d41680cca626bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Wed, 17 Dec 2025 17:17:00 +0100 Subject: [PATCH 07/14] Global type descriptor split (#180) --- README.md | 11 +- lib/passes/analysis/MemOpVisitor.cpp | 86 +++++++--- lib/passes/instrumentation/TypeIDProvider.cpp | 132 ++++++++++----- lib/runtime/AllocationTracking.cpp | 10 +- lib/runtime/GlobalTypeDefCallbacks.cpp | 157 +++++++++++++++--- lib/runtime/RuntimeData.h | 11 +- test/pass/inline_types/01_simple_malloc_int.c | 4 +- .../inline_types/05_malloc_struct_nested.c | 2 +- .../19_array_cookie_dynamic_size_opaque.cpp | 2 +- .../20_no_array_cookie_lulesh_ad.llin | 2 +- 10 files changed, 302 insertions(+), 115 deletions(-) diff --git a/README.md b/README.md index 9c7f4784..cf56a7c5 100644 --- a/README.md +++ b/README.md @@ -203,13 +203,14 @@ Type serialization for each user-defined type (mode `hybrid`) or *all* types (mo struct GlobalTypeInfo { std::int32_t type_id; const std::uint32_t extent; - const std::uint16_t num_members; - const std::uint16_t flag; + const GlobalTypeInfoData* data; // nullptr for built-ins +}; +struct GlobalTypeInfoData { const char* type_name; - const std::uint16_t* offsets; - const std::uint16_t* array_sizes; + // data : [ num_member, flag, offsets[num_member], array_sizes[num_member] ]: + const std::uint16_t* data; const GlobalTypeInfo** member_types; -}; +} ``` Each type is registered at startup with the TypeART runtime using the callback `void __typeart_register_type(const void* type_ptr);`. This adds the type information to the type database (for user queries) and assigns a unique `type-id`. diff --git a/lib/passes/analysis/MemOpVisitor.cpp b/lib/passes/analysis/MemOpVisitor.cpp index 3abc4f97..7c11a58c 100644 --- a/lib/passes/analysis/MemOpVisitor.cpp +++ b/lib/passes/analysis/MemOpVisitor.cpp @@ -167,33 +167,75 @@ std::optional getSingleUserAs(llvm::Instruction* value) { using MallocGeps = SmallPtrSet; using MallocBcasts = SmallPtrSet; -std::pair collectRelevantMallocUsers(llvm::CallBase& ci) { - auto geps = MallocGeps{}; - auto bcasts = MallocBcasts{}; - for (auto user : ci.users()) { - // Simple case: Pointer is immediately casted - if (auto inst = dyn_cast(user)) { - bcasts.insert(inst); - } - // Pointer is first stored, then loaded and subsequently casted - if (auto storeInst = dyn_cast(user)) { - auto storeAddr = storeInst->getPointerOperand(); - for (auto storeUser : storeAddr->users()) { // TODO: Ensure that load occurs after store? - if (auto loadInst = dyn_cast(storeUser)) { - for (auto loadUser : loadInst->users()) { - if (auto bcastInst = dyn_cast(loadUser)) { - // LOG_MSG(*bcastInst) - bcasts.insert(bcastInst); - } - } +// std::pair collectRelevantMallocUsers(llvm::CallBase& ci) { +// auto geps = MallocGeps{}; +// auto bcasts = MallocBcasts{}; +// for (auto user : ci.users()) { +// // Simple case: Pointer is immediately casted +// if (auto inst = dyn_cast(user)) { +// bcasts.insert(inst); +// } +// // Pointer is first stored, then loaded and subsequently casted +// if (auto storeInst = dyn_cast(user)) { +// auto storeAddr = storeInst->getPointerOperand(); +// if (!(storeAddr == nullptr || llvm::isa(storeAddr))) { +// for (auto storeUser : storeAddr->users()) { // TODO: Ensure that load occurs after store? +// if (auto loadInst = dyn_cast(storeUser)) { +// for (auto loadUser : loadInst->users()) { +// if (auto bcastInst = dyn_cast(loadUser)) { +// // LOG_MSG(*bcastInst) +// bcasts.insert(bcastInst); +// } +// } +// } +// } +// } else { +// LOG_DEBUG("Null, must skip") +// } +// } +// // GEP indicates that an array cookie is added to the allocation. (Fixes #13) +// if (auto gep = dyn_cast(user)) { +// geps.insert(gep); +// } +// } +// return {geps, bcasts}; +// } + +void collect_casts_from_stack(llvm::StoreInst* store_inst, MallocBcasts& out_bcasts) { + auto* slot = store_inst->getPointerOperand(); + + // Guard: Skip invalid or null storage locations + if (llvm::isa(slot)) { + LOG_DEBUG("Skipping null storage"); + return; + } + + for (auto* slot_user : slot->users()) { + // TODO: Ensure that load occurs after store? + if (auto* load_inst = llvm::dyn_cast(slot_user)) { + for (auto* load_user : load_inst->users()) { + if (auto* bit_cast = llvm::dyn_cast(load_user)) { + out_bcasts.insert(bit_cast); } } } - // GEP indicates that an array cookie is added to the allocation. (Fixes #13) - if (auto gep = dyn_cast(user)) { - geps.insert(gep); + } +} + +std::pair collectRelevantMallocUsers(llvm::CallBase& call_inst) { + auto geps = MallocGeps{}; + auto bcasts = MallocBcasts{}; + + for (auto* user : call_inst.users()) { + if (auto* bit_cast = llvm::dyn_cast(user)) { + bcasts.insert(bit_cast); + } else if (auto* gep_inst = llvm::dyn_cast(user)) { + geps.insert(gep_inst); + } else if (auto* store_inst = llvm::dyn_cast(user)) { + collect_casts_from_stack(store_inst, bcasts); } } + return {geps, bcasts}; } diff --git a/lib/passes/instrumentation/TypeIDProvider.cpp b/lib/passes/instrumentation/TypeIDProvider.cpp index b24a46a6..eb3e2a34 100644 --- a/lib/passes/instrumentation/TypeIDProvider.cpp +++ b/lib/passes/instrumentation/TypeIDProvider.cpp @@ -8,6 +8,7 @@ #include "support/ConfigurationBase.h" #include "support/Logger.h" +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include namespace typeart { @@ -72,6 +74,40 @@ inline std::string create_prefixed_name(Args&&... args) { return name; } +namespace detail { +template +T safe_cast(SourceT val) { + // Check if value exceeds the maximum limit of the target type T + // We cast max() to size_t to ensure we are comparing compatible types safely + assert(static_cast(val) <= static_cast(std::numeric_limits::max()) && + "Data loss detected: Value exceeds target type limits!"); + return static_cast(val); +} +} // namespace detail + +template +std::vector get_serialized_members_for(const StructTypeInfo& info) { + using namespace detail; + std::vector dest; + const size_t required_space = info.offsets.size() + info.array_sizes.size() + 2; + dest.reserve(required_space); + + // Layout : [ num_member, flag, offsets...[num_member], array_sizes...[num_member] ] + + dest.push_back(safe_cast(info.num_members)); + dest.push_back(safe_cast(static_cast>(info.flag))); + + for (size_t offset : info.offsets) { + dest.push_back(safe_cast(offset)); + } + + for (size_t size : info.array_sizes) { + dest.push_back(safe_cast(size)); + } + + return dest; +} + } // namespace helper namespace typedb { @@ -151,7 +187,8 @@ enum class IGlobalType : short { member_types, member_count, type_flag, - ptr + ptr, + info_holder }; struct TypeHelper { @@ -181,13 +218,14 @@ struct TypeHelper { } case IGlobalType::name: case IGlobalType::ptr: + case IGlobalType::info_holder: #if LLVM_VERSION_MAJOR < 15 return ir_build_.getInt8PtrTy(); #else return ir_build_.getPtrTy(); #endif } - llvm_unreachable("Should not be reached disk"); + llvm_unreachable("Should not be reached"); } llvm::Constant* get_constant_for(IGlobalType type, size_t value) { @@ -218,6 +256,7 @@ struct GlobalTypeRegistrar { llvm::IRBuilder<> ir_build; GlobalTypeCallback type_callback; llvm::StructType* struct_layout_type_; + llvm::StructType* struct_layout_type_cold_; TypeHelper types_helper; const bool builtin_emit_name{false}; @@ -225,15 +264,15 @@ struct GlobalTypeRegistrar { auto& context = module_->getContext(); struct_layout_type_ = llvm::StructType::create(context, "struct._typeart_struct_layout_t"); struct_layout_type_->setBody({ - types_helper.get_type_for(IGlobalType::type_id), // int type_id - types_helper.get_type_for(IGlobalType::extent), // uint32 extent - types_helper.get_type_for(IGlobalType::num_members), // uint16 num_members - types_helper.get_type_for(IGlobalType::type_flag), // uint16 type_flag + types_helper.get_type_for(IGlobalType::type_id), // uint32 type_id + types_helper.get_type_for(IGlobalType::extent), // uint32 extent + types_helper.get_type_for(IGlobalType::info_holder), + }); + struct_layout_type_cold_ = llvm::StructType::create(context, "struct._typeart_struct_layout_info_t"); + struct_layout_type_cold_->setBody({ types_helper.get_type_for(IGlobalType::name), // const char* name types_helper.get_type_for(IGlobalType::member_offsets), // const uint16* offsets - types_helper.get_type_for(IGlobalType::member_count), // const uint16* count types_helper.get_type_for(IGlobalType::member_types), // const typeart_struct_layout_t** member_types - }); } @@ -274,10 +313,11 @@ struct GlobalTypeRegistrar { return create_global(global_name, array_ty, constant_array); } - llvm::Constant* create_global_array_ptr(const llvm::StringRef name, llvm::ArrayRef values, + template + llvm::Constant* create_global_array_ptr(const llvm::StringRef name, llvm::ArrayRef values, IGlobalType type = IGlobalType::member_offsets) { return create_global_array_from_range(name, values, types_helper.get_type_for(IGlobalType::member_offsets, true), - [&](uint64_t val) { return types_helper.get_constant_for(type, val); }); + [&](const T& val) { return types_helper.get_constant_for(type, val); }); } llvm::Constant* create_global_member_array_ptr(const llvm::StringRef name, llvm::ArrayRef member_types) { @@ -294,51 +334,55 @@ struct GlobalTypeRegistrar { LOG_DEBUG("Type is forward decl " << base_name) } - llvm::Constant* offsets_ptr = create_global_array_ptr(helper::concat("offsets_", link_name), type_struct->offsets); - llvm::Constant* counts_ptr = create_global_array_ptr(helper::concat("counts_", link_name), type_struct->array_sizes, - IGlobalType::member_count); - llvm::Constant* members_ptr = - create_global_member_array_ptr(helper::concat("member_types_", link_name), type_struct->member_types); - const bool is_builtin = type_struct->flag == StructTypeFlag::BUILTIN; const bool emit_name = !is_builtin || builtin_emit_name; - llvm::Constant* name_str_ptr = - emit_name ? create_global_constant_string(link_name, base_name) : types_helper.get_constant_nullptr(); - llvm::GlobalVariable* global_struct = create_global(link_name, struct_layout_type_, nullptr, llvm::GlobalValue::LinkOnceODRLinkage); global_struct->setConstant(false); - std::vector init_fields = { - types_helper.get_constant_for(IGlobalType::type_id, type_struct->type_id), - types_helper.get_constant_for(IGlobalType::extent, type_struct->extent), - types_helper.get_constant_for(IGlobalType::member_count, type_struct->member_types.size()), - types_helper.get_constant_for(IGlobalType::type_flag, static_cast(type_struct->flag)), - name_str_ptr, - offsets_ptr, - counts_ptr, - members_ptr}; - - llvm::Constant* init = llvm::ConstantStruct::get(struct_layout_type_, init_fields); - global_struct->setInitializer(init); + llvm::Comdat* comdat = this->module_->getOrInsertComdat(helper::create_prefixed_name(link_name)); + comdat->setSelectionKind(llvm::Comdat::Any); + global_struct->setComdat(comdat); - { - llvm::Comdat* comdat = this->module_->getOrInsertComdat(helper::create_prefixed_name(link_name)); - comdat->setSelectionKind(llvm::Comdat::Any); - global_struct->setComdat(comdat); + auto add_to_comdat = [&](llvm::Constant* ptr) { + if (auto* global = llvm::dyn_cast_or_null(ptr)) { + global->setComdat(comdat); + } + }; - auto add_to_comdat = [&](llvm::Constant* ptr) { - if (auto* global = llvm::dyn_cast_or_null(ptr)) { - global->setComdat(comdat); + const auto get_info_object = [&]() -> llvm::Constant* { + if (emit_name) { + llvm::Constant* name_str_ptr = create_global_constant_string(link_name, base_name); + const auto info_data = helper::get_serialized_members_for(*type_struct); + llvm::Constant* data_ptr = + create_global_array_ptr(helper::concat("info_data_", link_name), info_data); + llvm::Constant* members_ptr = + create_global_member_array_ptr(helper::concat("member_types_", link_name), type_struct->member_types); + + llvm::GlobalVariable* global_struct_info = + create_global(helper::concat(link_name, "_info"), struct_layout_type_cold_, nullptr); + + std::vector init_fields_cold = {name_str_ptr, data_ptr, members_ptr}; + global_struct_info->setInitializer(llvm::ConstantStruct::get(struct_layout_type_cold_, init_fields_cold)); + + { + add_to_comdat(global_struct_info); + add_to_comdat(data_ptr); + add_to_comdat(members_ptr); + add_to_comdat(name_str_ptr); } - }; - add_to_comdat(offsets_ptr); - add_to_comdat(counts_ptr); - add_to_comdat(members_ptr); - add_to_comdat(name_str_ptr); - } + return global_struct_info; + } + return types_helper.get_constant_nullptr(); + }; + + std::vector init_fields = { + types_helper.get_constant_for(IGlobalType::type_id, type_struct->type_id), + types_helper.get_constant_for(IGlobalType::extent, type_struct->extent), get_info_object()}; + llvm::Constant* init = llvm::ConstantStruct::get(struct_layout_type_, init_fields); + global_struct->setInitializer(init); return global_struct; } diff --git a/lib/runtime/AllocationTracking.cpp b/lib/runtime/AllocationTracking.cpp index c22c2072..279e5272 100644 --- a/lib/runtime/AllocationTracking.cpp +++ b/lib/runtime/AllocationTracking.cpp @@ -292,7 +292,7 @@ void __typeart_leave_scope_omp(int alloca_count) { void __typeart_alloc_mty(const void* addr, const void* info, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - const auto type_id = reinterpret_cast(info)->type_id; + const auto type_id = reinterpret_cast(info)->type_id; auto& rt = typeart::RuntimeSystem::get(); assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); rt.allocation_tracker().onAlloc(addr, type_id, count, retAddr); @@ -301,7 +301,7 @@ void __typeart_alloc_mty(const void* addr, const void* info, size_t count) { void __typeart_alloc_stack_mty(const void* addr, const void* info, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - const auto type_id = reinterpret_cast(info)->type_id; + const auto type_id = reinterpret_cast(info)->type_id; auto& rt = typeart::RuntimeSystem::get(); assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); rt.allocation_tracker().onAllocStack(addr, type_id, count, retAddr); @@ -310,7 +310,7 @@ void __typeart_alloc_stack_mty(const void* addr, const void* info, size_t count) void __typeart_alloc_global_mty(const void* addr, const void* info, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - const auto type_id = reinterpret_cast(info)->type_id; + const auto type_id = reinterpret_cast(info)->type_id; auto& rt = typeart::RuntimeSystem::get(); assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); rt.allocation_tracker().onAllocGlobal(addr, type_id, count, retAddr); @@ -319,7 +319,7 @@ void __typeart_alloc_global_mty(const void* addr, const void* info, size_t count void __typeart_alloc_omp_mty(const void* addr, const void* info, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - const auto type_id = reinterpret_cast(info)->type_id; + const auto type_id = reinterpret_cast(info)->type_id; auto& rt = typeart::RuntimeSystem::get(); assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); rt.allocation_tracker().onAlloc(addr, type_id, count, retAddr); @@ -328,7 +328,7 @@ void __typeart_alloc_omp_mty(const void* addr, const void* info, size_t count) { void __typeart_alloc_stack_omp_mty(const void* addr, const void* info, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); - const auto type_id = reinterpret_cast(info)->type_id; + const auto type_id = reinterpret_cast(info)->type_id; auto& rt = typeart::RuntimeSystem::get(); assert(type_id == rt.type_translator().get_type_id_for(info) && "Type ID of global and lookup must match"); rt.allocation_tracker().onAllocStack(addr, type_id, count, retAddr); diff --git a/lib/runtime/GlobalTypeDefCallbacks.cpp b/lib/runtime/GlobalTypeDefCallbacks.cpp index e59ec73f..c1ab03da 100644 --- a/lib/runtime/GlobalTypeDefCallbacks.cpp +++ b/lib/runtime/GlobalTypeDefCallbacks.cpp @@ -8,12 +8,110 @@ #include "typelib/TypeDatabase.h" #include +#include #include #include #include namespace typeart { +namespace global_types { +struct GlobalTypeInfoData { + private: + const char* name_; + // Layout : [ num_member, flag, offsets...[num_member], array_sizes...[num_member] ] + const std::uint16_t* data_; + const GlobalTypeInfo** member_types_; + + public: + [[nodiscard]] const char* name() const { + assert(name_ != nullptr && "Name should not be NULL"); + return name_; + } + + [[nodiscard]] const GlobalTypeInfo** member_types() const { + return member_types_; + } + + [[nodiscard]] uint16_t num_member() const { + assert(data_ != nullptr && "Data should not be NULL"); + return data_[0]; + } + + [[nodiscard]] uint16_t flag() const { + assert(data_ != nullptr && "Data should not be NULL"); + return data_[1]; + } + + [[nodiscard]] const uint16_t* offsets() const { + return &data_[2]; + } + + [[nodiscard]] const uint16_t* array_sizes() const { + return &data_[2 + num_member()]; + } +}; +} // namespace global_types + +using namespace typeart::global_types; + +class TypeInfoHandle { + public: + explicit TypeInfoHandle(const GlobalTypeInfo* info) : info_(info) { + } + + [[nodiscard]] bool is_valid() const { + return info_ != nullptr; + } + + [[nodiscard]] const GlobalTypeInfo* handle() const { + return info_; + } + + [[nodiscard]] std::int32_t type_id() const { + return info_->type_id; + } + + [[nodiscard]] std::uint32_t extent() const { + return info_->extent; + } + + [[nodiscard]] bool is_builtin() const { + return builtins::BuiltInQuery::is_builtin_type(type_id()); + } + + [[nodiscard]] bool has_metadata() const { + return info_->data != nullptr; + } + + [[nodiscard]] const char* name() const { + return info_->data->name(); + } + + [[nodiscard]] std::uint16_t num_members() const { + return info_->data->num_member(); + } + + [[nodiscard]] std::uint16_t flags() const { + return info_->data->flag(); + } + + [[nodiscard]] TypeInfoHandle get_member_type(size_t index) const { + return TypeInfoHandle(info_->data->member_types()[index]); + } + + [[nodiscard]] std::uint16_t get_offset(size_t index) const { + return info_->data->offsets()[index]; + } + + [[nodiscard]] std::uint16_t get_array_size(size_t index) const { + return info_->data->array_sizes()[index]; + } + + private: + const GlobalTypeInfo* info_; +}; + #define unlikely(x) __builtin_expect(!!(x), 0) #define CONCAT_(x, y) x##y #define CONCAT(x, y) CONCAT_(x, y) @@ -37,9 +135,10 @@ class GlobalTypeTranslator::Impl { int next_type_id(const GlobalTypeInfo* type) { // a fwd_decl and the decl must have the same type_id: { - const auto& struct_list = type_db_.getStructList(); + const auto& struct_list = type_db_.getStructList(); + const auto* const global_type_name = type->data->name(); for (const auto& type_in_db : struct_list) { - if (type_in_db.name == type->name) { + if (type_in_db.name == global_type_name) { return type_in_db.type_id; } } @@ -49,36 +148,40 @@ class GlobalTypeTranslator::Impl { return id; } - int register_t(const GlobalTypeInfo* type) { // NOLINT(misc-no-recursion) - if (unlikely(type == nullptr)) { + int register_t(TypeInfoHandle type_handle) { + if (unlikely(!type_handle.is_valid())) { LOG_ERROR("Type descriptor is NULL, is it a weak extern global due to fwd decl?"); return TYPEART_UNKNOWN_TYPE; } - if (auto element = translator_map_.find(type); element != translator_map_.end()) { + if (auto element = translator_map_.find(type_handle.handle()); element != translator_map_.end()) { return element->second; } - const bool built_in = builtins::BuiltInQuery::is_builtin_type(type->type_id); - if (built_in) { - translator_map_.try_emplace(type, type->type_id); - return type->type_id; + if (type_handle.is_builtin()) { + translator_map_.try_emplace(type_handle.handle(), type_handle.type_id()); + return type_handle.type_id(); } + assert(type_handle.has_metadata() && "Required metadata is NULL"); + StructTypeInfo type_descriptor; - type_descriptor.type_id = next_type_id(type); - type_descriptor.name = type->name; - type_descriptor.extent = type->extent; - type_descriptor.num_members = type->num_members; - type_descriptor.flag = static_cast(type->flag); - - type_descriptor.array_sizes.reserve(type->num_members); - type_descriptor.offsets.reserve(type->num_members); - type_descriptor.member_types.reserve(type->num_members); - for (uint32_t i = 0; i < type->num_members; ++i) { - const auto member_id = register_t(type->member_types[i]); - const auto array_size = type->array_sizes[i]; - const auto offset = type->offsets[i]; + type_descriptor.type_id = next_type_id(type_handle.handle()); + type_descriptor.name = type_handle.name(); + type_descriptor.extent = type_handle.extent(); + type_descriptor.num_members = type_handle.num_members(); + type_descriptor.flag = static_cast(type_handle.flags()); + + const auto member_count = type_descriptor.num_members; + type_descriptor.array_sizes.reserve(member_count); + type_descriptor.offsets.reserve(member_count); + type_descriptor.member_types.reserve(member_count); + + for (size_t i = 0; i < member_count; ++i) { + const auto member_id = register_t(type_handle.get_member_type(i)); + const auto array_size = type_handle.get_array_size(i); + const auto offset = type_handle.get_offset(i); + type_descriptor.array_sizes.emplace_back(array_size); type_descriptor.offsets.emplace_back(offset); type_descriptor.member_types.emplace_back(member_id); @@ -91,14 +194,15 @@ class GlobalTypeTranslator::Impl { LOG_DEBUG(" Extent: " << type_descriptor.extent); LOG_DEBUG(" Num Members: " << type_descriptor.num_members); LOG_DEBUG(" Flag: " << static_cast(type_descriptor.flag)); - for (uint32_t i = 0; i < type->num_members; ++i) { + for (uint32_t i = 0; i < type_descriptor.num_members; ++i) { LOG_DEBUG(" Member[" << i << "]: " << "ID=" << type_db_.getTypeName(type_descriptor.member_types[i]) << ", Offset=" << type_descriptor.offsets[i] << ", ArraySize=" << type_descriptor.array_sizes[i]); } } + type_db_.registerStruct(type_descriptor, not fwd_decl); - translator_map_.try_emplace(type, type_descriptor.type_id); + translator_map_.try_emplace(type_handle.handle(), type_descriptor.type_id); return type_descriptor.type_id; } @@ -110,9 +214,8 @@ GlobalTypeTranslator::GlobalTypeTranslator(TypeDatabase& db) : pImpl(std::make_u GlobalTypeTranslator::~GlobalTypeTranslator() = default; void GlobalTypeTranslator::register_type(const void* type) { - const auto* info_struct = reinterpret_cast(type); - const auto type_id = pImpl->register_t(info_struct); - LOG_DEBUG("Type id reset: " << info_struct->name << " " << info_struct->type_id << " vs. " << type_id) + const auto* info_struct = reinterpret_cast(type); + const auto type_id = pImpl->register_t(TypeInfoHandle{info_struct}); const_cast(info_struct)->type_id = type_id; } diff --git a/lib/runtime/RuntimeData.h b/lib/runtime/RuntimeData.h index 6253655e..e62ef524 100644 --- a/lib/runtime/RuntimeData.h +++ b/lib/runtime/RuntimeData.h @@ -70,17 +70,14 @@ struct PointerInfo final { MemAddr debug{nullptr}; }; +namespace global_types { +struct GlobalTypeInfoData; struct GlobalTypeInfo { std::int32_t type_id; const std::uint32_t extent; - const std::uint16_t num_members; - const std::uint16_t flag; - - const char* name; - const std::uint16_t* offsets; - const std::uint16_t* array_sizes; - const GlobalTypeInfo** member_types; + const GlobalTypeInfoData* data; }; +} // namespace global_types struct RuntimeT { using Stack = std::vector; diff --git a/test/pass/inline_types/01_simple_malloc_int.c b/test/pass/inline_types/01_simple_malloc_int.c index 69c16ab5..9bc4ce2f 100644 --- a/test/pass/inline_types/01_simple_malloc_int.c +++ b/test/pass/inline_types/01_simple_malloc_int.c @@ -5,7 +5,7 @@ // RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=file -S 2>&1 | %filecheck %s --check-prefix FILE -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 // clang-format on #include @@ -17,7 +17,7 @@ void test() { // CHECK-NEXT: Free{{[ ]*}}:{{[ ]*}}0 // CHECK-NEXT: Alloca{{[ ]*}}:{{[ ]*}}0 -// CHECK: %struct._typeart_struct_layout_t = type { i32, i32, i16, i16, ptr, ptr, ptr, ptr } +// CHECK: %struct._typeart_struct_layout_t = type { i32, i32, ptr } // CHECK: [[POINTER:%[0-9a-z]+]] = call noalias{{( align [0-9]+)?}} ptr @malloc // CHECK-NEXT: call void @__typeart_alloc_mty(ptr [[POINTER]], ptr {{.*}}, i64 42) diff --git a/test/pass/inline_types/05_malloc_struct_nested.c b/test/pass/inline_types/05_malloc_struct_nested.c index 36f880c5..2a2855ff 100644 --- a/test/pass/inline_types/05_malloc_struct_nested.c +++ b/test/pass/inline_types/05_malloc_struct_nested.c @@ -23,6 +23,6 @@ int main(void) { // clang-format off // CHECK-DAG: @_typeart_member_types_DataNested = private constant [1 x ptr] [ptr @_typeart_ptr], comdat($_typeart_DataNested) -// CHECK-DAG: @_typeart_DataHolder = linkonce_odr global %struct._typeart_struct_layout_t { i32 256, i32 24, i16 4, i16 1, ptr @_typeart_typename_DataHolder, ptr @_typeart_offsets_DataHolder, ptr @_typeart_counts_DataHolder, ptr @_typeart_member_types_DataHolder }, comdat +// CHECK-DAG: @_typeart_DataHolder = linkonce_odr global %struct._typeart_struct_layout_t { i32 256, i32 24, ptr @_typeart_DataHolder_info }, comdat // CHECK-DAG: @_typeart_member_types_DataHolder = private constant [4 x ptr] [ptr @_typeart_double, ptr @_typeart_float, ptr @_typeart_int, ptr @_typeart_DataNested], comdat($_typeart_DataHolder) // CHECK-DAG: @_typeart_typename_DataHolder = private unnamed_addr constant [11 x i8] c"DataHolder\00", comdat($_typeart_DataHolder), align 1 diff --git a/test/pass/new_delete/19_array_cookie_dynamic_size_opaque.cpp b/test/pass/new_delete/19_array_cookie_dynamic_size_opaque.cpp index 48ede9f1..ca82eaf8 100644 --- a/test/pass/new_delete/19_array_cookie_dynamic_size_opaque.cpp +++ b/test/pass/new_delete/19_array_cookie_dynamic_size_opaque.cpp @@ -1,6 +1,6 @@ // clang-format off // RUN: %cpp-to-llvm %s | %apply-typeart --typeart-type-serialization=file -S 2>&1 | %filecheck %s -// REQUIRES: llvm-18 || llvm-19 +// REQUIRES: !llvm-14 // clang-format on // CHECK: TypeArtPass [Heap] diff --git a/test/pass/new_delete/20_no_array_cookie_lulesh_ad.llin b/test/pass/new_delete/20_no_array_cookie_lulesh_ad.llin index 43d30f97..8497e07c 100644 --- a/test/pass/new_delete/20_no_array_cookie_lulesh_ad.llin +++ b/test/pass/new_delete/20_no_array_cookie_lulesh_ad.llin @@ -1,5 +1,5 @@ ; RUN: %apply-typeart --typeart-type-serialization=file -S < %s | %filecheck %s -; REQUIRES: llvm-18 || llvm-19 +; REQUIRES: !llvm-14 ; llvm-reduce on lulesh.cc with culprit chunk.hpp:allocateData() where pattern is similar to array cookie. From af3caee32cfa70d543451712983e58278df36989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Fri, 19 Dec 2025 12:33:30 +0100 Subject: [PATCH 08/14] Reduce symbol visibility of runtime (#181) --- CMakePresets.json | 3 +- cmake/typeartToolchainOptions.cmake | 3 ++ lib/mpi_interceptor/CMakeLists.txt | 2 +- lib/mpi_interceptor/InterceptorFunctions.h | 30 ++++++++----- lib/runtime/CMakeLists.txt | 40 ++++++++++++++++- lib/runtime/CallbackInterface.h | 32 ++++++------- lib/runtime/RuntimeInterface.h | 46 ++++++++++--------- lib/support/CMakeLists.txt | 51 +++++++++++---------- lib/typelib/CMakeLists.txt | 52 +++++++++++----------- scripts/CMakeLists.txt | 4 +- scripts/typeart-tmpl.sh.in | 6 ++- test/CMakeLists.txt | 1 + test/lit.cfg | 3 ++ test/lit.site.cfg.in | 1 + test/pass/misc/05_make_all_callbacks.c | 2 +- test/runtime/44_typedb.cpp | 2 + test/runtime/47_memory_use.cpp | 2 + 17 files changed, 174 insertions(+), 106 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index 17d0a0da..86cc1818 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -138,7 +138,8 @@ ], "cacheVariables": { "TYPEART_ASAN": "OFF", - "TYPEART_UBSAN": "OFF" + "TYPEART_UBSAN": "OFF", + "TYPEART_CI_RUN": "ON" } }, { diff --git a/cmake/typeartToolchainOptions.cmake b/cmake/typeartToolchainOptions.cmake index ef6a9756..741c9b3e 100644 --- a/cmake/typeartToolchainOptions.cmake +++ b/cmake/typeartToolchainOptions.cmake @@ -94,6 +94,9 @@ mark_as_advanced(TYPEART_CONFIG_DIR_IS_SHARE) option(TYPEART_USE_LEGACY_WRAPPER "Use the old TypeART compiler wrapper" OFF) # mark_as_advanced(TYPEART_USE_NEW_PASSMANAGER) +option(TYPEART_INSTALL_TYPES_LIB "Install types library" OFF) +option(TYPEART_INSTALL_SYSTEM_LIB "Install system library" OFF) + # if(LLVM_VERSION_MAJOR VERSION_GREATER_EQUAL "18") # set(TYPEART_USE_NEW_PASSMANAGER ON CACHE BOOL ON FORCE) # endif() diff --git a/lib/mpi_interceptor/CMakeLists.txt b/lib/mpi_interceptor/CMakeLists.txt index dafa153e..c521026d 100644 --- a/lib/mpi_interceptor/CMakeLists.txt +++ b/lib/mpi_interceptor/CMakeLists.txt @@ -19,7 +19,7 @@ set_property(TARGET ${TYPEART_PREFIX}_MPITool PROPERTY C_STANDARD_REQUIRED TRUE) typeart_target_define_file_basename(${TYPEART_PREFIX}_MPITool) target_include_directories(${TYPEART_PREFIX}_MPITool ${warning_guard} - PUBLIC $ + PUBLIC $ $ $ ) diff --git a/lib/mpi_interceptor/InterceptorFunctions.h b/lib/mpi_interceptor/InterceptorFunctions.h index c782924e..c1ccb341 100644 --- a/lib/mpi_interceptor/InterceptorFunctions.h +++ b/lib/mpi_interceptor/InterceptorFunctions.h @@ -13,7 +13,8 @@ #ifndef TEST_MPI_INTERCEPTOR_INTERCEPTORFUNCTIONS_H_ #define TEST_MPI_INTERCEPTOR_INTERCEPTORFUNCTIONS_H_ -#include "runtime/RuntimeInterface.h" +#include "RuntimeExport.h" +#include "RuntimeInterface.h" #include #include @@ -22,8 +23,9 @@ #include #include -int ta_check_buffer(const char* mpi_name, const void* called_from, const void* buf, int mpi_count, int const_adr); -void ta_print_loc(const void* call_adr); +TYPEART_NO_EXPORT int ta_check_buffer(const char* mpi_name, const void* called_from, const void* buf, int mpi_count, + int const_adr); +TYPEART_NO_EXPORT void ta_print_loc(const void* call_adr); typedef struct CallCounter { _Atomic size_t send; @@ -42,31 +44,34 @@ typedef struct MPISemCounter { static MPICounter mcounter = {0, 0, 0}; -void ta_check_send(const char* name, const void* called_from, const void* sendbuf, int count, MPI_Datatype dtype) { +TYPEART_NO_EXPORT void ta_check_send(const char* name, const void* called_from, const void* sendbuf, int count, + MPI_Datatype dtype) { ++counter.send; ta_check_buffer(name, called_from, sendbuf, count, 1); } -void ta_check_recv(const char* name, const void* called_from, void* recvbuf, int count, MPI_Datatype dtype) { +TYPEART_NO_EXPORT void ta_check_recv(const char* name, const void* called_from, void* recvbuf, int count, + MPI_Datatype dtype) { ++counter.recv; ta_check_buffer(name, called_from, recvbuf, count, 0); } -void ta_check_send_and_recv(const char* name, const void* called_from, const void* sendbuf, int sendcount, - MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype) { +TYPEART_NO_EXPORT void ta_check_send_and_recv(const char* name, const void* called_from, const void* sendbuf, + int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, + MPI_Datatype recvtype) { ++counter.send_recv; ta_check_send(name, called_from, sendbuf, sendcount, sendtype); ta_check_recv(name, called_from, recvbuf, recvcount, recvtype); } -void ta_unsupported_mpi_call(const char* name, const void* called_from) { +TYPEART_NO_EXPORT void ta_unsupported_mpi_call(const char* name, const void* called_from) { ++counter.unsupported; fprintf(stderr, "[Error] The MPI function %s is currently not checked by TypeArt", name); ta_print_loc(called_from); // exit(0); } -const char* ta_get_error_message(typeart_status status) { +TYPEART_NO_EXPORT const char* ta_get_error_message(typeart_status status) { switch (status) { case TYPEART_OK: return "No errors"; @@ -85,7 +90,8 @@ const char* ta_get_error_message(typeart_status status) { } } -int ta_check_buffer(const char* mpi_name, const void* called_from, const void* buf, int mpi_count, int const_adr) { +TYPEART_NO_EXPORT int ta_check_buffer(const char* mpi_name, const void* called_from, const void* buf, int mpi_count, + int const_adr) { if (mpi_count <= 0) { ++mcounter.null_count; return 1; @@ -119,7 +125,7 @@ int ta_check_buffer(const char* mpi_name, const void* called_from, const void* b return 1; } -void ta_print_loc(const void* call_adr) { +TYPEART_NO_EXPORT void ta_print_loc(const void* call_adr) { const char* exe = getenv("TYPEART_EXE_TARGET"); if (exe == NULL || exe[0] == '\0') { return; @@ -138,7 +144,7 @@ void ta_print_loc(const void* call_adr) { } } -void ta_exit() { +TYPEART_NO_EXPORT void ta_exit() { // Called at MPI_Finalize time int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); diff --git a/lib/runtime/CMakeLists.txt b/lib/runtime/CMakeLists.txt index 5d04cfbb..c889e7d7 100644 --- a/lib/runtime/CMakeLists.txt +++ b/lib/runtime/CMakeLists.txt @@ -40,6 +40,39 @@ set_target_properties( ) add_library(typeart::Runtime ALIAS ${TYPEART_PREFIX}_Runtime) +include(GenerateExportHeader) +generate_export_header(${TYPEART_PREFIX}_Runtime + BASE_NAME TYPEART + EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/RuntimeExport.h" +) + +set_target_properties(${TYPEART_PREFIX}_Runtime PROPERTIES + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN ON +) + +if(UNIX AND NOT APPLE) + set(LINKER_MAP_CONTENTS + [=[{ + global: + typeart_*; + __typeart_*; + local: + *; + };]=]) + + set(RUNTIME_MAP_FILE "${CMAKE_CURRENT_BINARY_DIR}/Runtime.map") + file(WRITE "${RUNTIME_MAP_FILE}" "${LINKER_MAP_CONTENTS}") + + target_link_options(${TYPEART_PREFIX}_Runtime PRIVATE + "-Wl,--version-script,${RUNTIME_MAP_FILE}" + ) + + set_target_properties(${TYPEART_PREFIX}_Runtime PROPERTIES + LINK_DEPENDS "${RUNTIME_MAP_FILE}" + ) +endif() + target_link_libraries( ${TYPEART_PREFIX}_Runtime PRIVATE typeart::TypesStatic @@ -59,6 +92,7 @@ target_include_directories( PUBLIC $ $ $ + $ PRIVATE $ $ ) @@ -97,8 +131,10 @@ make_tidy_check(${TYPEART_PREFIX}_Runtime "${RUNTIME_LIB_SOURCES}") set(CONFIG_NAME ${PROJECT_NAME}Runtime) set(TARGETS_EXPORT_NAME ${CONFIG_NAME}Targets) -install(FILES RuntimeInterface.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} +install(FILES + RuntimeInterface.h + "${CMAKE_CURRENT_BINARY_DIR}/RuntimeExport.h" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} ) install( diff --git a/lib/runtime/CallbackInterface.h b/lib/runtime/CallbackInterface.h index 6ca76206..7b5f7490 100644 --- a/lib/runtime/CallbackInterface.h +++ b/lib/runtime/CallbackInterface.h @@ -13,6 +13,8 @@ #ifndef TYPEART_CALLBACKINTERFACE_H #define TYPEART_CALLBACKINTERFACE_H +#include "RuntimeExport.h" + #ifdef __cplusplus #include #else @@ -23,28 +25,28 @@ #ifdef __cplusplus extern "C" { #endif -void __typeart_alloc(const void* addr, int type_id, size_t count); +TYPEART_EXPORT void __typeart_alloc(const void* addr, int type_id, size_t count); -void __typeart_alloc_global(const void* addr, int type_id, size_t count); -void __typeart_free(const void* addr); +TYPEART_EXPORT void __typeart_alloc_global(const void* addr, int type_id, size_t count); +TYPEART_EXPORT void __typeart_free(const void* addr); -void __typeart_alloc_stack(const void* addr, int type_id, size_t count); -void __typeart_leave_scope(int alloca_count); +TYPEART_EXPORT void __typeart_alloc_stack(const void* addr, int type_id, size_t count); +TYPEART_EXPORT void __typeart_leave_scope(int alloca_count); // Called from OpenMP context -void __typeart_alloc_omp(const void* addr, int type_id, size_t count); -void __typeart_free_omp(const void* addr); -void __typeart_alloc_stack_omp(const void* addr, int type_id, size_t count); -void __typeart_leave_scope_omp(int alloca_count); +TYPEART_EXPORT void __typeart_alloc_omp(const void* addr, int type_id, size_t count); +TYPEART_EXPORT void __typeart_free_omp(const void* addr); +TYPEART_EXPORT void __typeart_alloc_stack_omp(const void* addr, int type_id, size_t count); +TYPEART_EXPORT void __typeart_leave_scope_omp(int alloca_count); // Called for inlined type definitions mode -void __typeart_alloc_mty(const void* addr, const void* info, size_t count); -void __typeart_alloc_global_mty(const void* addr, const void* info, size_t count); -void __typeart_alloc_stack_mty(const void* addr, const void* info, size_t count); -void __typeart_register_type(const void* type); +TYPEART_EXPORT void __typeart_alloc_mty(const void* addr, const void* info, size_t count); +TYPEART_EXPORT void __typeart_alloc_global_mty(const void* addr, const void* info, size_t count); +TYPEART_EXPORT void __typeart_alloc_stack_mty(const void* addr, const void* info, size_t count); +TYPEART_EXPORT void __typeart_register_type(const void* type); -void __typeart_alloc_global_mty_omp(const void* addr, const void* info, size_t count); -void __typeart_alloc_stack_mty_omp(const void* addr, const void* info, size_t count); +TYPEART_EXPORT void __typeart_alloc_global_mty_omp(const void* addr, const void* info, size_t count); +TYPEART_EXPORT void __typeart_alloc_stack_mty_omp(const void* addr, const void* info, size_t count); #ifdef __cplusplus } #endif diff --git a/lib/runtime/RuntimeInterface.h b/lib/runtime/RuntimeInterface.h index df01e259..e625ea2c 100644 --- a/lib/runtime/RuntimeInterface.h +++ b/lib/runtime/RuntimeInterface.h @@ -13,6 +13,7 @@ #ifndef TYPEART_RUNTIMEINTERFACE_H #define TYPEART_RUNTIMEINTERFACE_H +#include "RuntimeExport.h" #include "TypeInterface.h" #ifdef __cplusplus @@ -91,7 +92,7 @@ typedef struct typeart_source_loc_t { * - TYPEART_BAD_ALIGNMENT: The given address does not line up with the start of the atomic type at that location. * - TYPEART_INVALID_ID: Encountered unregistered ID during lookup. */ -typeart_status typeart_get_type(const void* addr, typeart_type_info* type_info); +TYPEART_EXPORT typeart_status typeart_get_type(const void* addr, typeart_type_info* type_info); /** * Determines the outermost type and array element count at the given address. @@ -138,8 +139,8 @@ typeart_status typeart_get_type(const void* addr, typeart_type_info* type_info); // typeart_status typeart_get_containing_type(const void* addr, int* type_id, size_t* count, const void** base_address, // size_t* byte_offset); -typeart_status typeart_get_containing_type(const typeart_type_info* type_info, typeart_base_type_info* containing_type, - size_t* byte_offset); +TYPEART_EXPORT typeart_status typeart_get_containing_type(const typeart_type_info* type_info, + typeart_base_type_info* containing_type, size_t* byte_offset); /** * Determines the subtype at the given offset w.r.t. a base address and a corresponding containing type. @@ -179,8 +180,9 @@ typeart_status typeart_get_containing_type(const typeart_type_info* type_info, t * - TYPEART_BAD_OFFSET: The provided offset is invalid. * - TYPEART_ERROR: The typeart_struct_layout is invalid. */ -typeart_status typeart_get_subtype(const typeart_struct_layout* container_layout, const void* base_addr, size_t offset, - typeart_base_type_info* subtype_info, size_t* subtype_byte_offset); +TYPEART_EXPORT typeart_status typeart_get_subtype(const typeart_struct_layout* container_layout, const void* base_addr, + size_t offset, typeart_base_type_info* subtype_info, + size_t* subtype_byte_offset); /** * Returns the stored debug address generated by __builtin_return_address(0). * @@ -191,7 +193,7 @@ typeart_status typeart_get_subtype(const typeart_struct_layout* container_layout * - TYPEART_OK: Success. * - TYPEART_UNKNOWN_ADDRESS: The given address is either not allocated, or was not recorded by the runtime. */ -typeart_status typeart_get_return_address(const void* addr, const void** return_addr); +TYPEART_EXPORT typeart_status typeart_get_return_address(const void* addr, const void** return_addr); /** * Tries to return file, function and line of a memory address from the current process. @@ -207,7 +209,7 @@ typeart_status typeart_get_return_address(const void* addr, const void** return_ * - TYPEART_UNKNOWN_ADDRESS: The given address is either not allocated, or was not recorded by the runtime. * - TYPEART_ERROR: Memory could not be allocated. */ -typeart_status typeart_get_source_location(const void* addr, typeart_source_location* source_loc); +TYPEART_EXPORT typeart_status typeart_get_source_location(const void* addr, typeart_source_location* source_loc); /** * Free previously allocated typeart_source_location. @@ -218,7 +220,7 @@ typeart_status typeart_get_source_location(const void* addr, typeart_source_loca * - TYPEART_OK: Success. * - TYPEART_ERROR: source_loc was NULL. */ -typeart_status typeart_free_source_location(typeart_source_location* source_loc); +TYPEART_EXPORT typeart_status typeart_free_source_location(typeart_source_location* source_loc); /** * Given a type ID, this function provides information about the corresponding struct type. @@ -231,7 +233,7 @@ typeart_status typeart_free_source_location(typeart_source_location* source_loc) * - TYPEART_WRONG_KIND: ID does not correspond to a struct type. * - TYPEART_INVALID_ID: ID is not valid. */ -typeart_status typeart_resolve_type_id(int type_id, typeart_struct_layout* struct_layout); +TYPEART_EXPORT typeart_status typeart_resolve_type_id(int type_id, typeart_struct_layout* struct_layout); /** * Returns the name of the type corresponding to the given type ID. @@ -240,7 +242,7 @@ typeart_status typeart_resolve_type_id(int type_id, typeart_struct_layout* struc * \param[in] type_id The type ID. * \return The name of the type, or "typeart_unknown_struct" if the ID is unknown. */ -const char* typeart_get_type_name(int type_id); +TYPEART_EXPORT const char* typeart_get_type_name(int type_id); /** * Returns true if this is a valid type according to @@ -250,7 +252,7 @@ const char* typeart_get_type_name(int type_id); * \param[in] type_id The type ID. * \return true, false */ -bool typeart_is_valid_type(int type_id); +TYPEART_EXPORT bool typeart_is_valid_type(int type_id); /** * Returns true if the type ID is in the pre-determined reserved range, @@ -259,7 +261,7 @@ bool typeart_is_valid_type(int type_id); * \param[in] type_id The type ID. * \return true, false */ -bool typeart_is_reserved_type(int type_id); +TYPEART_EXPORT bool typeart_is_reserved_type(int type_id); /** * Returns true if the type ID is a built-in type, @@ -268,7 +270,7 @@ bool typeart_is_reserved_type(int type_id); * \param[in] type_id The type ID. * \return true, false */ -bool typeart_is_builtin_type(int type_id); +TYPEART_EXPORT bool typeart_is_builtin_type(int type_id); /** * Returns true if the type ID is a structure type. @@ -278,7 +280,7 @@ bool typeart_is_builtin_type(int type_id); * \param[in] type_id The type ID. * \return true, false */ -bool typeart_is_struct_type(int type_id); +TYPEART_EXPORT bool typeart_is_struct_type(int type_id); /** * Returns true if the type ID is a user-defined structure type @@ -287,7 +289,7 @@ bool typeart_is_struct_type(int type_id); * \param[in] type_id The type ID. * \return true, false */ -bool typeart_is_userdefined_type(int type_id); +TYPEART_EXPORT bool typeart_is_userdefined_type(int type_id); /** * Returns true if the type ID is a (user-defined) union @@ -295,7 +297,7 @@ bool typeart_is_userdefined_type(int type_id); * \param[in] type_id The type ID. * \return true, false */ -bool typeart_is_union(int type_id); +TYPEART_EXPORT bool typeart_is_union(int type_id); /** * Returns true if the type ID is a LLVM SIMD vector type @@ -303,7 +305,7 @@ bool typeart_is_union(int type_id); * \param[in] type_id The type ID. * \return true, false */ -bool typeart_is_vector_type(int type_id); +TYPEART_EXPORT bool typeart_is_vector_type(int type_id); /** * Returns the byte size of the type behind the ID. @@ -311,14 +313,14 @@ bool typeart_is_vector_type(int type_id); * \param[in] type_id The type ID. * \return size in bytes of the type */ -size_t typeart_get_type_size(int type_id); +TYPEART_EXPORT size_t typeart_get_type_size(int type_id); /** * Version string "major.minor(.patch)" of TypeART. * * \return version string */ -const char* typeart_get_project_version(); +TYPEART_EXPORT const char* typeart_get_project_version(); /** * Short Git revision (length: 10) string of TypeART. @@ -327,17 +329,17 @@ const char* typeart_get_project_version(); * * \return revision string */ -const char* typeart_get_git_revision(); +TYPEART_EXPORT const char* typeart_get_git_revision(); /** * Version string "major.minor" of LLVM used to build TypeART. * * \return version string */ -const char* typeart_get_llvm_version(); +TYPEART_EXPORT const char* typeart_get_llvm_version(); #ifdef __cplusplus } #endif -#endif // TYPEART_RUNTIMEINTERFACE_H +#endif /* TYPEART_RUNTIMEINTERFACE_H */ diff --git a/lib/support/CMakeLists.txt b/lib/support/CMakeLists.txt index 61d53d10..7dbb014c 100644 --- a/lib/support/CMakeLists.txt +++ b/lib/support/CMakeLists.txt @@ -32,28 +32,31 @@ if(TYPEART_UBSAN) typeart_target_ubsan_options(${TYPEART_PREFIX}_SystemStatic) endif() -set(CONFIG_NAME ${PROJECT_NAME}System) -set(TARGETS_EXPORT_NAME ${CONFIG_NAME}Targets) -install(FILES Table.h System.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/support -) - -install( - TARGETS ${TYPEART_PREFIX}_SystemStatic - EXPORT ${TARGETS_EXPORT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -) - -install( - EXPORT ${TARGETS_EXPORT_NAME} - NAMESPACE typeart:: - DESTINATION ${TYPEART_INSTALL_CONFIGDIR} -) - -export( - EXPORT ${TARGETS_EXPORT_NAME} - FILE ${CMAKE_BINARY_DIR}/${TARGETS_EXPORT_NAME}.cmake - NAMESPACE typeart:: -) +if(TYPEART_INSTALL_SYSTEM_LIB) + set(CONFIG_NAME ${PROJECT_NAME}System) + set(TARGETS_EXPORT_NAME ${CONFIG_NAME}Targets) + + install(FILES System.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/support + ) + + install( + TARGETS ${TYPEART_PREFIX}_SystemStatic + EXPORT ${TARGETS_EXPORT_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + + install( + EXPORT ${TARGETS_EXPORT_NAME} + NAMESPACE typeart:: + DESTINATION ${TYPEART_INSTALL_CONFIGDIR} + ) + + export( + EXPORT ${TARGETS_EXPORT_NAME} + FILE ${CMAKE_BINARY_DIR}/${TARGETS_EXPORT_NAME}.cmake + NAMESPACE typeart:: + ) +endif() diff --git a/lib/typelib/CMakeLists.txt b/lib/typelib/CMakeLists.txt index 3a926fa1..5ed9da0f 100644 --- a/lib/typelib/CMakeLists.txt +++ b/lib/typelib/CMakeLists.txt @@ -56,31 +56,33 @@ target_include_directories( typeart_target_coverage_options(${TYPEART_PREFIX}_TypesStatic) -set(CONFIG_NAME ${PROJECT_NAME}Types) -set(TARGETS_EXPORT_NAME ${CONFIG_NAME}Targets) - -install(FILES TypeInterface.h TypeDatabase.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} -) - -install( - TARGETS ${TYPEART_PREFIX}_Types ${TYPEART_PREFIX}_TypesStatic - EXPORT ${TARGETS_EXPORT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -) - -install( - EXPORT ${TARGETS_EXPORT_NAME} - NAMESPACE typeart:: - DESTINATION ${TYPEART_INSTALL_CONFIGDIR} -) - -export( - EXPORT ${TARGETS_EXPORT_NAME} - FILE ${CMAKE_BINARY_DIR}/${TARGETS_EXPORT_NAME}.cmake - NAMESPACE typeart:: -) +if(TYPEART_INSTALL_TYPES_LIB) + set(CONFIG_NAME ${PROJECT_NAME}Types) + set(TARGETS_EXPORT_NAME ${CONFIG_NAME}Targets) + + install(FILES TypeInterface.h TypeDatabase.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} + ) + + install( + TARGETS ${TYPEART_PREFIX}_Types ${TYPEART_PREFIX}_TypesStatic + EXPORT ${TARGETS_EXPORT_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + + install( + EXPORT ${TARGETS_EXPORT_NAME} + NAMESPACE typeart:: + DESTINATION ${TYPEART_INSTALL_CONFIGDIR} + ) + + export( + EXPORT ${TARGETS_EXPORT_NAME} + FILE ${CMAKE_BINARY_DIR}/${TARGETS_EXPORT_NAME}.cmake + NAMESPACE typeart:: + ) +endif() #configure_package_config_file( # ${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 02261556..deec4f20 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -23,7 +23,7 @@ function(typeart_configure_script input output) set(TYPEART_RELOCATABLE 1) else() set(TYPEART_INCLUDE_DIRS - "-I${PROJECT_SOURCE_DIR}/lib/typelib -I${PROJECT_SOURCE_DIR}/lib/runtime -I${PROJECT_SOURCE_DIR}/lib/passes/typegen" + "-I${PROJECT_SOURCE_DIR}/lib/typelib -I${PROJECT_SOURCE_DIR}/lib/runtime -I${PROJECT_SOURCE_DIR}/lib/passes/typegen -I${CMAKE_CURRENT_BINARY_DIR}/../lib/runtime" ) if(LIBRARY_OUTPUT_PATH) set(TYPEART_MPI_INTERCEPT_DIR ${LIBRARY_OUTPUT_PATH}) @@ -181,6 +181,8 @@ typeart_configure_coverage_script(llvm-gcov.sh.in llvm-gcov.sh) typeart_configure_script(opt-shim.in opt-shim) +typeart_find_llvm_progs(TYPEART_LLVMCONFIG_COMMAND "llvm-config-${LLVM_VERSION_MAJOR};llvm-config" +HINTS /usr/lib/llvm-${LLVM_VERSION_MAJOR}/bin/) typeart_configure_script(typeart-tmpl.sh.in run.sh OPT ON) typeart_configure_script(typeart-tmpl.sh.in apply.sh diff --git a/scripts/typeart-tmpl.sh.in b/scripts/typeart-tmpl.sh.in index 0d5b88b2..bc353d44 100644 --- a/scripts/typeart-tmpl.sh.in +++ b/scripts/typeart-tmpl.sh.in @@ -132,6 +132,8 @@ function global_init() { readonly typeart_interceptor="@TYPEART_MPI_INTERCEPT_DIR@/@TYPEART_MPI_TOOL@" fi + readonly llvm_sys_libs=$(@TYPEART_LLVMCONFIG_COMMAND@ --system-libs) + readonly typeart_has_interceptor="@TYPEART_HAS_MPI_TOOL@" readonly opt_tool="@TYPEART_OPT@" @@ -140,7 +142,7 @@ function global_init() { readonly typeart_includes="${typeart_include_dir}" readonly typeart_ldflags="-L${typeart_lib_dir}/ \ -Wl,-rpath,${typeart_lib_dir}/ \ - -l$" + -l$ -Wl,--start-group $ $ $ $ ${llvm_sys_libs} -Wl,--end-group" # shellcheck disable=SC2027 typeart_plugin="-load-pass-plugin "${typeart_pass}" -passes=typeart<" @@ -255,7 +257,7 @@ function compile() { function main_link() { more_link_flags="-fPIC" - $compiler ${more_link_flags} ${omp_flags} ${threads_flags} ${typeart_san_flags} ${typeart_ldflags} "${object_file}" -o "${exe_file}" + $compiler ${more_link_flags} ${omp_flags} ${threads_flags} ${typeart_san_flags} "${object_file}" ${typeart_ldflags} -o "${exe_file}" } function execute() { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ab79a884..13ae0faa 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -45,6 +45,7 @@ function(typeart_configure_lit_site input output) pythonize_bool(MPI_C_FOUND TYPEARTPASS_MPI_C) pythonize_bool(MPI_CXX_FOUND TYPEARTPASS_MPI_CXX) + pythonize_bool(TYPEART_CI_RUN TYPEARTPASS_CI_RUN) pythonize_bool(TYPEART_TSAN TYPEARTPASS_TSAN) pythonize_bool(TYPEART_ASAN TYPEARTPASS_ASAN) diff --git a/test/lit.cfg b/test/lit.cfg index b199110f..163bbdcc 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -55,6 +55,9 @@ if config.coverage: if config.has_legacy_wrapper: config.available_features.add('legacywrapper') +if config.is_ci: + config.available_features.add('ci') + profile_files = getattr(config, 'profile_file', None) typeart_base_lib_dir= getattr(config, 'typeart_base_lib_dir', None) typeart_lib_root = getattr(config, 'typeart_lib_dir', None) diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 0cb824f3..7a37f7cc 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -44,6 +44,7 @@ config.python_interp = "@Python3_EXECUTABLE@" config.llvm_version = @LLVM_VERSION_MAJOR@ config.has_legacy_wrapper = @TYPEARTPASS_LEGACY_WRAPPER@ +config.is_ci = @TYPEARTPASS_CI_RUN@ # Let the main config do the real work. config.loaded_site_config = True diff --git a/test/pass/misc/05_make_all_callbacks.c b/test/pass/misc/05_make_all_callbacks.c index b4201d01..7a6b1601 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-stack=true -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm %s -I%runtime_path | %apply-typeart --typeart-stack=true -S 2>&1 | %filecheck %s #include "../../../lib/runtime/CallbackInterface.h" diff --git a/test/runtime/44_typedb.cpp b/test/runtime/44_typedb.cpp index 64bbaed1..f3eb1305 100644 --- a/test/runtime/44_typedb.cpp +++ b/test/runtime/44_typedb.cpp @@ -1,6 +1,8 @@ // RUN: export TYPEART_TYPE_SERIALIZATION=file // RUN: %run %s --compile_flags "-std=c++17" -o -O3 2>&1 | %filecheck %s +// REQUIRES: !ci + // TODO fails for inline/hybrid #include "../../lib/runtime/RuntimeInterface.h" diff --git a/test/runtime/47_memory_use.cpp b/test/runtime/47_memory_use.cpp index 04b6a80c..90205dff 100644 --- a/test/runtime/47_memory_use.cpp +++ b/test/runtime/47_memory_use.cpp @@ -1,5 +1,7 @@ // RUN: %run %s --compile_flags "-std=c++17" 2>&1 | %filecheck %s +// REQUIRES: !ci + #include "../../lib/support/System.h" #include From 8ae76f97da86fe5223db0899aeebd2f4895c7c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sat, 20 Dec 2025 21:26:17 +0100 Subject: [PATCH 09/14] fix: callback defines and missing install rule (#182) --- .github/workflows/basic-ci.yml | 4 ++++ lib/runtime/AllocationTracking.cpp | 4 ++-- lib/typelib/CMakeLists.txt | 6 +++++- test/lit.cfg | 1 + test/pass/misc/05_make_all_callbacks.c | 6 ++++-- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/basic-ci.yml b/.github/workflows/basic-ci.yml index 237686dc..852ff663 100644 --- a/.github/workflows/basic-ci.yml +++ b/.github/workflows/basic-ci.yml @@ -109,6 +109,10 @@ jobs: if: matrix.preset.coverage run: sudo apt-get install lcov + - name: Setup Mold Linker + if: ${{ matrix.platform.llvm-version > 14 }} + uses: rui314/setup-mold@v1 + - name: Setup env run: | sudo ln -f -s /usr/bin/clang-${{ matrix.platform.llvm-version }} /usr/bin/clang diff --git a/lib/runtime/AllocationTracking.cpp b/lib/runtime/AllocationTracking.cpp index 279e5272..7e4764e6 100644 --- a/lib/runtime/AllocationTracking.cpp +++ b/lib/runtime/AllocationTracking.cpp @@ -316,7 +316,7 @@ void __typeart_alloc_global_mty(const void* addr, const void* info, size_t count rt.allocation_tracker().onAllocGlobal(addr, type_id, count, retAddr); } -void __typeart_alloc_omp_mty(const void* addr, const void* info, size_t count) { +void __typeart_alloc_global_mty_omp(const void* addr, const void* info, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); const auto type_id = reinterpret_cast(info)->type_id; @@ -325,7 +325,7 @@ void __typeart_alloc_omp_mty(const void* addr, const void* info, size_t count) { rt.allocation_tracker().onAlloc(addr, type_id, count, retAddr); } -void __typeart_alloc_stack_omp_mty(const void* addr, const void* info, size_t count) { +void __typeart_alloc_stack_mty_omp(const void* addr, const void* info, size_t count) { TYPEART_RUNTIME_GUARD; const void* retAddr = __builtin_return_address(0); const auto type_id = reinterpret_cast(info)->type_id; diff --git a/lib/typelib/CMakeLists.txt b/lib/typelib/CMakeLists.txt index 5ed9da0f..6a0951f1 100644 --- a/lib/typelib/CMakeLists.txt +++ b/lib/typelib/CMakeLists.txt @@ -56,11 +56,15 @@ target_include_directories( typeart_target_coverage_options(${TYPEART_PREFIX}_TypesStatic) +install(FILES TypeInterface.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} +) + if(TYPEART_INSTALL_TYPES_LIB) set(CONFIG_NAME ${PROJECT_NAME}Types) set(TARGETS_EXPORT_NAME ${CONFIG_NAME}Targets) - install(FILES TypeInterface.h TypeDatabase.h + install(FILES TypeDatabase.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} ) diff --git a/test/lit.cfg b/test/lit.cfg index 163bbdcc..fc8dbd45 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -108,6 +108,7 @@ config.substitutions.append(('%filecheck', filecheck)) config.substitutions.append(('%llc', llc)) # Substitutions: executables use "-" separator, variables use underscore +config.substitutions.append(('%base_path', config.typeart_project_dir)) config.substitutions.append(('%base_lib_path', typeart_base_lib_dir)) config.substitutions.append(('%script_path', typeart_script_dir)) config.substitutions.append(('%plugin_path', typeart_lib_root)) diff --git a/test/pass/misc/05_make_all_callbacks.c b/test/pass/misc/05_make_all_callbacks.c index 7a6b1601..4a27a617 100644 --- a/test/pass/misc/05_make_all_callbacks.c +++ b/test/pass/misc/05_make_all_callbacks.c @@ -1,6 +1,7 @@ -// RUN: %c-to-llvm %s -I%runtime_path | %apply-typeart --typeart-stack=true -S 2>&1 | %filecheck %s +// RUN: %c-to-llvm -Wimplicit-function-declaration %s -I%runtime_path -I%base_path/lib/runtime | %apply-typeart --typeart-stack=true -S 2>&1 | \ +// RUN: %filecheck %s -#include "../../../lib/runtime/CallbackInterface.h" +#include "CallbackInterface.h" int main(void) { int count = 0; @@ -32,4 +33,5 @@ int main(void) { return 0; } +// CHECK-NOT: error // CHECK: TypeArtPass [Heap & Stack] \ No newline at end of file From b876949745296ae1f53329d21a7003358069b894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sat, 4 Apr 2026 14:36:24 +0200 Subject: [PATCH 10/14] Fix fwd declared types registering multiple times (#184) --- lib/passes/instrumentation/TypeIDProvider.cpp | 63 ++++++++++++------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/lib/passes/instrumentation/TypeIDProvider.cpp b/lib/passes/instrumentation/TypeIDProvider.cpp index eb3e2a34..c66880ae 100644 --- a/lib/passes/instrumentation/TypeIDProvider.cpp +++ b/lib/passes/instrumentation/TypeIDProvider.cpp @@ -74,6 +74,23 @@ inline std::string create_prefixed_name(Args&&... args) { return name; } +inline bool is_forward_declaration(int type_id, const TypeDatabase& db) { + if (db.isBuiltinType(type_id)) { + return false; + } + const auto* struct_info = db.getStructInfo(type_id); + return struct_info != nullptr && struct_info->flag == StructTypeFlag::FWD_DECL; +} + +inline std::string get_link_name(int type_id, const TypeDatabase& db) { + const auto base_name = db.getTypeName(type_id); + return is_forward_declaration(type_id, db) ? concat(base_name, "_fwd") : base_name; +} + +inline std::string get_prefixed_name(int type_id, const TypeDatabase& db) { + return create_prefixed_name(get_link_name(type_id, db)); +} + namespace detail { template T safe_cast(SourceT val) { @@ -327,8 +344,9 @@ struct GlobalTypeRegistrar { llvm::GlobalVariable* registerTypeStruct(const StructTypeInfo* type_struct) { const auto base_name = type_struct->name; - const bool is_fwd = type_struct->flag == StructTypeFlag::FWD_DECL; - const auto link_name = is_fwd ? helper::concat(base_name, "_fwd") : base_name; + const auto type_id = type_struct->type_id; + const bool is_fwd = helper::is_forward_declaration(type_id, *type_db_); + const auto link_name = helper::get_link_name(type_id, *type_db_); if (is_fwd) { LOG_DEBUG("Type is forward decl " << base_name) @@ -418,25 +436,28 @@ struct GlobalTypeRegistrar { } llvm::Constant* getOrRegister(int type_id) { - const auto name = type_db_->getTypeName(type_id); - LOG_DEBUG(name << " aka " << helper::create_prefixed_name(name)) - return module_->getOrInsertGlobal( - helper::create_prefixed_name(name), struct_layout_type_, [&]() -> llvm::GlobalVariable* { - LOG_DEBUG("Registering << " << type_id << " " << name << " aka " << helper::create_prefixed_name(name)) - const bool is_builtin = type_db_->isBuiltinType(type_id); - if (is_builtin) { - auto* global = registerBuiltin(type_id); - type_callback.insert(global); - return global; - } - auto* global = registerUserDefined(type_id); - const auto fwd_decl = StructTypeFlag::FWD_DECL == type_db_->getStructInfo(type_id)->flag; - if (!fwd_decl) { - LOG_DEBUG("Registering forward declared variable " << *global) - } - type_callback.insert(global); - return global; - }); + const auto base_name = type_db_->getTypeName(type_id); + const auto prefixed_name = helper::get_prefixed_name(type_id, *type_db_); + + LOG_DEBUG(base_name << " aka " << prefixed_name) + + return module_->getOrInsertGlobal(prefixed_name, struct_layout_type_, [&]() -> llvm::GlobalVariable* { + LOG_DEBUG("Registering << " << type_id << " " << base_name << " aka " << prefixed_name) + + if (type_db_->isBuiltinType(type_id)) { + auto* global = registerBuiltin(type_id); + type_callback.insert(global); + return global; + } + + auto* global = registerUserDefined(type_id); + + if (!helper::is_forward_declaration(type_id, *type_db_)) { + LOG_DEBUG("Registering forward declared variable " << *global) + } + type_callback.insert(global); + return global; + }); } }; // namespace typedb } // namespace typedb From 8018716680b7e538c027ece045b075bb7d8b10c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sun, 5 Apr 2026 16:19:07 +0200 Subject: [PATCH 11/14] Support LLVM 22 (#185) --- .github/workflows/basic-ci.yml | 13 +- .github/workflows/ext-ci.yml | 21 +- CMakeLists.txt | 2 +- cmake/modules/llvm-util.cmake | 11 +- externals/abseil/CMakeLists.txt | 2 +- externals/dimeta/CMakeLists.txt | 3 +- lib/mpi_interceptor/wrap.py | 24 +- lib/passes/TypeARTPass.cpp | 251 +++++++++--------- lib/passes/analysis/MemInstFinder.cpp | 14 +- lib/passes/analysis/MemOpVisitor.cpp | 25 +- .../instrumentation/MemOpInstrumentation.cpp | 7 +- lib/runtime/Runtime.cpp | 12 +- lib/runtime/RuntimeData.h | 4 +- lib/runtime/RuntimeInterface.h | 3 - test/runtime/45_default_types.c | 2 +- test/runtime/49_default_types_udef.c | 2 +- 16 files changed, 215 insertions(+), 181 deletions(-) diff --git a/.github/workflows/basic-ci.yml b/.github/workflows/basic-ci.yml index 852ff663..8c420922 100644 --- a/.github/workflows/basic-ci.yml +++ b/.github/workflows/basic-ci.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - @@ -47,7 +47,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: codespell-project/actions-codespell@v2.2 lit-suite: @@ -74,11 +74,12 @@ jobs: - { os: ubuntu-24.04, llvm-version: 19, typeart-typegen-legacy: 0 } - { os: ubuntu-24.04, llvm-version: 20, typeart-typegen-legacy: 0 } - { os: ubuntu-24.04, llvm-version: 21, typeart-typegen-legacy: 0 } + - { os: ubuntu-24.04, llvm-version: 22, typeart-typegen-legacy: 0 } runs-on: ${{ matrix.platform.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: LLVM apt if: ${{ matrix.platform.llvm-version >= 19 }} @@ -141,7 +142,7 @@ jobs: - name: Coveralls (parallel) if: matrix.preset.coverage - uses: coverallsapp/github-action@master + uses: coverallsapp/github-action@v2.3.6 with: github-token: ${{ secrets.GITHUB_TOKEN }} path-to-lcov: build/typeart.coverage @@ -150,10 +151,10 @@ jobs: finish-coverage: needs: lit-suite - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Coveralls Finished - uses: coverallsapp/github-action@master + uses: coverallsapp/github-action@v2.3.6 with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true \ No newline at end of file diff --git a/.github/workflows/ext-ci.yml b/.github/workflows/ext-ci.yml index 45e37ea5..47e24d5e 100644 --- a/.github/workflows/ext-ci.yml +++ b/.github/workflows/ext-ci.yml @@ -24,14 +24,15 @@ jobs: - { os: ubuntu-24.04, llvm-version: 19 } - { os: ubuntu-24.04, llvm-version: 20 } - { os: ubuntu-24.04, llvm-version: 21 } + - { os: ubuntu-24.04, llvm-version: 22 } runs-on: ${{ matrix.platform.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Checkout test-bench - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: repository: tudasc/typeart-bench ssh-key: ${{ secrets.AUTH_SSH_CI_EXT }} @@ -101,7 +102,7 @@ jobs: mv test-bench/artifact-${{ matrix.platform.llvm-version }}/* artifact - name: Upload test-bench artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: typeart-ci-ext-${{ matrix.platform.llvm-version }}-${{ matrix.preset.name }} path: artifact @@ -119,14 +120,15 @@ jobs: - { os: ubuntu-24.04, llvm-version: 19 } - { os: ubuntu-24.04, llvm-version: 20 } - { os: ubuntu-24.04, llvm-version: 21 } + - { os: ubuntu-24.04, llvm-version: 22 } runs-on: ${{ matrix.platform.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Checkout AD test-bench - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: repository: ahueck/typeart-ad-benchmarks ssh-key: ${{ secrets.AUTH_SSH_CI_EXT_AD }} @@ -181,7 +183,7 @@ jobs: mv ad-test-bench/artifact-${{ matrix.platform.llvm-version }}/* artifact - name: Upload AD test-bench artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: typeart-ci-ext-ad-${{ matrix.platform.llvm-version }}-${{ matrix.preset.name }} path: artifact @@ -202,14 +204,15 @@ jobs: - { os: ubuntu-24.04, llvm-version: 19 } - { os: ubuntu-24.04, llvm-version: 20 } - { os: ubuntu-24.04, llvm-version: 21 } + - { os: ubuntu-24.04, llvm-version: 22 } runs-on: ${{ matrix.platform.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Checkout OMP test-bench - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: repository: tudasc/typeart-bench ssh-key: ${{ secrets.AUTH_SSH_CI_EXT }} @@ -271,7 +274,7 @@ jobs: mv omp-test-bench/artifact-${{ matrix.platform.llvm-version }}/* artifact - name: Upload omp-test-bench artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: typeart-ci-ext-omp-${{ matrix.platform.llvm-version }}-${{ matrix.preset.name }} path: artifact diff --git a/CMakeLists.txt b/CMakeLists.txt index 09fc3856..623502e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ endif() if(TYPEART_IS_TOP_LEVEL) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - set(CMAKE_VERBOSE_MAKEFILE ON) + # set(CMAKE_VERBOSE_MAKEFILE ON) endif() set(CMAKE_CXX_STANDARD 17) diff --git a/cmake/modules/llvm-util.cmake b/cmake/modules/llvm-util.cmake index 21eb2444..1a67ab33 100644 --- a/cmake/modules/llvm-util.cmake +++ b/cmake/modules/llvm-util.cmake @@ -40,9 +40,18 @@ function(typeart_make_llvm_module name sources) typeart_target_define_file_basename(${name}) + set(LLVM_DEFINITIONS_LIST "${LLVM_DEFINITIONS}") + separate_arguments(LLVM_DEFINITIONS_LIST) + + set(CLEAN_LLVM_DEFINITIONS "") + foreach(definition ${LLVM_DEFINITIONS_LIST}) + string(REGEX REPLACE "^-D" "" clean_definition ${definition}) + list(APPEND CLEAN_LLVM_DEFINITIONS ${clean_definition}) + endforeach() + target_compile_definitions(${name} PRIVATE - ${LLVM_DEFINITIONS} + ${CLEAN_LLVM_DEFINITIONS} ) make_tidy_check(${name} diff --git a/externals/abseil/CMakeLists.txt b/externals/abseil/CMakeLists.txt index c47f6890..fe914405 100644 --- a/externals/abseil/CMakeLists.txt +++ b/externals/abseil/CMakeLists.txt @@ -3,7 +3,7 @@ set(ABSL_PROPAGATE_CXX_STD ON) FetchContent_Declare( cpp-abseil GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git - GIT_TAG 20250814.1 + GIT_TAG 20250814.2 GIT_SHALLOW 1 ) diff --git a/externals/dimeta/CMakeLists.txt b/externals/dimeta/CMakeLists.txt index 6dcdf0bd..85d23e22 100644 --- a/externals/dimeta/CMakeLists.txt +++ b/externals/dimeta/CMakeLists.txt @@ -1,7 +1,7 @@ FetchContent_Declare( llvm-dimeta GIT_REPOSITORY https://github.com/ahueck/llvm-dimeta - GIT_TAG v0.4.0 + GIT_TAG v0.5.1 GIT_SHALLOW 1 ) @@ -19,6 +19,7 @@ mark_as_advanced( DIMETA_ENABLE_COVERAGE DIMETA_TEST_CONFIG DIMETA_LOG_LEVEL + DIMETA_ENABLE_FLANG FETCHCONTENT_UPDATES_DISCONNECTED_LLVM-DIMETA FETCHCONTENT_SOURCE_DIR_LLVM-DIMETA ) diff --git a/lib/mpi_interceptor/wrap.py b/lib/mpi_interceptor/wrap.py index 6aa6a3af..d98996e0 100644 --- a/lib/mpi_interceptor/wrap.py +++ b/lib/mpi_interceptor/wrap.py @@ -85,21 +85,21 @@ # Regular expressions for start and end of declarations in mpi.h. These are # used to get the declaration strings out for parsing with formal_re below. -begin_decl_re = re.compile("(" + "|".join(rtypes) + ")\s+(MPI_\w+)\s*\(") +begin_decl_re = re.compile(r"(" + "|".join(rtypes) + r")\s+(MPI_\w+)\s*\(") exclude_re = re.compile("|".join(exclude_strings)) -end_decl_re = re.compile("\).*\;") +end_decl_re = re.compile(r"\).*\;") # Regular Expression for splitting up args. Matching against this # returns three groups: type info, arg name, and array info formal_re = re.compile( - "\s*(" + # Start type - "(?:const)?\s*" + # Initial const - "\w+" # Type name (note: doesn't handle 'long long', etc. right now) - ")\s*(" + # End type, begin pointers - "(?:\s*\*(?:\s*const)?)*" + # Look for 0 or more pointers with optional 'const' - ")\s*" # End pointers - "(?:(\w+)\s*)?" + # Argument name. Optional. - "(\[.*\])?\s*$" # Array type. Also optional. Works for multidimensions b/c it's greedy. + r"\s*(" + # Start type + r"(?:const)?\s*" + # Initial const + r"\w+" # Type name (note: doesn't handle 'long long', etc. right now) + r")\s*(" + # End type, begin pointers + r"(?:\s*\*(?:\s*const)?)*" + # Look for 0 or more pointers with optional 'const' + r")\s*" # End pointers + r"(?:(\w+)\s*)?" + # Argument name. Optional. + r"(\[.*\])?\s*$" # Array type. Also optional. Works for multidimensions b/c it's greedy. ) # Fortran wrapper suffix @@ -724,12 +724,12 @@ def cFormal(self): def castType(self): arr = self.array or '' pointers = self.pointers or '' - if re.search('\[\s*\]', arr): + if re.search(r'\[\s*\]', arr): if arr.count('[') > 1: pointers += '(*)' # need extra parens for, e.g., int[][3] -> int(*)[3] else: pointers += '*' # justa single array; can pass pointer. - arr = re.sub('\[\s*\]', '', arr) + arr = re.sub(r'\[\s*\]', '', arr) return "%s%s%s" % (self.type, pointers, arr) def __str__(self): diff --git a/lib/passes/TypeARTPass.cpp b/lib/passes/TypeARTPass.cpp index 3d7a8b3c..7780f43b 100644 --- a/lib/passes/TypeARTPass.cpp +++ b/lib/passes/TypeARTPass.cpp @@ -44,7 +44,11 @@ #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include "llvm/Passes/PassBuilder.h" +#if LLVM_VERSION_MAJOR < 22 #include "llvm/Passes/PassPlugin.h" +#else +#include "llvm/Plugins/PassPlugin.h" +#endif #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" @@ -212,156 +216,161 @@ class TypeArtPass : public llvm::PassInfoMixin { functions = declare_instrumentation_functions(m, configuration()); } - void printStats(llvm::raw_ostream& out) { - const auto scope_exit_cleanup_counter = llvm::make_scope_exit([&]() { - NumInstrumentedAlloca = 0; - NumInstrumentedFrees = 0; - NumInstrumentedGlobal = 0; - NumInstrumentedMallocs = 0; - }); - meminst_finder->printStats(out); - - const auto get_ta_mode = [&]() { - const bool heap = configuration()[config::ConfigStdArgs::heap]; - const bool stack = configuration()[config::ConfigStdArgs::stack]; - const bool global = configuration()[config::ConfigStdArgs::global]; - - if (heap) { - if (stack) { - return " [Heap & Stack]"; - } - return " [Heap]"; - } + void printStats(llvm::raw_ostream& out){ +#if LLVM_VERSION_MAJOR < 22 + const auto scope_exit_cleanup_counter = llvm::make_scope_exit([&]() { +#else + llvm::scope_exit scope_exit_cleanup_counter([&]() { +#endif + NumInstrumentedAlloca = 0; + NumInstrumentedFrees = 0; + NumInstrumentedGlobal = 0; + NumInstrumentedMallocs = 0; + }); + meminst_finder->printStats(out); - if (stack) { - return " [Stack]"; - } + const auto get_ta_mode = [&]() { + const bool heap = configuration()[config::ConfigStdArgs::heap]; + const bool stack = configuration()[config::ConfigStdArgs::stack]; + const bool global = configuration()[config::ConfigStdArgs::global]; - if (global) { - return " [Global]"; + if (heap) { + if (stack) { + return " [Heap & Stack]"; } + return " [Heap]"; + } - LOG_ERROR("Did not find heap or stack, or combination thereof!"); - assert((heap || stack || global) && "Needs stack, heap, global or combination thereof"); - return " [Unknown]"; - }; + if (stack) { + return " [Stack]"; + } - Table stats("TypeArtPass"); - stats.wrap_header_ = true; - stats.title_ += get_ta_mode(); - stats.put(Row::make("Malloc", NumInstrumentedMallocs.getValue())); - stats.put(Row::make("Free", NumInstrumentedFrees.getValue())); - stats.put(Row::make("Alloca", NumInstrumentedAlloca.getValue())); - stats.put(Row::make("Global", NumInstrumentedGlobal.getValue())); - - std::ostringstream stream; - stats.print(stream); - out << stream.str(); - } + if (global) { + return " [Global]"; + } - llvm::PreservedAnalyses run(llvm::Module& m, llvm::ModuleAnalysisManager&) { - bool changed{false}; - changed |= doInitialization(m); - const bool heap = configuration()[config::ConfigStdArgs::heap]; // Must happen after doInit - dump_module(m, heap ? util::module::ModulePhase::kBase : util::module::ModulePhase::kOpt); - changed |= runOnModule(m); - dump_module(m, heap ? util::module::ModulePhase::kHeap : util::module::ModulePhase::kStack); - changed |= doFinalization(); - return changed ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all(); - } + LOG_ERROR("Did not find heap or stack, or combination thereof!"); + assert((heap || stack || global) && "Needs stack, heap, global or combination thereof"); + return " [Unknown]"; + }; - bool runOnModule(llvm::Module& m) { - meminst_finder->runOnModule(m); - const bool instrument_global = configuration()[config::ConfigStdArgs::global]; - bool globals_were_instrumented{false}; - if (instrument_global) { - // declareInstrumentationFunctions(m); - - const auto& globalsList = meminst_finder->getModuleGlobals(); - if (!globalsList.empty()) { - const auto global_count = instrumentation_context->handleGlobal(globalsList); - NumInstrumentedGlobal += global_count; - globals_were_instrumented = global_count > 0; - } - } + Table stats("TypeArtPass"); + stats.wrap_header_ = true; + stats.title_ += get_ta_mode(); + stats.put(Row::make("Malloc", NumInstrumentedMallocs.getValue())); + stats.put(Row::make("Free", NumInstrumentedFrees.getValue())); + stats.put(Row::make("Alloca", NumInstrumentedAlloca.getValue())); + stats.put(Row::make("Global", NumInstrumentedGlobal.getValue())); + + std::ostringstream stream; + stats.print(stream); + out << stream.str(); +} - llvm::DenseSet tor_funcs; - { - const auto collect_funcs = [&tor_funcs](const auto* constant) -> bool { - if (llvm::isa(constant)) { - tor_funcs.insert(constant); - } - return false; - }; +llvm::PreservedAnalyses +run(llvm::Module& m, llvm::ModuleAnalysisManager&) { + bool changed{false}; + changed |= doInitialization(m); + const bool heap = configuration()[config::ConfigStdArgs::heap]; // Must happen after doInit + dump_module(m, heap ? util::module::ModulePhase::kBase : util::module::ModulePhase::kOpt); + changed |= runOnModule(m); + dump_module(m, heap ? util::module::ModulePhase::kHeap : util::module::ModulePhase::kStack); + changed |= doFinalization(); + return changed ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all(); +} - util::for_each_cdtor("llvm.global_ctors", m, collect_funcs); - util::for_each_cdtor("llvm.global_dtors", m, collect_funcs); +bool runOnModule(llvm::Module& m) { + meminst_finder->runOnModule(m); + const bool instrument_global = configuration()[config::ConfigStdArgs::global]; + bool globals_were_instrumented{false}; + if (instrument_global) { + // declareInstrumentationFunctions(m); + + const auto& globalsList = meminst_finder->getModuleGlobals(); + if (!globalsList.empty()) { + const auto global_count = instrumentation_context->handleGlobal(globalsList); + NumInstrumentedGlobal += global_count; + globals_were_instrumented = global_count > 0; } + } + + llvm::DenseSet tor_funcs; + { + const auto collect_funcs = [&tor_funcs](const auto* constant) -> bool { + if (llvm::isa(constant)) { + tor_funcs.insert(constant); + } + return false; + }; - const auto instrumented_function = llvm::count_if(m.functions(), [&](auto& f) { - if (tor_funcs.contains(&f)) { - LOG_DEBUG("Function is in LLVM global ctor or dtor " << f.getName()) - return false; - } - return runOnFunc(f); - }) > 0; - return instrumented_function || globals_were_instrumented; + util::for_each_cdtor("llvm.global_ctors", m, collect_funcs); + util::for_each_cdtor("llvm.global_dtors", m, collect_funcs); } - bool runOnFunc(llvm::Function& f) { - using namespace typeart; + const auto instrumented_function = llvm::count_if(m.functions(), [&](auto& f) { + if (tor_funcs.contains(&f)) { + LOG_DEBUG("Function is in LLVM global ctor or dtor " << f.getName()) + return false; + } + return runOnFunc(f); + }) > 0; + return instrumented_function || globals_were_instrumented; +} - if (f.isDeclaration() || util::starts_with_any_of(f.getName(), "__typeart", "typeart", "__sanitizer", "__tysan")) { - return false; - } +bool runOnFunc(llvm::Function& f) { + using namespace typeart; - if (!meminst_finder->hasFunctionData(f)) { - LOG_WARNING("No allocation data could be retrieved for function: " << f.getName()); - return false; - } + if (f.isDeclaration() || util::starts_with_any_of(f.getName(), "__typeart", "typeart", "__sanitizer", "__tysan")) { + return false; + } + + if (!meminst_finder->hasFunctionData(f)) { + LOG_WARNING("No allocation data could be retrieved for function: " << f.getName()); + return false; + } - LOG_DEBUG("Running on function: " << f.getName()) + LOG_DEBUG("Running on function: " << f.getName()) - // FIXME this is required when "PassManagerBuilder::EP_OptimizerLast" is used as the function (constant) pointer are - // nullpointer/invalidated - // declareInstrumentationFunctions(*f.getParent()); + // FIXME this is required when "PassManagerBuilder::EP_OptimizerLast" is used as the function (constant) pointer are + // nullpointer/invalidated + // declareInstrumentationFunctions(*f.getParent()); - bool mod{false}; + bool mod{false}; // auto& c = f.getContext(); #if LLVM_VERSION_MAJOR > 19 - DataLayout dl(f.getParent()->getDataLayout()); + DataLayout dl(f.getParent()->getDataLayout()); #else - DataLayout dl(f.getParent()); + DataLayout dl(f.getParent()); #endif - const auto& fData = meminst_finder->getFunctionData(f); - const auto& mallocs = fData.mallocs; - const auto& allocas = fData.allocas; - const auto& frees = fData.frees; - - const bool instrument_heap = configuration()[config::ConfigStdArgs::heap]; - const bool instrument_stack = configuration()[config::ConfigStdArgs::stack]; + const auto& fData = meminst_finder->getFunctionData(f); + const auto& mallocs = fData.mallocs; + const auto& allocas = fData.allocas; + const auto& frees = fData.frees; - if (instrument_heap) { - // instrument collected calls of bb: - const auto heap_count = instrumentation_context->handleHeap(mallocs); - const auto free_count = instrumentation_context->handleFree(frees); + const bool instrument_heap = configuration()[config::ConfigStdArgs::heap]; + const bool instrument_stack = configuration()[config::ConfigStdArgs::stack]; - NumInstrumentedMallocs += heap_count; - NumInstrumentedFrees += free_count; + if (instrument_heap) { + // instrument collected calls of bb: + const auto heap_count = instrumentation_context->handleHeap(mallocs); + const auto free_count = instrumentation_context->handleFree(frees); - mod |= heap_count > 0 || free_count > 0; - } + NumInstrumentedMallocs += heap_count; + NumInstrumentedFrees += free_count; - if (instrument_stack) { - const auto stack_count = instrumentation_context->handleStack(allocas); - NumInstrumentedAlloca += stack_count; - mod |= stack_count > 0; - } + mod |= heap_count > 0 || free_count > 0; + } - return mod; + if (instrument_stack) { + const auto stack_count = instrumentation_context->handleStack(allocas); + NumInstrumentedAlloca += stack_count; + mod |= stack_count > 0; } -}; + + return mod; +} +}; // namespace typeart::pass class LegacyTypeArtPass : public llvm::ModulePass { private: diff --git a/lib/passes/analysis/MemInstFinder.cpp b/lib/passes/analysis/MemInstFinder.cpp index 1260db13..1de001e3 100644 --- a/lib/passes/analysis/MemInstFinder.cpp +++ b/lib/passes/analysis/MemInstFinder.cpp @@ -391,7 +391,11 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) { } // namespace typeart void MemInstFinderPass::printStats(llvm::raw_ostream& out) const { +#if LLVM_VERSION_MAJOR < 22 const auto scope_exit_cleanup_counter = llvm::make_scope_exit([&]() { +#else + llvm::scope_exit scope_exit_cleanup_counter([&]() { +#endif NumDetectedAllocs = 0; NumFilteredNonArrayAllocs = 0; NumFilteredMallocAllocs = 0; @@ -401,11 +405,11 @@ void MemInstFinderPass::printStats(llvm::raw_ostream& out) const { NumFilteredGlobals = 0; NumDetectedGlobals = 0; }); - auto all_stack = double(NumDetectedAllocs); - auto nonarray_stack = double(NumFilteredNonArrayAllocs); - auto malloc_alloc_stack = double(NumFilteredMallocAllocs); - auto call_filter_stack = double(NumCallFilteredAllocs); - auto filter_pointer_stack = double(NumFilteredPointerAllocs); + auto all_stack = double(NumDetectedAllocs); + auto nonarray_stack = double(NumFilteredNonArrayAllocs); + auto malloc_alloc_stack = double(NumFilteredMallocAllocs); + auto call_filter_stack = double(NumCallFilteredAllocs); + auto filter_pointer_stack = double(NumFilteredPointerAllocs); const auto call_filter_stack_p = (call_filter_stack / diff --git a/lib/passes/analysis/MemOpVisitor.cpp b/lib/passes/analysis/MemOpVisitor.cpp index 7c11a58c..0e8e4294 100644 --- a/lib/passes/analysis/MemOpVisitor.cpp +++ b/lib/passes/analysis/MemOpVisitor.cpp @@ -374,19 +374,26 @@ void MemOpVisitor::visitAllocaInst(llvm::AllocaInst& ai) { } void MemOpVisitor::visitIntrinsicInst(llvm::IntrinsicInst& inst) { - if (inst.getIntrinsicID() == Intrinsic::lifetime_start) { -#if LLVM_VERSION_MAJOR >= 12 - auto alloca = llvm::findAllocaForValue(inst.getOperand(1)); + if (inst.getIntrinsicID() != Intrinsic::lifetime_start) { + return; + } + AllocaInst* alloca{nullptr}; +#if LLVM_VERSION_MAJOR > 21 + auto* operand = inst.getArgOperand(0); + alloca = llvm::findAllocaForValue(operand); +#elif LLVM_VERSION_MAJOR >= 12 + auto* operand = inst.getOperand(1); + alloca = llvm::findAllocaForValue(operand); #else - DenseMap alloca_for_value; - auto* alloca = llvm::findAllocaForValue(inst.getOperand(1), alloca_for_value); + auto* operand = inst.getOperand(1); + DenseMap alloca_for_value; + alloca = llvm::findAllocaForValue(operand, alloca_for_value); #endif - if (alloca != nullptr) { - lifetime_starts.emplace_back(&inst, alloca); - } + + if (alloca != nullptr) { + lifetime_starts.emplace_back(&inst, alloca); } } - void MemOpVisitor::clear() { allocas.clear(); mallocs.clear(); diff --git a/lib/passes/instrumentation/MemOpInstrumentation.cpp b/lib/passes/instrumentation/MemOpInstrumentation.cpp index b50f1fc2..ba64511e 100644 --- a/lib/passes/instrumentation/MemOpInstrumentation.cpp +++ b/lib/passes/instrumentation/MemOpInstrumentation.cpp @@ -233,7 +233,12 @@ InstrCount MemOpInstrumentation::instrumentStack(const StackArgList& stack) { } else { for (auto* lifetime_s : lifetime_starts) { IRBuilder<> IRB(lifetime_s->getNextNode()); - instrument_stack(IRB, lifetime_s->getOperand(1), lifetime_s->getNextNode()); +#if LLVM_VERSION_MAJOR < 22 + auto ptr = lifetime_s->getOperand(1); +#else + auto ptr = lifetime_s->getArgOperand(0); +#endif + instrument_stack(IRB, ptr, lifetime_s->getNextNode()); } } } diff --git a/lib/runtime/Runtime.cpp b/lib/runtime/Runtime.cpp index 441f41cc..e53bf9dd 100644 --- a/lib/runtime/Runtime.cpp +++ b/lib/runtime/Runtime.cpp @@ -90,12 +90,10 @@ RuntimeSystem::RuntimeSystem() } } else { if (!loadTypes(defaultTypeFileName, error)) { - LOG_WARNING( - "No type file with default name \"" - << defaultTypeFileName - << "\" in current directory. Using default built-in types only. To specify a different file, edit the " - "TYPEART_TYPE_FILE environment variable. Reason: " - << error.message()); + LOG_DEBUG("No type file with default name \"" + << defaultTypeFileName + << "\" in current directory. Using default built-in types only. To specify a different file, edit the " + << config::EnvironmentStdArgs::types << " environment variable. Reason: " << error.message()); } } @@ -105,7 +103,7 @@ RuntimeSystem::RuntimeSystem() ss << structInfo.name << ", "; } recorder.incUDefTypes(typeList.size()); - LOG_INFO("Recorded types: " << ss.str()); + LOG_DEBUG("Recorded types: " << ss.str()); rtScopeInit.reset(); } diff --git a/lib/runtime/RuntimeData.h b/lib/runtime/RuntimeData.h index e62ef524..b3b3f41f 100644 --- a/lib/runtime/RuntimeData.h +++ b/lib/runtime/RuntimeData.h @@ -51,8 +51,8 @@ #endif #if defined(__has_feature) -#if __has_feature(address_sanitizer) -#define __SANITIZE_ADDRESS__ +#if __has_feature(address_sanitizer) && !defined(__SANITIZE_ADDRESS__) +#define __SANITIZE_ADDRESS__ 1 #endif #endif diff --git a/lib/runtime/RuntimeInterface.h b/lib/runtime/RuntimeInterface.h index e625ea2c..e6190b34 100644 --- a/lib/runtime/RuntimeInterface.h +++ b/lib/runtime/RuntimeInterface.h @@ -136,9 +136,6 @@ TYPEART_EXPORT typeart_status typeart_get_type(const void* addr, typeart_type_in * - 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* byte_offset); - TYPEART_EXPORT typeart_status typeart_get_containing_type(const typeart_type_info* type_info, typeart_base_type_info* containing_type, size_t* byte_offset); diff --git a/test/runtime/45_default_types.c b/test/runtime/45_default_types.c index 82d44d7c..24b87721 100644 --- a/test/runtime/45_default_types.c +++ b/test/runtime/45_default_types.c @@ -5,7 +5,7 @@ int main(int argc, char** argv) { const int n = 42; // CHECK: [Trace] TypeART Runtime Trace - // CHECK: [Warning]{{.*}}No type file with default name + // CHECK: [Debug]{{.*}}No type file with default name // CHECK: [Trace] Alloc 0x{{.*}} {{(int8_t|char)}} 1 42 char* a = malloc(n * sizeof(char)); // CHECK: [Trace] Free 0x{{.*}} diff --git a/test/runtime/49_default_types_udef.c b/test/runtime/49_default_types_udef.c index cd35a0e0..f22804e5 100644 --- a/test/runtime/49_default_types_udef.c +++ b/test/runtime/49_default_types_udef.c @@ -9,7 +9,7 @@ struct Datastruct { int main(int argc, char** argv) { // CHECK: [Trace] TypeART Runtime Trace - // CHECK: [Warning]{{.*}}No type file with default name + // CHECK: [Debug]{{.*}}No type file with default name // CHECK: [Trace] Alloc [[POINTER:0x[0-9a-fA-F]+]] 256 typeart_unknown_struct 0 1 struct Datastruct data = {0}; From d9afbfc36a2fb2dcb23d55e8e3a84cc9c500eca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sun, 5 Apr 2026 16:34:26 +0200 Subject: [PATCH 12/14] License header --- LICENSE.txt | 2 +- lib/mpi_interceptor/InterceptorFunctions.h | 2 +- lib/mpi_interceptor/mpi_interceptor_tmpl.impl | 2 +- lib/passes/Commandline.cpp | 2 +- lib/passes/Commandline.h | 2 +- lib/passes/TypeARTConfiguration.cpp | 2 +- lib/passes/TypeARTConfiguration.h | 2 +- lib/passes/TypeARTPass.cpp | 2 +- lib/passes/analysis/MemInstFinder.cpp | 2 +- lib/passes/analysis/MemInstFinder.h | 2 +- lib/passes/analysis/MemOpData.h | 2 +- lib/passes/analysis/MemOpVisitor.cpp | 2 +- lib/passes/analysis/MemOpVisitor.h | 2 +- lib/passes/compat/CallSite.h | 2 +- lib/passes/configuration/Configuration.h | 2 +- lib/passes/configuration/EnvironmentConfiguration.cpp | 2 +- lib/passes/configuration/EnvironmentConfiguration.h | 2 +- lib/passes/configuration/FileConfiguration.cpp | 2 +- lib/passes/configuration/FileConfiguration.h | 2 +- lib/passes/configuration/OptionsUtil.h | 2 +- lib/passes/configuration/PassBuilderUtil.h | 6 +++--- lib/passes/configuration/PassConfiguration.cpp | 2 +- lib/passes/configuration/PassConfiguration.h | 2 +- lib/passes/configuration/TypeARTOptions.cpp | 6 +++--- lib/passes/configuration/TypeARTOptions.h | 2 +- lib/passes/filter/CGForwardFilter.cpp | 2 +- lib/passes/filter/CGForwardFilter.h | 2 +- lib/passes/filter/CGInterface.cpp | 2 +- lib/passes/filter/CGInterface.h | 2 +- lib/passes/filter/Filter.h | 2 +- lib/passes/filter/FilterBase.h | 2 +- lib/passes/filter/FilterUtil.cpp | 2 +- lib/passes/filter/FilterUtil.h | 2 +- lib/passes/filter/IRPath.h | 2 +- lib/passes/filter/IRSearch.h | 2 +- lib/passes/filter/Matcher.h | 2 +- lib/passes/filter/OmpUtil.h | 2 +- lib/passes/filter/StdForwardFilter.cpp | 2 +- lib/passes/filter/StdForwardFilter.h | 2 +- lib/passes/instrumentation/Instrumentation.cpp | 2 +- lib/passes/instrumentation/Instrumentation.h | 2 +- lib/passes/instrumentation/InstrumentationHelper.cpp | 2 +- lib/passes/instrumentation/InstrumentationHelper.h | 2 +- lib/passes/instrumentation/MemOpArgCollector.cpp | 2 +- lib/passes/instrumentation/MemOpArgCollector.h | 2 +- lib/passes/instrumentation/MemOpInstrumentation.cpp | 2 +- lib/passes/instrumentation/MemOpInstrumentation.h | 2 +- lib/passes/instrumentation/TransformUtil.h | 2 +- lib/passes/instrumentation/TypeARTFunctions.cpp | 2 +- lib/passes/instrumentation/TypeARTFunctions.h | 2 +- lib/passes/support/DefUseChain.h | 2 +- lib/passes/support/Error.h | 2 +- lib/passes/support/ModuleDumper.cpp | 2 +- lib/passes/support/ModuleDumper.h | 2 +- lib/passes/support/OmpUtil.h | 2 +- lib/passes/support/TypeUtil.cpp | 2 +- lib/passes/support/TypeUtil.h | 2 +- lib/passes/support/Util.h | 2 +- lib/passes/typegen/TypeGenerator.cpp | 2 +- lib/passes/typegen/TypeGenerator.h | 2 +- lib/passes/typegen/TypeIDGenerator.h | 2 +- lib/passes/typegen/dimeta/DimetaTypeGen.cpp | 2 +- lib/passes/typegen/dimeta/DimetaTypeGen.h | 2 +- lib/passes/typegen/ir/IRTypeGen.h | 2 +- lib/passes/typegen/ir/StructTypeHandler.cpp | 2 +- lib/passes/typegen/ir/StructTypeHandler.h | 2 +- lib/passes/typegen/ir/TypeManager.cpp | 2 +- lib/passes/typegen/ir/TypeManager.h | 2 +- lib/passes/typegen/ir/VectorTypeHandler.cpp | 2 +- lib/passes/typegen/ir/VectorTypeHandler.h | 2 +- lib/runtime/AccessCountPrinter.h | 2 +- lib/runtime/AccessCounter.h | 2 +- lib/runtime/AllocMapWrapper.h | 2 +- lib/runtime/AllocationTracking.cpp | 2 +- lib/runtime/AllocationTracking.h | 2 +- lib/runtime/CallbackInterface.h | 2 +- lib/runtime/Runtime.cpp | 2 +- lib/runtime/Runtime.h | 2 +- lib/runtime/RuntimeData.h | 2 +- lib/runtime/RuntimeInterface.h | 2 +- lib/runtime/TypeResolution.cpp | 2 +- lib/runtime/TypeResolution.h | 2 +- lib/runtime/Version.cpp.in | 2 +- lib/support/ConfigurationBase.h | 2 +- lib/support/ConfigurationBaseOptions.h | 2 +- lib/support/Logger.h | 2 +- lib/support/MPILogger.cpp | 2 +- lib/support/System.cpp | 2 +- lib/support/System.h | 2 +- lib/support/Table.h | 2 +- lib/typelib/TypeDB.cpp | 2 +- lib/typelib/TypeDB.h | 2 +- lib/typelib/TypeDatabase.h | 2 +- lib/typelib/TypeIO.cpp | 2 +- lib/typelib/TypeIO.h | 2 +- lib/typelib/TypeInterface.h | 2 +- scripts/typeart-tmpl.sh.in | 2 +- scripts/typeart-wrapper.in | 2 +- scripts/typeart-wrapperv2.in | 2 +- scripts/typeart_ir_compare.py | 2 +- scripts/typeart_ir_viewer.py | 2 +- 101 files changed, 105 insertions(+), 105 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 3b7824c3..149127ac 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2017-2025, TypeART authors +Copyright (c) 2017-2026, TypeART authors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/lib/mpi_interceptor/InterceptorFunctions.h b/lib/mpi_interceptor/InterceptorFunctions.h index c1ccb341..4d2a47e5 100644 --- a/lib/mpi_interceptor/InterceptorFunctions.h +++ b/lib/mpi_interceptor/InterceptorFunctions.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/mpi_interceptor/mpi_interceptor_tmpl.impl b/lib/mpi_interceptor/mpi_interceptor_tmpl.impl index 5df24932..921b0e47 100644 --- a/lib/mpi_interceptor/mpi_interceptor_tmpl.impl +++ b/lib/mpi_interceptor/mpi_interceptor_tmpl.impl @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/Commandline.cpp b/lib/passes/Commandline.cpp index 3ea91a4e..9619e166 100644 --- a/lib/passes/Commandline.cpp +++ b/lib/passes/Commandline.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/Commandline.h b/lib/passes/Commandline.h index 8b554908..a39f9f05 100644 --- a/lib/passes/Commandline.h +++ b/lib/passes/Commandline.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/TypeARTConfiguration.cpp b/lib/passes/TypeARTConfiguration.cpp index 93b50ccd..a0a60f69 100644 --- a/lib/passes/TypeARTConfiguration.cpp +++ b/lib/passes/TypeARTConfiguration.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/TypeARTConfiguration.h b/lib/passes/TypeARTConfiguration.h index 2927d5e3..80ff4301 100644 --- a/lib/passes/TypeARTConfiguration.h +++ b/lib/passes/TypeARTConfiguration.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/TypeARTPass.cpp b/lib/passes/TypeARTPass.cpp index 7780f43b..cf63ac3b 100644 --- a/lib/passes/TypeARTPass.cpp +++ b/lib/passes/TypeARTPass.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/analysis/MemInstFinder.cpp b/lib/passes/analysis/MemInstFinder.cpp index 1de001e3..09a93621 100644 --- a/lib/passes/analysis/MemInstFinder.cpp +++ b/lib/passes/analysis/MemInstFinder.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/analysis/MemInstFinder.h b/lib/passes/analysis/MemInstFinder.h index a11cf88f..8f74f23c 100644 --- a/lib/passes/analysis/MemInstFinder.h +++ b/lib/passes/analysis/MemInstFinder.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/analysis/MemOpData.h b/lib/passes/analysis/MemOpData.h index 8750b07d..34d173e5 100644 --- a/lib/passes/analysis/MemOpData.h +++ b/lib/passes/analysis/MemOpData.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/analysis/MemOpVisitor.cpp b/lib/passes/analysis/MemOpVisitor.cpp index 0e8e4294..9b835cc8 100644 --- a/lib/passes/analysis/MemOpVisitor.cpp +++ b/lib/passes/analysis/MemOpVisitor.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/analysis/MemOpVisitor.h b/lib/passes/analysis/MemOpVisitor.h index 3117e41a..88738e39 100644 --- a/lib/passes/analysis/MemOpVisitor.h +++ b/lib/passes/analysis/MemOpVisitor.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/compat/CallSite.h b/lib/passes/compat/CallSite.h index 9a4f821a..430ac868 100644 --- a/lib/passes/compat/CallSite.h +++ b/lib/passes/compat/CallSite.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/configuration/Configuration.h b/lib/passes/configuration/Configuration.h index 8a386567..ab1c4596 100644 --- a/lib/passes/configuration/Configuration.h +++ b/lib/passes/configuration/Configuration.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/configuration/EnvironmentConfiguration.cpp b/lib/passes/configuration/EnvironmentConfiguration.cpp index 2d43fa8a..76182011 100644 --- a/lib/passes/configuration/EnvironmentConfiguration.cpp +++ b/lib/passes/configuration/EnvironmentConfiguration.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/configuration/EnvironmentConfiguration.h b/lib/passes/configuration/EnvironmentConfiguration.h index 68ceb184..a9c6a6dd 100644 --- a/lib/passes/configuration/EnvironmentConfiguration.h +++ b/lib/passes/configuration/EnvironmentConfiguration.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/configuration/FileConfiguration.cpp b/lib/passes/configuration/FileConfiguration.cpp index 71a05032..4ba5a018 100644 --- a/lib/passes/configuration/FileConfiguration.cpp +++ b/lib/passes/configuration/FileConfiguration.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/configuration/FileConfiguration.h b/lib/passes/configuration/FileConfiguration.h index 5ed453d9..62d63bfb 100644 --- a/lib/passes/configuration/FileConfiguration.h +++ b/lib/passes/configuration/FileConfiguration.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/configuration/OptionsUtil.h b/lib/passes/configuration/OptionsUtil.h index f44ac0c4..59cf5f2f 100644 --- a/lib/passes/configuration/OptionsUtil.h +++ b/lib/passes/configuration/OptionsUtil.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/configuration/PassBuilderUtil.h b/lib/passes/configuration/PassBuilderUtil.h index 8908e2f5..a2b27371 100644 --- a/lib/passes/configuration/PassBuilderUtil.h +++ b/lib/passes/configuration/PassBuilderUtil.h @@ -1,7 +1,7 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) @@ -52,8 +52,8 @@ inline bool checkParametrizedPassName(llvm::StringRef Name, llvm::StringRef Pass /// Expected<> template class. /// template -inline auto parsePassParameters(ParametersParseCallableT&& Parser, llvm::StringRef Name, - llvm::StringRef PassName) -> decltype(Parser(llvm::StringRef{})) { +inline auto parsePassParameters(ParametersParseCallableT&& Parser, llvm::StringRef Name, llvm::StringRef PassName) + -> decltype(Parser(llvm::StringRef{})) { using namespace llvm; using ParametersT = typename decltype(Parser(StringRef{}))::value_type; diff --git a/lib/passes/configuration/PassConfiguration.cpp b/lib/passes/configuration/PassConfiguration.cpp index 659aab1f..5c067571 100644 --- a/lib/passes/configuration/PassConfiguration.cpp +++ b/lib/passes/configuration/PassConfiguration.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/configuration/PassConfiguration.h b/lib/passes/configuration/PassConfiguration.h index 9dda8566..2937132f 100644 --- a/lib/passes/configuration/PassConfiguration.h +++ b/lib/passes/configuration/PassConfiguration.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/configuration/TypeARTOptions.cpp b/lib/passes/configuration/TypeARTOptions.cpp index db1a76eb..232c5c1c 100644 --- a/lib/passes/configuration/TypeARTOptions.cpp +++ b/lib/passes/configuration/TypeARTOptions.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) @@ -172,8 +172,8 @@ TypeARTConfigOptions config_to_options(const Configuration& configuration) { } template -auto make_entry(std::string_view key, - const T& field_value) -> std::pair { +auto make_entry(std::string_view key, const T& field_value) + -> std::pair { if constexpr (std::is_enum_v) { return {key, config::OptionValue{static_cast(field_value)}}; } else { diff --git a/lib/passes/configuration/TypeARTOptions.h b/lib/passes/configuration/TypeARTOptions.h index edccff6f..3091701a 100644 --- a/lib/passes/configuration/TypeARTOptions.h +++ b/lib/passes/configuration/TypeARTOptions.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/CGForwardFilter.cpp b/lib/passes/filter/CGForwardFilter.cpp index 2570f5aa..65b8342f 100644 --- a/lib/passes/filter/CGForwardFilter.cpp +++ b/lib/passes/filter/CGForwardFilter.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/CGForwardFilter.h b/lib/passes/filter/CGForwardFilter.h index 3f017dc1..eac8ae49 100644 --- a/lib/passes/filter/CGForwardFilter.h +++ b/lib/passes/filter/CGForwardFilter.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/CGInterface.cpp b/lib/passes/filter/CGInterface.cpp index 25dd24c8..9ba7cacf 100644 --- a/lib/passes/filter/CGInterface.cpp +++ b/lib/passes/filter/CGInterface.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/CGInterface.h b/lib/passes/filter/CGInterface.h index e51bce26..1450bb4b 100644 --- a/lib/passes/filter/CGInterface.h +++ b/lib/passes/filter/CGInterface.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/Filter.h b/lib/passes/filter/Filter.h index 898fdedc..49fb0e87 100644 --- a/lib/passes/filter/Filter.h +++ b/lib/passes/filter/Filter.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/FilterBase.h b/lib/passes/filter/FilterBase.h index b46104ec..4173874f 100644 --- a/lib/passes/filter/FilterBase.h +++ b/lib/passes/filter/FilterBase.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/FilterUtil.cpp b/lib/passes/filter/FilterUtil.cpp index 245be8c0..4d34cae1 100644 --- a/lib/passes/filter/FilterUtil.cpp +++ b/lib/passes/filter/FilterUtil.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/FilterUtil.h b/lib/passes/filter/FilterUtil.h index c54ca2f5..11878673 100644 --- a/lib/passes/filter/FilterUtil.h +++ b/lib/passes/filter/FilterUtil.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/IRPath.h b/lib/passes/filter/IRPath.h index ba10785e..ed94a7bf 100644 --- a/lib/passes/filter/IRPath.h +++ b/lib/passes/filter/IRPath.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/IRSearch.h b/lib/passes/filter/IRSearch.h index c9eb2477..a7518475 100644 --- a/lib/passes/filter/IRSearch.h +++ b/lib/passes/filter/IRSearch.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/Matcher.h b/lib/passes/filter/Matcher.h index d58653ec..aa1b4a5f 100644 --- a/lib/passes/filter/Matcher.h +++ b/lib/passes/filter/Matcher.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/OmpUtil.h b/lib/passes/filter/OmpUtil.h index 31478ee0..497eb478 100644 --- a/lib/passes/filter/OmpUtil.h +++ b/lib/passes/filter/OmpUtil.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/StdForwardFilter.cpp b/lib/passes/filter/StdForwardFilter.cpp index 24a14beb..f9edfc06 100644 --- a/lib/passes/filter/StdForwardFilter.cpp +++ b/lib/passes/filter/StdForwardFilter.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/filter/StdForwardFilter.h b/lib/passes/filter/StdForwardFilter.h index 343f6c82..2b365ba7 100644 --- a/lib/passes/filter/StdForwardFilter.h +++ b/lib/passes/filter/StdForwardFilter.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/Instrumentation.cpp b/lib/passes/instrumentation/Instrumentation.cpp index 229813e3..88f183d8 100644 --- a/lib/passes/instrumentation/Instrumentation.cpp +++ b/lib/passes/instrumentation/Instrumentation.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/Instrumentation.h b/lib/passes/instrumentation/Instrumentation.h index c32bae1d..643263d3 100644 --- a/lib/passes/instrumentation/Instrumentation.h +++ b/lib/passes/instrumentation/Instrumentation.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/InstrumentationHelper.cpp b/lib/passes/instrumentation/InstrumentationHelper.cpp index 7467847a..1e499815 100644 --- a/lib/passes/instrumentation/InstrumentationHelper.cpp +++ b/lib/passes/instrumentation/InstrumentationHelper.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/InstrumentationHelper.h b/lib/passes/instrumentation/InstrumentationHelper.h index 38d2a322..ba8e381f 100644 --- a/lib/passes/instrumentation/InstrumentationHelper.h +++ b/lib/passes/instrumentation/InstrumentationHelper.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/MemOpArgCollector.cpp b/lib/passes/instrumentation/MemOpArgCollector.cpp index 2da62cf5..bd6315ed 100644 --- a/lib/passes/instrumentation/MemOpArgCollector.cpp +++ b/lib/passes/instrumentation/MemOpArgCollector.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/MemOpArgCollector.h b/lib/passes/instrumentation/MemOpArgCollector.h index 5ccd1a0d..31bd1da2 100644 --- a/lib/passes/instrumentation/MemOpArgCollector.h +++ b/lib/passes/instrumentation/MemOpArgCollector.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/MemOpInstrumentation.cpp b/lib/passes/instrumentation/MemOpInstrumentation.cpp index ba64511e..950bfd8d 100644 --- a/lib/passes/instrumentation/MemOpInstrumentation.cpp +++ b/lib/passes/instrumentation/MemOpInstrumentation.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/MemOpInstrumentation.h b/lib/passes/instrumentation/MemOpInstrumentation.h index 0b82c0bd..824fd749 100644 --- a/lib/passes/instrumentation/MemOpInstrumentation.h +++ b/lib/passes/instrumentation/MemOpInstrumentation.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/TransformUtil.h b/lib/passes/instrumentation/TransformUtil.h index b6d38ef3..bb761bda 100644 --- a/lib/passes/instrumentation/TransformUtil.h +++ b/lib/passes/instrumentation/TransformUtil.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/TypeARTFunctions.cpp b/lib/passes/instrumentation/TypeARTFunctions.cpp index 2953957a..0a1a8ea5 100644 --- a/lib/passes/instrumentation/TypeARTFunctions.cpp +++ b/lib/passes/instrumentation/TypeARTFunctions.cpp @@ -1,7 +1,7 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/instrumentation/TypeARTFunctions.h b/lib/passes/instrumentation/TypeARTFunctions.h index e0927ae3..21c135da 100644 --- a/lib/passes/instrumentation/TypeARTFunctions.h +++ b/lib/passes/instrumentation/TypeARTFunctions.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/support/DefUseChain.h b/lib/passes/support/DefUseChain.h index 6d14928f..ba504f9d 100644 --- a/lib/passes/support/DefUseChain.h +++ b/lib/passes/support/DefUseChain.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/support/Error.h b/lib/passes/support/Error.h index cea1e86e..0df91b02 100644 --- a/lib/passes/support/Error.h +++ b/lib/passes/support/Error.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/support/ModuleDumper.cpp b/lib/passes/support/ModuleDumper.cpp index 40148268..35bcae37 100644 --- a/lib/passes/support/ModuleDumper.cpp +++ b/lib/passes/support/ModuleDumper.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/support/ModuleDumper.h b/lib/passes/support/ModuleDumper.h index cd6120a1..0ae30fb2 100644 --- a/lib/passes/support/ModuleDumper.h +++ b/lib/passes/support/ModuleDumper.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/support/OmpUtil.h b/lib/passes/support/OmpUtil.h index 209c0e92..fe5c229a 100644 --- a/lib/passes/support/OmpUtil.h +++ b/lib/passes/support/OmpUtil.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/support/TypeUtil.cpp b/lib/passes/support/TypeUtil.cpp index 334cafaf..94c9fe75 100644 --- a/lib/passes/support/TypeUtil.cpp +++ b/lib/passes/support/TypeUtil.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/support/TypeUtil.h b/lib/passes/support/TypeUtil.h index 97b1175b..0dcee0bf 100644 --- a/lib/passes/support/TypeUtil.h +++ b/lib/passes/support/TypeUtil.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/support/Util.h b/lib/passes/support/Util.h index c7b48fa8..9019d85e 100644 --- a/lib/passes/support/Util.h +++ b/lib/passes/support/Util.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/TypeGenerator.cpp b/lib/passes/typegen/TypeGenerator.cpp index 2401bda2..1af54153 100644 --- a/lib/passes/typegen/TypeGenerator.cpp +++ b/lib/passes/typegen/TypeGenerator.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/TypeGenerator.h b/lib/passes/typegen/TypeGenerator.h index 20d1c501..3130afee 100644 --- a/lib/passes/typegen/TypeGenerator.h +++ b/lib/passes/typegen/TypeGenerator.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/TypeIDGenerator.h b/lib/passes/typegen/TypeIDGenerator.h index 8e6e271b..68fe4a8f 100644 --- a/lib/passes/typegen/TypeIDGenerator.h +++ b/lib/passes/typegen/TypeIDGenerator.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/dimeta/DimetaTypeGen.cpp b/lib/passes/typegen/dimeta/DimetaTypeGen.cpp index 39c57c7a..90a19cc3 100644 --- a/lib/passes/typegen/dimeta/DimetaTypeGen.cpp +++ b/lib/passes/typegen/dimeta/DimetaTypeGen.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/dimeta/DimetaTypeGen.h b/lib/passes/typegen/dimeta/DimetaTypeGen.h index 3333b57e..51d7ccfe 100644 --- a/lib/passes/typegen/dimeta/DimetaTypeGen.h +++ b/lib/passes/typegen/dimeta/DimetaTypeGen.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/ir/IRTypeGen.h b/lib/passes/typegen/ir/IRTypeGen.h index ddaf9367..bbc6a8d0 100644 --- a/lib/passes/typegen/ir/IRTypeGen.h +++ b/lib/passes/typegen/ir/IRTypeGen.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/ir/StructTypeHandler.cpp b/lib/passes/typegen/ir/StructTypeHandler.cpp index e4e3fc7d..1a87b070 100644 --- a/lib/passes/typegen/ir/StructTypeHandler.cpp +++ b/lib/passes/typegen/ir/StructTypeHandler.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/ir/StructTypeHandler.h b/lib/passes/typegen/ir/StructTypeHandler.h index d3306a7b..3f373af7 100644 --- a/lib/passes/typegen/ir/StructTypeHandler.h +++ b/lib/passes/typegen/ir/StructTypeHandler.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/ir/TypeManager.cpp b/lib/passes/typegen/ir/TypeManager.cpp index 0ce54df2..daf26dbb 100644 --- a/lib/passes/typegen/ir/TypeManager.cpp +++ b/lib/passes/typegen/ir/TypeManager.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/ir/TypeManager.h b/lib/passes/typegen/ir/TypeManager.h index a5b5d5d5..996a905a 100644 --- a/lib/passes/typegen/ir/TypeManager.h +++ b/lib/passes/typegen/ir/TypeManager.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/ir/VectorTypeHandler.cpp b/lib/passes/typegen/ir/VectorTypeHandler.cpp index f674e80f..c2bf1d71 100644 --- a/lib/passes/typegen/ir/VectorTypeHandler.cpp +++ b/lib/passes/typegen/ir/VectorTypeHandler.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/passes/typegen/ir/VectorTypeHandler.h b/lib/passes/typegen/ir/VectorTypeHandler.h index b7fe09b9..97539bdc 100644 --- a/lib/passes/typegen/ir/VectorTypeHandler.h +++ b/lib/passes/typegen/ir/VectorTypeHandler.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/AccessCountPrinter.h b/lib/runtime/AccessCountPrinter.h index d7cf343b..a1030b28 100644 --- a/lib/runtime/AccessCountPrinter.h +++ b/lib/runtime/AccessCountPrinter.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/AccessCounter.h b/lib/runtime/AccessCounter.h index 086c73a6..8db9e1fe 100644 --- a/lib/runtime/AccessCounter.h +++ b/lib/runtime/AccessCounter.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/AllocMapWrapper.h b/lib/runtime/AllocMapWrapper.h index 2500be6c..d1546fbf 100644 --- a/lib/runtime/AllocMapWrapper.h +++ b/lib/runtime/AllocMapWrapper.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/AllocationTracking.cpp b/lib/runtime/AllocationTracking.cpp index 7e4764e6..afcbf973 100644 --- a/lib/runtime/AllocationTracking.cpp +++ b/lib/runtime/AllocationTracking.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/AllocationTracking.h b/lib/runtime/AllocationTracking.h index ab1156ee..d843dcd8 100644 --- a/lib/runtime/AllocationTracking.h +++ b/lib/runtime/AllocationTracking.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/CallbackInterface.h b/lib/runtime/CallbackInterface.h index 7b5f7490..83ec2d06 100644 --- a/lib/runtime/CallbackInterface.h +++ b/lib/runtime/CallbackInterface.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/Runtime.cpp b/lib/runtime/Runtime.cpp index e53bf9dd..1c3e10c4 100644 --- a/lib/runtime/Runtime.cpp +++ b/lib/runtime/Runtime.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/Runtime.h b/lib/runtime/Runtime.h index b17aaf43..c5539e2d 100644 --- a/lib/runtime/Runtime.h +++ b/lib/runtime/Runtime.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/RuntimeData.h b/lib/runtime/RuntimeData.h index b3b3f41f..5e334b58 100644 --- a/lib/runtime/RuntimeData.h +++ b/lib/runtime/RuntimeData.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/RuntimeInterface.h b/lib/runtime/RuntimeInterface.h index e6190b34..125445b2 100644 --- a/lib/runtime/RuntimeInterface.h +++ b/lib/runtime/RuntimeInterface.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/TypeResolution.cpp b/lib/runtime/TypeResolution.cpp index 056b1a6b..00de468b 100644 --- a/lib/runtime/TypeResolution.cpp +++ b/lib/runtime/TypeResolution.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/TypeResolution.h b/lib/runtime/TypeResolution.h index edd8ee9c..760ca56a 100644 --- a/lib/runtime/TypeResolution.h +++ b/lib/runtime/TypeResolution.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/runtime/Version.cpp.in b/lib/runtime/Version.cpp.in index a56c6bcd..56c501fa 100644 --- a/lib/runtime/Version.cpp.in +++ b/lib/runtime/Version.cpp.in @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/support/ConfigurationBase.h b/lib/support/ConfigurationBase.h index ab085acc..85a3f691 100644 --- a/lib/support/ConfigurationBase.h +++ b/lib/support/ConfigurationBase.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/support/ConfigurationBaseOptions.h b/lib/support/ConfigurationBaseOptions.h index 87b889b0..f7386c8e 100644 --- a/lib/support/ConfigurationBaseOptions.h +++ b/lib/support/ConfigurationBaseOptions.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/support/Logger.h b/lib/support/Logger.h index 81a106f1..2cf064e7 100644 --- a/lib/support/Logger.h +++ b/lib/support/Logger.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/support/MPILogger.cpp b/lib/support/MPILogger.cpp index 2ae30520..1632408f 100644 --- a/lib/support/MPILogger.cpp +++ b/lib/support/MPILogger.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/support/System.cpp b/lib/support/System.cpp index 1173fa3a..95984e5a 100644 --- a/lib/support/System.cpp +++ b/lib/support/System.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/support/System.h b/lib/support/System.h index 75410533..34902826 100644 --- a/lib/support/System.h +++ b/lib/support/System.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/support/Table.h b/lib/support/Table.h index 17f02728..2d7c7041 100644 --- a/lib/support/Table.h +++ b/lib/support/Table.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/typelib/TypeDB.cpp b/lib/typelib/TypeDB.cpp index 9f262ed0..1e612d2e 100644 --- a/lib/typelib/TypeDB.cpp +++ b/lib/typelib/TypeDB.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/typelib/TypeDB.h b/lib/typelib/TypeDB.h index 25227547..54e7b611 100644 --- a/lib/typelib/TypeDB.h +++ b/lib/typelib/TypeDB.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/typelib/TypeDatabase.h b/lib/typelib/TypeDatabase.h index 07678ffe..29f0d082 100644 --- a/lib/typelib/TypeDatabase.h +++ b/lib/typelib/TypeDatabase.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/typelib/TypeIO.cpp b/lib/typelib/TypeIO.cpp index 6c99bf26..8b815c26 100644 --- a/lib/typelib/TypeIO.cpp +++ b/lib/typelib/TypeIO.cpp @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/typelib/TypeIO.h b/lib/typelib/TypeIO.h index 9487bf59..85d40d88 100644 --- a/lib/typelib/TypeIO.h +++ b/lib/typelib/TypeIO.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/lib/typelib/TypeInterface.h b/lib/typelib/TypeInterface.h index f791fe1c..0f91a961 100644 --- a/lib/typelib/TypeInterface.h +++ b/lib/typelib/TypeInterface.h @@ -1,6 +1,6 @@ // TypeART library // -// Copyright (c) 2017-2025 TypeART Authors +// Copyright (c) 2017-2026 TypeART Authors // Distributed under the BSD 3-Clause license. // (See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/BSD-3-Clause) diff --git a/scripts/typeart-tmpl.sh.in b/scripts/typeart-tmpl.sh.in index bc353d44..e3ad8c7a 100644 --- a/scripts/typeart-tmpl.sh.in +++ b/scripts/typeart-tmpl.sh.in @@ -2,7 +2,7 @@ # # TypeART library # -# Copyright (c) 2017-2025 TypeART Authors +# Copyright (c) 2017-2026 TypeART Authors # Distributed under the BSD 3-Clause license. # (See accompanying file LICENSE.txt or copy at # https://opensource.org/licenses/BSD-3-Clause) diff --git a/scripts/typeart-wrapper.in b/scripts/typeart-wrapper.in index 2d5b0abc..aa2891a1 100755 --- a/scripts/typeart-wrapper.in +++ b/scripts/typeart-wrapper.in @@ -2,7 +2,7 @@ # # TypeART library # -# Copyright (c) 2017-2025 TypeART Authors +# Copyright (c) 2017-2026 TypeART Authors # Distributed under the BSD 3-Clause license. # (See accompanying file LICENSE.txt or copy at # https://opensource.org/licenses/BSD-3-Clause) diff --git a/scripts/typeart-wrapperv2.in b/scripts/typeart-wrapperv2.in index cefc4091..494cb4b9 100644 --- a/scripts/typeart-wrapperv2.in +++ b/scripts/typeart-wrapperv2.in @@ -2,7 +2,7 @@ # # TypeART library # -# Copyright (c) 2017-2025 TypeART Authors +# Copyright (c) 2017-2026 TypeART Authors # Distributed under the BSD 3-Clause license. # (See accompanying file LICENSE.txt or copy at # https://opensource.org/licenses/BSD-3-Clause) diff --git a/scripts/typeart_ir_compare.py b/scripts/typeart_ir_compare.py index 77af59ea..1c995d59 100755 --- a/scripts/typeart_ir_compare.py +++ b/scripts/typeart_ir_compare.py @@ -2,7 +2,7 @@ # # TypeART library # -# Copyright (c) 2017-2025 TypeART Authors +# Copyright (c) 2017-2026 TypeART Authors # Distributed under the BSD 3-Clause license. # (See accompanying file LICENSE.txt or copy at # https://opensource.org/licenses/BSD-3-Clause) diff --git a/scripts/typeart_ir_viewer.py b/scripts/typeart_ir_viewer.py index 6a430d2f..f81146e5 100755 --- a/scripts/typeart_ir_viewer.py +++ b/scripts/typeart_ir_viewer.py @@ -2,7 +2,7 @@ # # TypeART library # -# Copyright (c) 2017-2025 TypeART Authors +# Copyright (c) 2017-2026 TypeART Authors # Distributed under the BSD 3-Clause license. # (See accompanying file LICENSE.txt or copy at # https://opensource.org/licenses/BSD-3-Clause) From 1ac35a39d83159fb7711b36b10199ff0485c1313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sun, 5 Apr 2026 17:01:10 +0200 Subject: [PATCH 13/14] Format --- lib/passes/configuration/PassBuilderUtil.h | 4 ++-- lib/passes/configuration/TypeARTOptions.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/passes/configuration/PassBuilderUtil.h b/lib/passes/configuration/PassBuilderUtil.h index a2b27371..cea89fcd 100644 --- a/lib/passes/configuration/PassBuilderUtil.h +++ b/lib/passes/configuration/PassBuilderUtil.h @@ -52,8 +52,8 @@ inline bool checkParametrizedPassName(llvm::StringRef Name, llvm::StringRef Pass /// Expected<> template class. /// template -inline auto parsePassParameters(ParametersParseCallableT&& Parser, llvm::StringRef Name, llvm::StringRef PassName) - -> decltype(Parser(llvm::StringRef{})) { +inline auto parsePassParameters(ParametersParseCallableT&& Parser, llvm::StringRef Name, + llvm::StringRef PassName) -> decltype(Parser(llvm::StringRef{})) { using namespace llvm; using ParametersT = typename decltype(Parser(StringRef{}))::value_type; diff --git a/lib/passes/configuration/TypeARTOptions.cpp b/lib/passes/configuration/TypeARTOptions.cpp index 232c5c1c..1c82427f 100644 --- a/lib/passes/configuration/TypeARTOptions.cpp +++ b/lib/passes/configuration/TypeARTOptions.cpp @@ -172,8 +172,8 @@ TypeARTConfigOptions config_to_options(const Configuration& configuration) { } template -auto make_entry(std::string_view key, const T& field_value) - -> std::pair { +auto make_entry(std::string_view key, + const T& field_value) -> std::pair { if constexpr (std::is_enum_v) { return {key, config::OptionValue{static_cast(field_value)}}; } else { From 2781192053e37b37338168e412cba7d470bee88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Tue, 7 Apr 2026 14:05:15 +0200 Subject: [PATCH 14/14] Rename header guards (#186) --- externals/abseil/CMakeLists.txt | 1 + lib/mpi_interceptor/InterceptorFunctions.h | 6 +++--- lib/passes/analysis/MemOpVisitor.h | 6 +++--- lib/passes/compat/CallSite.h | 6 +++--- lib/passes/configuration/OptionsUtil.h | 6 +++--- lib/passes/configuration/TypeARTOptions.h | 6 +++--- lib/passes/filter/CGInterface.h | 6 +++--- lib/passes/instrumentation/CallBackFunctionInserter.h | 6 +++--- lib/passes/instrumentation/InstrumentationHelper.h | 6 +++--- lib/passes/instrumentation/MemOpInstrumentation.h | 6 +++--- lib/passes/instrumentation/TypeIDProvider.h | 6 +++--- lib/passes/support/ModuleDumper.h | 6 +++--- lib/passes/support/TypeUtil.h | 6 +++--- lib/passes/support/Util.h | 6 +++--- lib/passes/typegen/TypeGenerator.h | 6 +++--- lib/passes/typegen/ir/TypeManager.h | 6 +++--- lib/runtime/GlobalTypeDefCallbacks.h | 6 +++--- lib/runtime/Runtime.h | 6 +++--- lib/runtime/RuntimeData.h | 5 ----- lib/support/Logger.h | 6 +++--- lib/typelib/TypeDB.h | 6 +++--- lib/typelib/TypeIO.h | 6 +++--- 22 files changed, 61 insertions(+), 65 deletions(-) diff --git a/externals/abseil/CMakeLists.txt b/externals/abseil/CMakeLists.txt index fe914405..0891c2cd 100644 --- a/externals/abseil/CMakeLists.txt +++ b/externals/abseil/CMakeLists.txt @@ -1,4 +1,5 @@ set(ABSL_PROPAGATE_CXX_STD ON) +set(ABSL_USE_SYSTEM_INCLUDES ON CACHE BOOL "Use system includes for Abseil" FORCE) FetchContent_Declare( cpp-abseil diff --git a/lib/mpi_interceptor/InterceptorFunctions.h b/lib/mpi_interceptor/InterceptorFunctions.h index 4d2a47e5..4ddbe4cd 100644 --- a/lib/mpi_interceptor/InterceptorFunctions.h +++ b/lib/mpi_interceptor/InterceptorFunctions.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef TEST_MPI_INTERCEPTOR_INTERCEPTORFUNCTIONS_H_ -#define TEST_MPI_INTERCEPTOR_INTERCEPTORFUNCTIONS_H_ +#ifndef TYPEART_MPI_INTERCEPTOR_INTERCEPTORFUNCTIONS_H +#define TYPEART_MPI_INTERCEPTOR_INTERCEPTORFUNCTIONS_H #include "RuntimeExport.h" #include "RuntimeInterface.h" @@ -156,4 +156,4 @@ TYPEART_NO_EXPORT void ta_exit() { mcounter.null_count); } -#endif /* TEST_MPI_INTERCEPTOR_INTERCEPTORFUNCTIONS_H_ */ +#endif // TYPEART_MPI_INTERCEPTOR_INTERCEPTORFUNCTIONS_H diff --git a/lib/passes/analysis/MemOpVisitor.h b/lib/passes/analysis/MemOpVisitor.h index 88738e39..fc982549 100644 --- a/lib/passes/analysis/MemOpVisitor.h +++ b/lib/passes/analysis/MemOpVisitor.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_MEMOPVISITOR_H_ -#define LIB_MEMOPVISITOR_H_ +#ifndef TYPEART_MEMOPVISITOR_H +#define TYPEART_MEMOPVISITOR_H #include "MemOpData.h" #include "configuration/Configuration.h" @@ -57,4 +57,4 @@ struct MemOpVisitor : public llvm::InstVisitor { } // namespace typeart::analysis -#endif /* LIB_MEMOPVISITOR_H_ */ +#endif // TYPEART_MEMOPVISITOR_H diff --git a/lib/passes/compat/CallSite.h b/lib/passes/compat/CallSite.h index 430ac868..d3f9ebd9 100644 --- a/lib/passes/compat/CallSite.h +++ b/lib/passes/compat/CallSite.h @@ -12,8 +12,8 @@ // In Clang 11 CallSite.h was removed, this is a small wrapper reimplementation -#ifndef COMPAT_LLVM_IR_CALLSITE_H -#define COMPAT_LLVM_IR_CALLSITE_H +#ifndef TYPEART_CALLSITE_H +#define TYPEART_CALLSITE_H #include "llvm/IR/Instruction.h" @@ -86,4 +86,4 @@ class CallSite { }; } // namespace llvm -#endif +#endif // TYPEART_CALLSITE_H diff --git a/lib/passes/configuration/OptionsUtil.h b/lib/passes/configuration/OptionsUtil.h index 59cf5f2f..75a11c82 100644 --- a/lib/passes/configuration/OptionsUtil.h +++ b/lib/passes/configuration/OptionsUtil.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_PASSES_CONFIGURATION_OPTIONSUTIL -#define LIB_PASSES_CONFIGURATION_OPTIONSUTIL +#ifndef TYPEART_CONFIGURATION_OPTIONS_UTIL_H +#define TYPEART_CONFIGURATION_OPTIONS_UTIL_H #include "analysis/MemInstFinder.h" #include "instrumentation/TypeIDProvider.h" @@ -80,4 +80,4 @@ ClType make_opt(llvm::StringRef cl_value) { } } // namespace typeart::config::util -#endif /* LIB_PASSES_CONFIGURATION_OPTIONSUTIL */ +#endif // TYPEART_CONFIGURATION_OPTIONS_UTIL_H diff --git a/lib/passes/configuration/TypeARTOptions.h b/lib/passes/configuration/TypeARTOptions.h index 3091701a..03e7884d 100644 --- a/lib/passes/configuration/TypeARTOptions.h +++ b/lib/passes/configuration/TypeARTOptions.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_PASSES_CONFIGURATION_TYPEARTOPTIONS -#define LIB_PASSES_CONFIGURATION_TYPEARTOPTIONS +#ifndef TYPEART_CONFIGURATION_OPTIONS_H +#define TYPEART_CONFIGURATION_OPTIONS_H #include "analysis/MemInstFinder.h" #include "configuration/Configuration.h" @@ -82,4 +82,4 @@ llvm::raw_ostream& operator<<(llvm::raw_ostream& out_s, const TypeARTConfigOptio } // namespace typeart::config -#endif /* LIB_PASSES_CONFIGURATION_TYPEARTOPTIONS */ +#endif // TYPEART_CONFIGURATION_OPTIONS_H diff --git a/lib/passes/filter/CGInterface.h b/lib/passes/filter/CGInterface.h index 1450bb4b..fea57be8 100644 --- a/lib/passes/filter/CGInterface.h +++ b/lib/passes/filter/CGInterface.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef _LIB_TYPEART_CGINTERFACE_H -#define _LIB_TYPEART_CGINTERFACE_H +#ifndef TYPEART_CGINTERFACE_H +#define TYPEART_CGINTERFACE_H #include "llvm/Support/JSON.h" @@ -80,4 +80,4 @@ class JSONCG final : public CGInterface { }; } // namespace typeart::filter -#endif \ No newline at end of file +#endif // TYPEART_CGINTERFACE_H \ No newline at end of file diff --git a/lib/passes/instrumentation/CallBackFunctionInserter.h b/lib/passes/instrumentation/CallBackFunctionInserter.h index 70e88737..7901fce4 100644 --- a/lib/passes/instrumentation/CallBackFunctionInserter.h +++ b/lib/passes/instrumentation/CallBackFunctionInserter.h @@ -1,5 +1,5 @@ -#ifndef LIB_PASSES_INSTRUMENTATION_CALLBACKFUNCTIONINSERTER -#define LIB_PASSES_INSTRUMENTATION_CALLBACKFUNCTIONINSERTER +#ifndef TYPEART_CALLBACKFUNCTIONINSERTER_H +#define TYPEART_CALLBACKFUNCTIONINSERTER_H #include "instrumentation/TypeARTFunctions.h" @@ -51,4 +51,4 @@ std::unique_ptr make_callback_inserter(const config::Co } // namespace typeart -#endif /* LIB_PASSES_INSTRUMENTATION_CALLBACKFUNCTIONINSERTER */ +#endif // TYPEART_CALLBACKFUNCTIONINSERTER_H diff --git a/lib/passes/instrumentation/InstrumentationHelper.h b/lib/passes/instrumentation/InstrumentationHelper.h index ba8e381f..be7211c8 100644 --- a/lib/passes/instrumentation/InstrumentationHelper.h +++ b/lib/passes/instrumentation/InstrumentationHelper.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_INSTRUMENTATIONHELPER_H_ -#define LIB_INSTRUMENTATIONHELPER_H_ +#ifndef TYPEART_INSTRUMENTATIONHELPER_H +#define TYPEART_INSTRUMENTATIONHELPER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" @@ -66,4 +66,4 @@ class InstrumentationHelper { } // namespace typeart -#endif /* LIB_INSTRUMENTATIONHELPER_H_ */ +#endif // TYPEART_INSTRUMENTATIONHELPER_H diff --git a/lib/passes/instrumentation/MemOpInstrumentation.h b/lib/passes/instrumentation/MemOpInstrumentation.h index 824fd749..4db19f74 100644 --- a/lib/passes/instrumentation/MemOpInstrumentation.h +++ b/lib/passes/instrumentation/MemOpInstrumentation.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_PASSES_INSTRUMENTATION_MEMOPINSTRUMENTATION -#define LIB_PASSES_INSTRUMENTATION_MEMOPINSTRUMENTATION +#ifndef TYPEART_MEMOPINSTRUMENTATION_H +#define TYPEART_MEMOPINSTRUMENTATION_H #include "Instrumentation.h" #include "configuration/Configuration.h" @@ -45,4 +45,4 @@ class MemOpInstrumentation final : public MemoryInstrument { }; } // namespace typeart -#endif /* LIB_PASSES_INSTRUMENTATION_MEMOPINSTRUMENTATION */ +#endif // TYPEART_MEMOPINSTRUMENTATION_H diff --git a/lib/passes/instrumentation/TypeIDProvider.h b/lib/passes/instrumentation/TypeIDProvider.h index e0467edc..1271af4a 100644 --- a/lib/passes/instrumentation/TypeIDProvider.h +++ b/lib/passes/instrumentation/TypeIDProvider.h @@ -1,5 +1,5 @@ -#ifndef LIB_PASSES_INSTRUMENTATION_MODULETYPEREGISTRY -#define LIB_PASSES_INSTRUMENTATION_MODULETYPEREGISTRY +#ifndef TYPEART_TYPEIDPROVIDER_H +#define TYPEART_TYPEIDPROVIDER_H // #include "TypeARTFunctions.h" // #include "instrumentation/TypeARTFunctions.h" @@ -36,4 +36,4 @@ std::unique_ptr get_type_id_handler(llvm::Module& m, const TypeDat } // namespace typeart -#endif /* LIB_PASSES_INSTRUMENTATION_MODULETYPEREGISTRY */ +#endif // TYPEART_TYPEIDPROVIDER_H diff --git a/lib/passes/support/ModuleDumper.h b/lib/passes/support/ModuleDumper.h index 0ae30fb2..cacadf3f 100644 --- a/lib/passes/support/ModuleDumper.h +++ b/lib/passes/support/ModuleDumper.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef MODULE_DUMPER_UTIL_H -#define MODULE_DUMPER_UTIL_H +#ifndef TYPEART_MODULEDUMPER_H +#define TYPEART_MODULEDUMPER_H #include "llvm/IR/Module.h" @@ -23,4 +23,4 @@ void dump_module(const llvm::Module& module, ModulePhase phase); } // namespace typeart::util::module -#endif +#endif // TYPEART_MODULEDUMPER_H diff --git a/lib/passes/support/TypeUtil.h b/lib/passes/support/TypeUtil.h index 0dcee0bf..129f6d99 100644 --- a/lib/passes/support/TypeUtil.h +++ b/lib/passes/support/TypeUtil.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_UTIL_TYPE_H -#define LIB_UTIL_TYPE_H +#ifndef TYPEART_TYPE_UTIL_H +#define TYPEART_TYPE_UTIL_H namespace llvm { class DataLayout; @@ -46,4 +46,4 @@ unsigned getPointerSizeInBytes(llvm::Type* ptrT, const llvm::DataLayout& dl); } // namespace typeart::util::type -#endif +#endif // TYPEART_TYPE_UTIL_H diff --git a/lib/passes/support/Util.h b/lib/passes/support/Util.h index 9019d85e..b7e1c8b2 100644 --- a/lib/passes/support/Util.h +++ b/lib/passes/support/Util.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_UTIL_H_ -#define LIB_UTIL_H_ +#ifndef TYPEART_UTIL_H +#define TYPEART_UTIL_H // #include "Logger.h" @@ -228,4 +228,4 @@ void for_each_cdtor(llvm::StringRef name, llvm::Module& module, Matcher&& matchi } // namespace typeart::util -#endif /* LIB_UTIL_H_ */ +#endif // TYPEART_UTIL_H diff --git a/lib/passes/typegen/TypeGenerator.h b/lib/passes/typegen/TypeGenerator.h index 3130afee..37c65d9e 100644 --- a/lib/passes/typegen/TypeGenerator.h +++ b/lib/passes/typegen/TypeGenerator.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_PASSES_TYPEGEN_TYPEGENERATOR -#define LIB_PASSES_TYPEGEN_TYPEGENERATOR +#ifndef TYPEART_TYPEGENERATOR_H +#define TYPEART_TYPEGENERATOR_H #include "analysis/MemOpData.h" #include "typelib/TypeDatabase.h" @@ -68,4 +68,4 @@ std::unique_ptr make_typegen(std::string_view file, TypegenImplem } // namespace typeart -#endif /* LIB_PASSES_TYPEGEN_TYPEGENERATOR */ +#endif // TYPEART_TYPEGENERATOR_H diff --git a/lib/passes/typegen/ir/TypeManager.h b/lib/passes/typegen/ir/TypeManager.h index 996a905a..6953d475 100644 --- a/lib/passes/typegen/ir/TypeManager.h +++ b/lib/passes/typegen/ir/TypeManager.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LLVM_MUST_SUPPORT_TYPEMANAGER_H -#define LLVM_MUST_SUPPORT_TYPEMANAGER_H +#ifndef TYPEART_TYPEMANAGER_H +#define TYPEART_TYPEMANAGER_H #include "typegen/TypeIDGenerator.h" @@ -44,4 +44,4 @@ class TypeManager final : public types::TypeIDGenerator { } // namespace typeart -#endif // LLVM_MUST_SUPPORT_TYPEMANAGER_H +#endif // TYPEART_TYPEMANAGER_H diff --git a/lib/runtime/GlobalTypeDefCallbacks.h b/lib/runtime/GlobalTypeDefCallbacks.h index b59d93d4..a836809b 100644 --- a/lib/runtime/GlobalTypeDefCallbacks.h +++ b/lib/runtime/GlobalTypeDefCallbacks.h @@ -1,5 +1,5 @@ -#ifndef LIB_RUNTIME_GLOBALTYPEDEFCALLBACKS -#define LIB_RUNTIME_GLOBALTYPEDEFCALLBACKS +#ifndef TYPEART_GLOBALTYPEDEFCALLBACKS_H +#define TYPEART_GLOBALTYPEDEFCALLBACKS_H #include "RuntimeData.h" #include "TypeInterface.h" @@ -41,4 +41,4 @@ class GlobalTypeTranslator final { } // namespace typeart -#endif /* LIB_RUNTIME_GLOBALTYPEDEFCALLBACKS */ +#endif // TYPEART_GLOBALTYPEDEFCALLBACKS_H diff --git a/lib/runtime/Runtime.h b/lib/runtime/Runtime.h index c5539e2d..97aaa819 100644 --- a/lib/runtime/Runtime.h +++ b/lib/runtime/Runtime.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_RUNTIME_RUNTIME -#define LIB_RUNTIME_RUNTIME +#ifndef TYPEART_RUNTIME_H +#define TYPEART_RUNTIME_H #include "AccessCounter.h" #include "AllocationTracking.h" @@ -126,4 +126,4 @@ struct RTGuard final { } // namespace typeart -#endif /* LIB_RUNTIME_RUNTIME */ +#endif // TYPEART_RUNTIME_H diff --git a/lib/runtime/RuntimeData.h b/lib/runtime/RuntimeData.h index 5e334b58..cf179f58 100644 --- a/lib/runtime/RuntimeData.h +++ b/lib/runtime/RuntimeData.h @@ -21,13 +21,8 @@ #ifdef TYPEART_PHMAP #error TypeART-RT: Set ABSL and PHMAP, mutually exclusive. #endif - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#pragma GCC diagnostic ignored "-Wshadow" #include "absl/container/btree_map.h" #include "absl/container/flat_hash_map.h" -#pragma GCC diagnostic pop #endif #ifdef TYPEART_PHMAP diff --git a/lib/support/Logger.h b/lib/support/Logger.h index 2cf064e7..e055d565 100644 --- a/lib/support/Logger.h +++ b/lib/support/Logger.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LIB_LOGGER_H_ -#define LIB_LOGGER_H_ +#ifndef TYPEART_LOGGER_H +#define TYPEART_LOGGER_H #include "llvm/Support/raw_ostream.h" @@ -67,4 +67,4 @@ inline void typeart_log(const std::string& 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_ */ +#endif // TYPEART_LOGGER_H diff --git a/lib/typelib/TypeDB.h b/lib/typelib/TypeDB.h index 54e7b611..bcac9d4f 100644 --- a/lib/typelib/TypeDB.h +++ b/lib/typelib/TypeDB.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LLVM_MUST_SUPPORT_TYPECONFIG_H -#define LLVM_MUST_SUPPORT_TYPECONFIG_H +#ifndef TYPEART_TYPEDB_H +#define TYPEART_TYPEDB_H #include "TypeDatabase.h" #include "TypeInterface.h" @@ -110,4 +110,4 @@ class TypeDB final : public TypeDatabase { } // namespace typeart -#endif // LLVM_MUST_SUPPORT_TYPECONFIG_H +#endif // TYPEART_TYPEDB_H diff --git a/lib/typelib/TypeIO.h b/lib/typelib/TypeIO.h index 85d40d88..25b4e011 100644 --- a/lib/typelib/TypeIO.h +++ b/lib/typelib/TypeIO.h @@ -10,8 +10,8 @@ // SPDX-License-Identifier: BSD-3-Clause // -#ifndef LLVM_MUST_SUPPORT_CONFIGIO_H -#define LLVM_MUST_SUPPORT_CONFIGIO_H +#ifndef TYPEART_TYPEIO_H +#define TYPEART_TYPEIO_H #include "typelib/TypeDatabase.h" @@ -30,4 +30,4 @@ namespace io { } // namespace typeart -#endif // LLVM_MUST_SUPPORT_CONFIGIO_H +#endif // TYPEART_TYPEIO_H