https://github.com/kevinsala updated https://github.com/llvm/llvm-project/pull/138978
>From 371483a750a456459d054a56787b40e946ab2890 Mon Sep 17 00:00:00 2001 From: Kevin Sala <salapenad...@llnl.gov> Date: Tue, 6 May 2025 22:48:41 -0700 Subject: [PATCH] [Instrumentor] Allow printing a runtime stub --- .../llvm/Transforms/IPO/Instrumentor.h | 16 ++ .../Transforms/IPO/InstrumentorStubPrinter.h | 32 +++ llvm/lib/Transforms/IPO/CMakeLists.txt | 1 + llvm/lib/Transforms/IPO/Instrumentor.cpp | 3 + .../IPO/InstrumentorStubPrinter.cpp | 210 ++++++++++++++++++ .../Instrumentor/bad_rt_config.json | 105 +++++++++ .../Instrumentor/default_config.json | 2 + .../Instrumentation/Instrumentor/default_rt | 37 +++ .../Instrumentor/generate_bad_rt.ll | 3 + .../Instrumentor/generate_rt.ll | 2 + .../Instrumentor/load_store_config.json | 2 +- .../load_store_noreplace_config.json | 2 +- .../Instrumentor/rt_config.json | 105 +++++++++ 13 files changed, 518 insertions(+), 2 deletions(-) create mode 100644 llvm/include/llvm/Transforms/IPO/InstrumentorStubPrinter.h create mode 100644 llvm/lib/Transforms/IPO/InstrumentorStubPrinter.cpp create mode 100644 llvm/test/Instrumentation/Instrumentor/bad_rt_config.json create mode 100644 llvm/test/Instrumentation/Instrumentor/default_rt create mode 100644 llvm/test/Instrumentation/Instrumentor/generate_bad_rt.ll create mode 100644 llvm/test/Instrumentation/Instrumentor/generate_rt.ll create mode 100644 llvm/test/Instrumentation/Instrumentor/rt_config.json diff --git a/llvm/include/llvm/Transforms/IPO/Instrumentor.h b/llvm/include/llvm/Transforms/IPO/Instrumentor.h index 26445d221d00f..e6d5f717072a2 100644 --- a/llvm/include/llvm/Transforms/IPO/Instrumentor.h +++ b/llvm/include/llvm/Transforms/IPO/Instrumentor.h @@ -116,6 +116,18 @@ struct IRTCallDescription { InstrumentorIRBuilderTy &IIRB, const DataLayout &DL, InstrumentationCaches &ICaches); + /// Create a string representation of the function declaration in C. Two + /// strings are returned: the function definition with direct arguments and + /// the function with any indirect argument. + std::pair<std::string, std::string> + createCSignature(const InstrumentationConfig &IConf) const; + + /// Create a string representation of the function definition in C. The + /// function body implements a stub and only prints the passed arguments. Two + /// strings are returned: the function definition with direct arguments and + /// the function with any indirect argument. + std::pair<std::string, std::string> createCBodies() const; + /// Return whether the \p IRTA argument can be replaced. bool isReplacable(IRTArg &IRTA) const { return (IRTA.Flags & (IRTArg::REPLACABLE | IRTArg::REPLACABLE_CUSTOM)); @@ -334,6 +346,9 @@ struct InstrumentationConfig { InstrumentationConfig() : SS(StringAllocator) { RuntimePrefix = BaseConfigurationOption::getStringOption( *this, "runtime_prefix", "The runtime API prefix.", "__instrumentor_"); + RuntimeStubsFile = BaseConfigurationOption::getStringOption( + *this, "runtime_stubs_file", + "The file into which runtime stubs should be written.", ""); TargetRegex = BaseConfigurationOption::getStringOption( *this, "target_regex", "Regular expression to be matched against the module target. " @@ -380,6 +395,7 @@ struct InstrumentationConfig { /// The base configuration options. BaseConfigurationOption *RuntimePrefix; + BaseConfigurationOption *RuntimeStubsFile; BaseConfigurationOption *TargetRegex; BaseConfigurationOption *HostEnabled; BaseConfigurationOption *GPUEnabled; diff --git a/llvm/include/llvm/Transforms/IPO/InstrumentorStubPrinter.h b/llvm/include/llvm/Transforms/IPO/InstrumentorStubPrinter.h new file mode 100644 index 0000000000000..6e1e24d5fef9e --- /dev/null +++ b/llvm/include/llvm/Transforms/IPO/InstrumentorStubPrinter.h @@ -0,0 +1,32 @@ +//===- Transforms/IPO/InstrumentorStubPrinter.h ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// A generator of Instrumentor's runtime stubs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_INSTRUMENTOR_STUB_PRINTER_H +#define LLVM_TRANSFORMS_IPO_INSTRUMENTOR_STUB_PRINTER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Module.h" +#include "llvm/Transforms/IPO/Instrumentor.h" + +namespace llvm { +namespace instrumentor { + +/// Print a runtime stub file with the implementation of the instrumentation +/// runtime functions corresponding to the instrumentation opportunities +/// enabled. +void printRuntimeStub(const InstrumentationConfig &IConf, + StringRef StubRuntimeName, LLVMContext &Ctx); + +} // end namespace instrumentor +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_IPO_INSTRUMENTOR_STUB_PRINTER_H diff --git a/llvm/lib/Transforms/IPO/CMakeLists.txt b/llvm/lib/Transforms/IPO/CMakeLists.txt index 824dff527a672..d1d132c51dca9 100644 --- a/llvm/lib/Transforms/IPO/CMakeLists.txt +++ b/llvm/lib/Transforms/IPO/CMakeLists.txt @@ -29,6 +29,7 @@ add_llvm_component_library(LLVMipo Inliner.cpp Instrumentor.cpp InstrumentorConfigFile.cpp + InstrumentorStubPrinter.cpp Internalize.cpp LoopExtractor.cpp LowerTypeTests.cpp diff --git a/llvm/lib/Transforms/IPO/Instrumentor.cpp b/llvm/lib/Transforms/IPO/Instrumentor.cpp index a28a40bdcb90e..4545af75ca8ac 100644 --- a/llvm/lib/Transforms/IPO/Instrumentor.cpp +++ b/llvm/lib/Transforms/IPO/Instrumentor.cpp @@ -10,6 +10,7 @@ #include "llvm/Transforms/IPO/Instrumentor.h" #include "llvm/Transforms/IPO/InstrumentorConfigFile.h" +#include "llvm/Transforms/IPO/InstrumentorStubPrinter.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/SmallPtrSet.h" @@ -261,6 +262,8 @@ PreservedAnalyses InstrumentorPass::run(Module &M, InstrumentationConfig &IConf, writeConfigToJSON(IConf, WriteConfigFile, IIRB.Ctx); + printRuntimeStub(IConf, IConf.RuntimeStubsFile->getString(), IIRB.Ctx); + bool Changed = Impl.instrument(); if (!Changed) return PreservedAnalyses::all(); diff --git a/llvm/lib/Transforms/IPO/InstrumentorStubPrinter.cpp b/llvm/lib/Transforms/IPO/InstrumentorStubPrinter.cpp new file mode 100644 index 0000000000000..bab8726f03b0d --- /dev/null +++ b/llvm/lib/Transforms/IPO/InstrumentorStubPrinter.cpp @@ -0,0 +1,210 @@ +//===-- InstrumentorStubPrinter.cpp ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/IPO/Instrumentor.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Support/raw_ostream.h" + +#include <cassert> +#include <string> +#include <system_error> + +namespace llvm { +namespace instrumentor { + +/// Get the string representation of an argument with type \p Ty. Two strings +/// are returned: one for direct arguments and another for indirect arguments. +/// The flags in \p Flags describe the properties of the argument. See +/// IRTArg::IRArgFlagTy. +static std::pair<std::string, std::string> getAsCType(Type *Ty, + unsigned Flags) { + if (Ty->isIntegerTy()) { + auto BW = Ty->getIntegerBitWidth(); + if (BW == 1) + return {"bool ", "bool *"}; + auto S = "int" + std::to_string(BW) + "_t "; + return {S, S + "*"}; + } + if (Ty->isPointerTy()) + return {Flags & IRTArg::STRING ? "char *" : "void *", "void **"}; + if (Ty->isFloatTy()) + return {"float ", "float *"}; + if (Ty->isDoubleTy()) + return {"double ", "double *"}; + return {"<>", "<>"}; +} + +/// Get the string representation of the C printf format of an argument with +/// type \p Ty. The flags in \p Flags describe the properties of the argument. +/// See IRTArg::IRArgFlagTy. +static std::string getPrintfFormatString(Type *Ty, unsigned Flags) { + if (Ty->isIntegerTy()) { + if (Ty->getIntegerBitWidth() > 32) { + assert(Ty->getIntegerBitWidth() == 64); + return "%lli"; + } + return "%i"; + } + if (Ty->isPointerTy()) + return Flags & IRTArg::STRING ? "%s" : "%p"; + if (Ty->isFloatTy()) + return "%f"; + if (Ty->isDoubleTy()) + return "%lf"; + return "<>"; +} + +std::pair<std::string, std::string> IRTCallDescription::createCBodies() const { + std::string DirectFormat = "printf(\"" + IO.getName().str() + + (IO.IP.isPRE() ? " pre" : " post") + " -- "; + std::string IndirectFormat = DirectFormat; + std::string DirectArg, IndirectArg, DirectReturnValue, IndirectReturnValue; + + auto AddToFormats = [&](Twine S) { + DirectFormat += S.str(); + IndirectFormat += S.str(); + }; + auto AddToArgs = [&](Twine S) { + DirectArg += S.str(); + IndirectArg += S.str(); + }; + bool First = true; + for (auto &IRArg : IO.IRTArgs) { + if (!IRArg.Enabled) + continue; + if (!First) + AddToFormats(", "); + First = false; + AddToArgs(", " + IRArg.Name); + AddToFormats(IRArg.Name + ": "); + if (NumReplaceableArgs == 1 && (IRArg.Flags & IRTArg::REPLACABLE)) { + DirectReturnValue = IRArg.Name; + if (!isPotentiallyIndirect(IRArg)) + IndirectReturnValue = IRArg.Name; + } + if (!isPotentiallyIndirect(IRArg)) { + AddToFormats(getPrintfFormatString(IRArg.Ty, IRArg.Flags)); + } else { + DirectFormat += getPrintfFormatString(IRArg.Ty, IRArg.Flags); + IndirectFormat += "%p"; + IndirectArg += "_ptr"; + // Add the indirect argument size + if (!(IRArg.Flags & IRTArg::INDIRECT_HAS_SIZE)) { + IndirectFormat += ", " + IRArg.Name.str() + "_size: %i"; + IndirectArg += ", " + IRArg.Name.str() + "_size"; + } + } + } + + std::string DirectBody = DirectFormat + "\\n\"" + DirectArg + ");\n"; + std::string IndirectBody = IndirectFormat + "\\n\"" + IndirectArg + ");\n"; + if (RetTy) + IndirectReturnValue = DirectReturnValue = "0"; + if (!DirectReturnValue.empty()) + DirectBody += " return " + DirectReturnValue + ";\n"; + if (!IndirectReturnValue.empty()) + IndirectBody += " return " + IndirectReturnValue + ";\n"; + return {DirectBody, IndirectBody}; +} + +std::pair<std::string, std::string> +IRTCallDescription::createCSignature(const InstrumentationConfig &IConf) const { + SmallVector<std::string> DirectArgs, IndirectArgs; + std::string DirectRetTy = "void ", IndirectRetTy = "void "; + for (auto &IRArg : IO.IRTArgs) { + if (!IRArg.Enabled) + continue; + const auto &[DirectArgTy, IndirectArgTy] = + getAsCType(IRArg.Ty, IRArg.Flags); + std::string DirectArg = DirectArgTy + IRArg.Name.str(); + std::string IndirectArg = IndirectArgTy + IRArg.Name.str() + "_ptr"; + std::string IndirectArgSize = "int32_t " + IRArg.Name.str() + "_size"; + DirectArgs.push_back(DirectArg); + if (NumReplaceableArgs == 1 && (IRArg.Flags & IRTArg::REPLACABLE)) { + DirectRetTy = DirectArgTy; + if (!isPotentiallyIndirect(IRArg)) + IndirectRetTy = DirectArgTy; + } + if (!isPotentiallyIndirect(IRArg)) { + IndirectArgs.push_back(DirectArg); + } else { + IndirectArgs.push_back(IndirectArg); + if (!(IRArg.Flags & IRTArg::INDIRECT_HAS_SIZE)) + IndirectArgs.push_back(IndirectArgSize); + } + } + + auto DirectName = + IConf.getRTName(IO.IP.isPRE() ? "pre_" : "post_", IO.getName(), ""); + auto IndirectName = + IConf.getRTName(IO.IP.isPRE() ? "pre_" : "post_", IO.getName(), "_ind"); + auto MakeSignature = [&](std::string &RetTy, std::string &Name, + SmallVectorImpl<std::string> &Args) { + return RetTy + Name + "(" + join(Args, ", ") + ")"; + }; + + if (RetTy) { + auto UserRetTy = getAsCType(RetTy, 0).first; + assert((DirectRetTy == UserRetTy || DirectRetTy == "void ") && + (IndirectRetTy == UserRetTy || IndirectRetTy == "void ") && + "Explicit return type but also implicit one!"); + IndirectRetTy = DirectRetTy = UserRetTy; + } + if (RequiresIndirection) + return {"", MakeSignature(IndirectRetTy, IndirectName, IndirectArgs)}; + if (!MightRequireIndirection) + return {MakeSignature(DirectRetTy, DirectName, DirectArgs), ""}; + return {MakeSignature(DirectRetTy, DirectName, DirectArgs), + MakeSignature(IndirectRetTy, IndirectName, IndirectArgs)}; +} + +void printRuntimeStub(const InstrumentationConfig &IConf, + StringRef StubRuntimeName, LLVMContext &Ctx) { + if (StubRuntimeName.empty()) + return; + + std::error_code EC; + raw_fd_ostream OS(StubRuntimeName, EC); + if (EC) { + Ctx.emitError( + Twine("failed to open instrumentor stub runtime file for writing: ") + + EC.message()); + return; + } + + OS << "// LLVM Instrumentor stub runtime\n\n"; + OS << "#include <stdint.h>\n"; + OS << "#include <stdio.h>\n\n"; + + for (auto &ChoiceMap : IConf.IChoices) { + for (auto &[_, IO] : ChoiceMap) { + if (!IO->Enabled) + continue; + IRTCallDescription IRTCallDesc(*IO, IO->getRetTy(Ctx)); + const auto Signatures = IRTCallDesc.createCSignature(IConf); + const auto Bodies = IRTCallDesc.createCBodies(); + if (!Signatures.first.empty()) { + OS << Signatures.first << " {\n"; + OS << " " << Bodies.first << "}\n\n"; + } + if (!Signatures.second.empty()) { + OS << Signatures.second << " {\n"; + OS << " " << Bodies.second << "}\n\n"; + } + } + } +} + +} // end namespace instrumentor +} // end namespace llvm diff --git a/llvm/test/Instrumentation/Instrumentor/bad_rt_config.json b/llvm/test/Instrumentation/Instrumentor/bad_rt_config.json new file mode 100644 index 0000000000000..d36966c0451a9 --- /dev/null +++ b/llvm/test/Instrumentation/Instrumentor/bad_rt_config.json @@ -0,0 +1,105 @@ +{ + "configuration": { + "runtime_prefix": "__instrumentor_", + "runtime_prefix.description": "The runtime API prefix.", + "runtime_stubs_file": ".", + "runtime_stubs_file.description": "The file into which runtime stubs should be written." + }, + "instruction_pre": { + "load": { + "enabled": true, + "pointer": true, + "pointer.replace": true, + "pointer.description": "The accessed pointer.", + "pointer_as": true, + "pointer_as.description": "The address space of the accessed pointer.", + "value_size": true, + "value_size.description": "The size of the loaded value.", + "alignment": true, + "alignment.description": "The known access alignment.", + "value_type_id": true, + "value_type_id.description": "The type id of the loaded value.", + "atomicity_ordering": true, + "atomicity_ordering.description": "The atomicity ordering of the load.", + "sync_scope_id": true, + "sync_scope_id.description": "The sync scope id of the load.", + "is_volatile": true, + "is_volatile.description": "Flag indicating a volatile load.", + "id": true, + "id.description": "A unique ID associated with the given instrumentor call" + }, + "store": { + "enabled": true, + "pointer": true, + "pointer.replace": true, + "pointer.description": "The accessed pointer.", + "pointer_as": true, + "pointer_as.description": "The address space of the accessed pointer.", + "value": true, + "value.description": "The stored value.", + "value_size": true, + "value_size.description": "The size of the stored value.", + "alignment": true, + "alignment.description": "The known access alignment.", + "value_type_id": true, + "value_type_id.description": "The type id of the stored value.", + "atomicity_ordering": true, + "atomicity_ordering.description": "The atomicity ordering of the store.", + "sync_scope_id": true, + "sync_scope_id.description": "The sync scope id of the store.", + "is_volatile": true, + "is_volatile.description": "Flag indicating a volatile store.", + "id": true, + "id.description": "A unique ID associated with the given instrumentor call" + } + }, + "instruction_post": { + "load": { + "enabled": true, + "pointer": true, + "pointer.description": "The accessed pointer.", + "pointer_as": true, + "pointer_as.description": "The address space of the accessed pointer.", + "value": true, + "value.replace": true, + "value.description": "The loaded value.", + "value_size": true, + "value_size.description": "The size of the loaded value.", + "alignment": true, + "alignment.description": "The known access alignment.", + "value_type_id": true, + "value_type_id.description": "The type id of the loaded value.", + "atomicity_ordering": true, + "atomicity_ordering.description": "The atomicity ordering of the load.", + "sync_scope_id": true, + "sync_scope_id.description": "The sync scope id of the load.", + "is_volatile": true, + "is_volatile.description": "Flag indicating a volatile load.", + "id": true, + "id.description": "A unique ID associated with the given instrumentor call" + }, + "store": { + "enabled": true, + "pointer": true, + "pointer.description": "The accessed pointer.", + "pointer_as": true, + "pointer_as.description": "The address space of the accessed pointer.", + "value": true, + "value.description": "The stored value.", + "value_size": true, + "value_size.description": "The size of the stored value.", + "alignment": true, + "alignment.description": "The known access alignment.", + "value_type_id": true, + "value_type_id.description": "The type id of the stored value.", + "atomicity_ordering": true, + "atomicity_ordering.description": "The atomicity ordering of the store.", + "sync_scope_id": true, + "sync_scope_id.description": "The sync scope id of the store.", + "is_volatile": true, + "is_volatile.description": "Flag indicating a volatile store.", + "id": true, + "id.description": "A unique ID associated with the given instrumentor call" + } + } +} diff --git a/llvm/test/Instrumentation/Instrumentor/default_config.json b/llvm/test/Instrumentation/Instrumentor/default_config.json index 2765d5c0116d2..263ab58e2566d 100644 --- a/llvm/test/Instrumentation/Instrumentor/default_config.json +++ b/llvm/test/Instrumentation/Instrumentor/default_config.json @@ -2,6 +2,8 @@ "configuration": { "runtime_prefix": "__instrumentor_", "runtime_prefix.description": "The runtime API prefix.", + "runtime_stubs_file": "", + "runtime_stubs_file.description": "The file into which runtime stubs should be written.", "target_regex": "", "target_regex.description": "Regular expression to be matched against the module target. Only targets that match this regex will be instrumented", "host_enabled": true, diff --git a/llvm/test/Instrumentation/Instrumentor/default_rt b/llvm/test/Instrumentation/Instrumentor/default_rt new file mode 100644 index 0000000000000..1e9750b2f6874 --- /dev/null +++ b/llvm/test/Instrumentation/Instrumentor/default_rt @@ -0,0 +1,37 @@ +// LLVM Instrumentor stub runtime + +#include <stdint.h> +#include <stdio.h> + +void *__instrumentor_pre_load(void *pointer, int32_t pointer_as, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int8_t is_volatile, int32_t id) { + printf("load pre -- pointer: %p, pointer_as: %i, value_size: %lli, alignment: %lli, value_type_id: %i, atomicity_ordering: %i, sync_scope_id: %i, is_volatile: %i, id: %i\n", pointer, pointer_as, value_size, alignment, value_type_id, atomicity_ordering, sync_scope_id, is_volatile, id); + return pointer; +} + +void *__instrumentor_pre_store(void *pointer, int32_t pointer_as, int64_t value, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int8_t is_volatile, int32_t id) { + printf("store pre -- pointer: %p, pointer_as: %i, value: %lli, value_size: %lli, alignment: %lli, value_type_id: %i, atomicity_ordering: %i, sync_scope_id: %i, is_volatile: %i, id: %i\n", pointer, pointer_as, value, value_size, alignment, value_type_id, atomicity_ordering, sync_scope_id, is_volatile, id); + return pointer; +} + +void *__instrumentor_pre_store_ind(void *pointer, int32_t pointer_as, int64_t *value_ptr, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int8_t is_volatile, int32_t id) { + printf("store pre -- pointer: %p, pointer_as: %i, value: %p, value_size: %lli, alignment: %lli, value_type_id: %i, atomicity_ordering: %i, sync_scope_id: %i, is_volatile: %i, id: %i\n", pointer, pointer_as, value_ptr, value_size, alignment, value_type_id, atomicity_ordering, sync_scope_id, is_volatile, id); + return pointer; +} + +int64_t __instrumentor_post_load(void *pointer, int32_t pointer_as, int64_t value, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int8_t is_volatile, int32_t id) { + printf("load post -- pointer: %p, pointer_as: %i, value: %lli, value_size: %lli, alignment: %lli, value_type_id: %i, atomicity_ordering: %i, sync_scope_id: %i, is_volatile: %i, id: %i\n", pointer, pointer_as, value, value_size, alignment, value_type_id, atomicity_ordering, sync_scope_id, is_volatile, id); + return value; +} + +void __instrumentor_post_load_ind(void *pointer, int32_t pointer_as, int64_t *value_ptr, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int8_t is_volatile, int32_t id) { + printf("load post -- pointer: %p, pointer_as: %i, value: %p, value_size: %lli, alignment: %lli, value_type_id: %i, atomicity_ordering: %i, sync_scope_id: %i, is_volatile: %i, id: %i\n", pointer, pointer_as, value_ptr, value_size, alignment, value_type_id, atomicity_ordering, sync_scope_id, is_volatile, id); +} + +void __instrumentor_post_store(void *pointer, int32_t pointer_as, int64_t value, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int8_t is_volatile, int32_t id) { + printf("store post -- pointer: %p, pointer_as: %i, value: %lli, value_size: %lli, alignment: %lli, value_type_id: %i, atomicity_ordering: %i, sync_scope_id: %i, is_volatile: %i, id: %i\n", pointer, pointer_as, value, value_size, alignment, value_type_id, atomicity_ordering, sync_scope_id, is_volatile, id); +} + +void __instrumentor_post_store_ind(void *pointer, int32_t pointer_as, int64_t *value_ptr, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int8_t is_volatile, int32_t id) { + printf("store post -- pointer: %p, pointer_as: %i, value: %p, value_size: %lli, alignment: %lli, value_type_id: %i, atomicity_ordering: %i, sync_scope_id: %i, is_volatile: %i, id: %i\n", pointer, pointer_as, value_ptr, value_size, alignment, value_type_id, atomicity_ordering, sync_scope_id, is_volatile, id); +} + diff --git a/llvm/test/Instrumentation/Instrumentor/generate_bad_rt.ll b/llvm/test/Instrumentation/Instrumentor/generate_bad_rt.ll new file mode 100644 index 0000000000000..2254f4fc2bd2a --- /dev/null +++ b/llvm/test/Instrumentation/Instrumentor/generate_bad_rt.ll @@ -0,0 +1,3 @@ +; RUN: not opt < %s -passes=instrumentor -instrumentor-read-config-file=%S/bad_rt_config.json 2>&1 | FileCheck %s + +; CHECK: error: failed to open instrumentor stub runtime file for writing: Is a directory diff --git a/llvm/test/Instrumentation/Instrumentor/generate_rt.ll b/llvm/test/Instrumentation/Instrumentor/generate_rt.ll new file mode 100644 index 0000000000000..645a1f935165b --- /dev/null +++ b/llvm/test/Instrumentation/Instrumentor/generate_rt.ll @@ -0,0 +1,2 @@ +; RUN: opt < %s -passes=instrumentor -instrumentor-read-config-file=%S/rt_config.json -S +; RUN: diff rt.c %S/default_rt diff --git a/llvm/test/Instrumentation/Instrumentor/load_store_config.json b/llvm/test/Instrumentation/Instrumentor/load_store_config.json index b96a02a4e09ea..1cc1f0e152543 100644 --- a/llvm/test/Instrumentation/Instrumentor/load_store_config.json +++ b/llvm/test/Instrumentation/Instrumentor/load_store_config.json @@ -2,7 +2,7 @@ "configuration": { "runtime_prefix": "__instrumentor_", "runtime_prefix.description": "The runtime API prefix.", - "runtime_stubs_file": "rt.c", + "runtime_stubs_file": "", "runtime_stubs_file.description": "The file into which runtime stubs should be written.", "demangle_function_names": true, "demangle_function_names.description": "Demangle functions names passed to the runtime." diff --git a/llvm/test/Instrumentation/Instrumentor/load_store_noreplace_config.json b/llvm/test/Instrumentation/Instrumentor/load_store_noreplace_config.json index f59de1c010adf..251148e075008 100644 --- a/llvm/test/Instrumentation/Instrumentor/load_store_noreplace_config.json +++ b/llvm/test/Instrumentation/Instrumentor/load_store_noreplace_config.json @@ -2,7 +2,7 @@ "configuration": { "runtime_prefix": "__instrumentor_", "runtime_prefix.description": "The runtime API prefix.", - "runtime_stubs_file": "rt.c", + "runtime_stubs_file": "", "runtime_stubs_file.description": "The file into which runtime stubs should be written.", "demangle_function_names": true, "demangle_function_names.description": "Demangle functions names passed to the runtime." diff --git a/llvm/test/Instrumentation/Instrumentor/rt_config.json b/llvm/test/Instrumentation/Instrumentor/rt_config.json new file mode 100644 index 0000000000000..2af8f11eb9ad3 --- /dev/null +++ b/llvm/test/Instrumentation/Instrumentor/rt_config.json @@ -0,0 +1,105 @@ +{ + "configuration": { + "runtime_prefix": "__instrumentor_", + "runtime_prefix.description": "The runtime API prefix.", + "runtime_stubs_file": "rt.c", + "runtime_stubs_file.description": "The file into which runtime stubs should be written." + }, + "instruction_pre": { + "load": { + "enabled": true, + "pointer": true, + "pointer.replace": true, + "pointer.description": "The accessed pointer.", + "pointer_as": true, + "pointer_as.description": "The address space of the accessed pointer.", + "value_size": true, + "value_size.description": "The size of the loaded value.", + "alignment": true, + "alignment.description": "The known access alignment.", + "value_type_id": true, + "value_type_id.description": "The type id of the loaded value.", + "atomicity_ordering": true, + "atomicity_ordering.description": "The atomicity ordering of the load.", + "sync_scope_id": true, + "sync_scope_id.description": "The sync scope id of the load.", + "is_volatile": true, + "is_volatile.description": "Flag indicating a volatile load.", + "id": true, + "id.description": "A unique ID associated with the given instrumentor call" + }, + "store": { + "enabled": true, + "pointer": true, + "pointer.replace": true, + "pointer.description": "The accessed pointer.", + "pointer_as": true, + "pointer_as.description": "The address space of the accessed pointer.", + "value": true, + "value.description": "The stored value.", + "value_size": true, + "value_size.description": "The size of the stored value.", + "alignment": true, + "alignment.description": "The known access alignment.", + "value_type_id": true, + "value_type_id.description": "The type id of the stored value.", + "atomicity_ordering": true, + "atomicity_ordering.description": "The atomicity ordering of the store.", + "sync_scope_id": true, + "sync_scope_id.description": "The sync scope id of the store.", + "is_volatile": true, + "is_volatile.description": "Flag indicating a volatile store.", + "id": true, + "id.description": "A unique ID associated with the given instrumentor call" + } + }, + "instruction_post": { + "load": { + "enabled": true, + "pointer": true, + "pointer.description": "The accessed pointer.", + "pointer_as": true, + "pointer_as.description": "The address space of the accessed pointer.", + "value": true, + "value.replace": true, + "value.description": "The loaded value.", + "value_size": true, + "value_size.description": "The size of the loaded value.", + "alignment": true, + "alignment.description": "The known access alignment.", + "value_type_id": true, + "value_type_id.description": "The type id of the loaded value.", + "atomicity_ordering": true, + "atomicity_ordering.description": "The atomicity ordering of the load.", + "sync_scope_id": true, + "sync_scope_id.description": "The sync scope id of the load.", + "is_volatile": true, + "is_volatile.description": "Flag indicating a volatile load.", + "id": true, + "id.description": "A unique ID associated with the given instrumentor call" + }, + "store": { + "enabled": true, + "pointer": true, + "pointer.description": "The accessed pointer.", + "pointer_as": true, + "pointer_as.description": "The address space of the accessed pointer.", + "value": true, + "value.description": "The stored value.", + "value_size": true, + "value_size.description": "The size of the stored value.", + "alignment": true, + "alignment.description": "The known access alignment.", + "value_type_id": true, + "value_type_id.description": "The type id of the stored value.", + "atomicity_ordering": true, + "atomicity_ordering.description": "The atomicity ordering of the store.", + "sync_scope_id": true, + "sync_scope_id.description": "The sync scope id of the store.", + "is_volatile": true, + "is_volatile.description": "Flag indicating a volatile store.", + "id": true, + "id.description": "A unique ID associated with the given instrumentor call" + } + } +} _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits