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

Reply via email to