[Instrumentor] Move instrumentor stub library into its own header file (#199329)
This patch depends on #198366. It moves the instrumentor runtime helper header into its own file and makes it accessible as a string value to the instrumentor pass.
This commit is contained in:
1 parent
4910eda2a0
commit
7964b66bf5
5 files changed
+403
-341
No files matched your search
@@ -2,6 +2,15 @@
|
||||
# LLVM_HEADERS_TABLEGEN points to `llvm-min-tblgen`
|
||||
set(LLVM_TABLEGEN_PROJECT LLVM_HEADERS)
|
||||
|
||||
# Read instrumentor runtime helper header to a string for use in
|
||||
# instrumentor pass
|
||||
file(READ
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Transforms/IPO/InstrumentorRuntimeHelper.h
|
||||
LLVM_INSTRUMENTOR_RUNTIME_HELPER)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Transforms/IPO/InstrumentorVariables.inc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Transforms/IPO/InstrumentorVariables.inc @ONLY)
|
||||
|
||||
add_subdirectory(Analysis)
|
||||
add_subdirectory(CodeGen)
|
||||
add_subdirectory(IR)
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
//===-- Instrumentor Runtime Helper Header -------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This header provides helper structures and functions for reading data
|
||||
// generated by the LLVM Instrumentor pass and passed to runtime functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef INSTRUMENTOR_RUNTIME_H
|
||||
#define INSTRUMENTOR_RUNTIME_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Header for each value in a value pack. Value packs are used to pass function
|
||||
/// arguments and other variable-length data to the runtime. The format is:
|
||||
/// [ValueHeader][Padding][Value Data]
|
||||
/// where padding aligns the value data to 8-byte boundaries.
|
||||
typedef struct {
|
||||
uint32_t size; // Size of the value in bytes
|
||||
uint32_t type_id; // LLVM Type::TypeID of the value
|
||||
} ValuePackHeader;
|
||||
|
||||
/// Iterator for reading values from a value pack.
|
||||
typedef struct {
|
||||
const char *current; // Current position in the pack
|
||||
uint64_t offset; // Byte offset from the start
|
||||
uint32_t count; // Number of elements in the pack
|
||||
uint32_t index; // Current element index
|
||||
} ValuePackIterator;
|
||||
|
||||
/// Initialize a value pack iterator.
|
||||
/// \param iter The iterator to initialize
|
||||
/// \param pack_ptr Pointer to the start of the value pack
|
||||
/// \param num_elements Number of elements in the pack
|
||||
static inline void initValuePackIterator(ValuePackIterator *iter,
|
||||
const void *pack_ptr,
|
||||
uint32_t num_elements) {
|
||||
iter->current = (const char *)pack_ptr;
|
||||
iter->offset = 0;
|
||||
iter->count = num_elements;
|
||||
iter->index = 0;
|
||||
}
|
||||
|
||||
/// Get the header for the current value.
|
||||
static inline ValuePackHeader
|
||||
getValuePackHeader(const ValuePackIterator *iter) {
|
||||
const ValuePackHeader *header = (const ValuePackHeader *)iter->current;
|
||||
return *header;
|
||||
}
|
||||
|
||||
/// Get a pointer to the current value data.
|
||||
static inline const void *getValuePackData(const ValuePackIterator *iter) {
|
||||
// Skip header (8 bytes: size + type_id)
|
||||
const char *data_start = iter->current + sizeof(ValuePackHeader);
|
||||
// Calculate padding for 8-byte alignment
|
||||
ValuePackHeader header = getValuePackHeader(iter);
|
||||
uint32_t padding = (8 - (header.size % 8)) % 8;
|
||||
// Skip padding
|
||||
return data_start + padding;
|
||||
}
|
||||
|
||||
/// Move to the next value in the pack.
|
||||
static inline void nextValuePack(ValuePackIterator *iter) {
|
||||
if (iter->index >= iter->count) {
|
||||
iter->current = NULL;
|
||||
return;
|
||||
}
|
||||
ValuePackHeader header = getValuePackHeader(iter);
|
||||
uint32_t padding = (8 - (header.size % 8)) % 8;
|
||||
uint64_t advance = sizeof(ValuePackHeader) + padding + header.size;
|
||||
iter->current += advance;
|
||||
iter->offset += advance;
|
||||
iter->index++;
|
||||
}
|
||||
|
||||
/// Get the current offset in bytes from the start of the pack.
|
||||
static inline uint64_t getValuePackOffset(const ValuePackIterator *iter) {
|
||||
return iter->offset;
|
||||
}
|
||||
|
||||
/// Extract a specific value from a value pack by index.
|
||||
///
|
||||
/// \param pack_ptr Pointer to the start of the value pack
|
||||
/// \param num_elements Number of elements in the pack
|
||||
/// \param index Zero-based index of the value to extract
|
||||
/// \param header Output parameter for the value header (can be NULL)
|
||||
/// \return Pointer to the value data, or NULL if index is out of bounds
|
||||
static inline const void *getValuePackEntry(const void *pack_ptr,
|
||||
uint32_t num_elements,
|
||||
uint32_t index,
|
||||
ValuePackHeader *header) {
|
||||
if (!pack_ptr || index >= num_elements)
|
||||
return NULL;
|
||||
|
||||
ValuePackIterator iter;
|
||||
initValuePackIterator(&iter, pack_ptr, num_elements);
|
||||
|
||||
while (iter.current != NULL && iter.index < iter.count) {
|
||||
ValuePackHeader h = getValuePackHeader(&iter);
|
||||
if (iter.index == index) {
|
||||
if (header)
|
||||
*header = h;
|
||||
return getValuePackData(&iter);
|
||||
}
|
||||
nextValuePack(&iter);
|
||||
}
|
||||
|
||||
return NULL; // Index out of bounds
|
||||
}
|
||||
|
||||
/// LLVM Type IDs for interpreting value pack data.
|
||||
/// These correspond to llvm::Type::TypeID enum values.
|
||||
enum LLVMTypeID {
|
||||
HalfTyID = 0, ///< 16-bit floating point type
|
||||
BFloatTyID, ///< 16-bit floating point type (7-bit significand)
|
||||
FloatTyID, ///< 32-bit floating point type
|
||||
DoubleTyID, ///< 64-bit floating point type
|
||||
X86_FP80TyID, ///< 80-bit floating point type (X87)
|
||||
FP128TyID, ///< 128-bit floating point type (112-bit significand)
|
||||
PPC_FP128TyID, ///< 128-bit floating point type (two 64-bits, PowerPC)
|
||||
VoidTyID, ///< type with no size
|
||||
LabelTyID, ///< Labels
|
||||
MetadataTyID, ///< Metadata
|
||||
X86_AMXTyID, ///< AMX vectors (8192 bits, X86 specific)
|
||||
TokenTyID, ///< Tokens
|
||||
// Derived types... see DerivedTypes.h file.
|
||||
IntegerTyID, ///< Arbitrary bit width integers
|
||||
ByteTyID, ///< Arbitrary bit width bytes
|
||||
FunctionTyID, ///< Functions
|
||||
PointerTyID, ///< Pointers
|
||||
StructTyID, ///< Structures
|
||||
ArrayTyID, ///< Arrays
|
||||
FixedVectorTyID, ///< Fixed width SIMD vector type
|
||||
ScalableVectorTyID, ///< Scalable SIMD vector type
|
||||
TypedPointerTyID, ///< Typed pointer used by some GPU targets
|
||||
TargetExtTyID, ///< Target extension type
|
||||
};
|
||||
|
||||
/// Get the string name of an LLVM Type ID.
|
||||
static inline const char *getLLVMTypeIDName(uint32_t type_id) {
|
||||
switch (type_id) {
|
||||
case HalfTyID:
|
||||
return "half";
|
||||
case BFloatTyID:
|
||||
return "bfloat";
|
||||
case FloatTyID:
|
||||
return "float";
|
||||
case DoubleTyID:
|
||||
return "double";
|
||||
case X86_FP80TyID:
|
||||
return "x86_fp80";
|
||||
case FP128TyID:
|
||||
return "fp128";
|
||||
case PPC_FP128TyID:
|
||||
return "ppc_fp128";
|
||||
case VoidTyID:
|
||||
return "void";
|
||||
case LabelTyID:
|
||||
return "label";
|
||||
case MetadataTyID:
|
||||
return "metadata";
|
||||
case X86_AMXTyID:
|
||||
return "x86_amx";
|
||||
case TokenTyID:
|
||||
return "token";
|
||||
case IntegerTyID:
|
||||
return "integer";
|
||||
case ByteTyID:
|
||||
return "integer";
|
||||
case FunctionTyID:
|
||||
return "function";
|
||||
case PointerTyID:
|
||||
return "pointer";
|
||||
case StructTyID:
|
||||
return "struct";
|
||||
case ArrayTyID:
|
||||
return "array";
|
||||
case FixedVectorTyID:
|
||||
return "fixed_vector";
|
||||
case ScalableVectorTyID:
|
||||
return "scalable_vector";
|
||||
case TypedPointerTyID:
|
||||
return "typed_pointer";
|
||||
case TargetExtTyID:
|
||||
return "target_ext";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
// C++ overlays for range-based iteration and quality of life improvements
|
||||
|
||||
/// Range wrapper for value packs enabling range-based for loops.
|
||||
/// Example:
|
||||
/// for (auto val : ValuePackRange(pack_ptr, num_elements)) {
|
||||
/// // val provides access to header and data
|
||||
/// }
|
||||
class ValuePackRange {
|
||||
public:
|
||||
struct ValueRef {
|
||||
ValuePackHeader header;
|
||||
const void *data;
|
||||
|
||||
uint32_t type_id() const { return header.type_id; }
|
||||
uint32_t size() const { return header.size; }
|
||||
const char *type_name() const { return getLLVMTypeIDName(header.type_id); }
|
||||
|
||||
template <typename T> const T &as() const {
|
||||
return *static_cast<const T *>(data);
|
||||
}
|
||||
template <typename T> const T *ptr() const {
|
||||
return static_cast<const T *>(data);
|
||||
}
|
||||
};
|
||||
|
||||
class iterator {
|
||||
public:
|
||||
iterator(const void *ptr, uint32_t num_elements, uint64_t max_offset)
|
||||
: max_offset_(max_offset) {
|
||||
initValuePackIterator(&iter_, ptr, num_elements);
|
||||
if (ptr && !is_valid_position())
|
||||
iter_.current = nullptr;
|
||||
}
|
||||
|
||||
ValueRef operator*() const {
|
||||
return ValueRef{getValuePackHeader(&iter_), getValuePackData(&iter_)};
|
||||
}
|
||||
|
||||
iterator &operator++() {
|
||||
nextValuePack(&iter_);
|
||||
if (!is_valid_position())
|
||||
iter_.current = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator &other) const {
|
||||
return iter_.current != other.iter_.current;
|
||||
}
|
||||
|
||||
private:
|
||||
bool is_valid_position() const {
|
||||
if (!iter_.current)
|
||||
return false;
|
||||
if (iter_.index >= iter_.count)
|
||||
return false;
|
||||
if (max_offset_ > 0 && iter_.offset >= max_offset_)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
ValuePackIterator iter_;
|
||||
uint64_t max_offset_;
|
||||
};
|
||||
|
||||
ValuePackRange(const void *ptr, uint32_t num_elements, uint64_t max_size = 0)
|
||||
: ptr_(ptr), num_elements_(num_elements), max_size_(max_size) {}
|
||||
|
||||
iterator begin() const { return iterator(ptr_, num_elements_, max_size_); }
|
||||
iterator end() const { return iterator(nullptr, 0, 0); }
|
||||
|
||||
private:
|
||||
const void *ptr_;
|
||||
uint32_t num_elements_;
|
||||
uint64_t max_size_;
|
||||
};
|
||||
|
||||
/// Template helper to extract a typed value from a value pack by index.
|
||||
template <typename T>
|
||||
inline const T *getValueAs(const void *pack_ptr, uint32_t num_elements,
|
||||
uint32_t index) {
|
||||
return static_cast<const T *>(
|
||||
getValuePackEntry(pack_ptr, num_elements, index, nullptr));
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // INSTRUMENTOR_RUNTIME_H
|
||||
@@ -0,0 +1,18 @@
|
||||
//===-- InstrumentorVariables.inc.in - instrumentor variables -*- C++ -*---===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is configured by the build system to define a variable containing
|
||||
// instrumentor runtime library source code for use by the instrumentor pass.
|
||||
//
|
||||
// The variant of this file not ending with .in has been autogenerated by the
|
||||
// LLVM build. Do not edit!
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
constexpr char InstrumentorRuntimeHelper[] =
|
||||
R"(@LLVM_INSTRUMENTOR_RUNTIME_HELPER@)";
|
||||
@@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/IPO/Instrumentor.h"
|
||||
#include "llvm/Transforms/IPO/InstrumentorVariables.inc"
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
@@ -242,298 +243,8 @@ void printRuntimeHeader(const InstrumentationConfig &IConf,
|
||||
|
||||
StringRef Prefix = IConf.getRTName();
|
||||
|
||||
OS << "//===-- Instrumentor Runtime Helper Header "
|
||||
"-------------------------------===//\n";
|
||||
OS << "//\n";
|
||||
OS << "// Part of the LLVM Project, under the Apache License v2.0 with LLVM "
|
||||
"Exceptions.\n";
|
||||
OS << "// See https://llvm.org/LICENSE.txt for license information.\n";
|
||||
OS << "// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n";
|
||||
OS << "//\n";
|
||||
OS << "//"
|
||||
"===-------------------------------------------------------------------"
|
||||
"---===//\n";
|
||||
OS << "//\n";
|
||||
OS << "// This header provides helper structures and functions for reading "
|
||||
"data\n";
|
||||
OS << "// generated by the LLVM Instrumentor pass and passed to runtime "
|
||||
"functions.\n";
|
||||
OS << "//\n";
|
||||
OS << "// Generated with runtime prefix: " << Prefix << "\n";
|
||||
OS << "//\n";
|
||||
OS << "//"
|
||||
"===-------------------------------------------------------------------"
|
||||
"---===//\n\n";
|
||||
|
||||
OS << "#ifndef INSTRUMENTOR_RUNTIME_H\n";
|
||||
OS << "#define INSTRUMENTOR_RUNTIME_H\n\n";
|
||||
|
||||
OS << "#ifdef __cplusplus\n";
|
||||
OS << "extern \"C\" {\n";
|
||||
OS << "#endif\n\n";
|
||||
|
||||
OS << "#include <stdint.h>\n";
|
||||
OS << "#include <string.h>\n\n";
|
||||
|
||||
OS << "#ifdef __cplusplus\n";
|
||||
OS << "}\n";
|
||||
OS << "#endif\n\n";
|
||||
|
||||
// Value pack structures
|
||||
OS << "/// Header for each value in a value pack.\n";
|
||||
OS << "/// Value packs are used to pass function arguments and other "
|
||||
"variable-length\n";
|
||||
OS << "/// data to the runtime. The format is:\n";
|
||||
OS << "/// [ValueHeader][Padding][Value Data]\n";
|
||||
OS << "/// where padding aligns the value data to 8-byte boundaries.\n";
|
||||
OS << "typedef struct {\n";
|
||||
OS << " uint32_t size; // Size of the value in bytes\n";
|
||||
OS << " uint32_t type_id; // LLVM Type::TypeID of the value\n";
|
||||
OS << "} ValuePackHeader;\n\n";
|
||||
|
||||
// Value pack iterator
|
||||
OS << "/// Iterator for reading values from a value pack.\n";
|
||||
OS << "typedef struct {\n";
|
||||
OS << " const char *current; // Current position in the pack\n";
|
||||
OS << " uint64_t offset; // Byte offset from the start\n";
|
||||
OS << " uint32_t count; // Number of elements in the pack\n";
|
||||
OS << " uint32_t index; // Current element index\n";
|
||||
OS << "} ValuePackIterator;\n\n";
|
||||
|
||||
OS << "/// Initialize a value pack iterator.\n";
|
||||
OS << "/// \\param iter The iterator to initialize\n";
|
||||
OS << "/// \\param pack_ptr Pointer to the start of the value pack\n";
|
||||
OS << "/// \\param num_elements Number of elements in the pack\n";
|
||||
OS << "static inline void initValuePackIterator(ValuePackIterator *iter, "
|
||||
"const void *pack_ptr, uint32_t num_elements) {\n";
|
||||
OS << " iter->current = (const char *)pack_ptr;\n";
|
||||
OS << " iter->offset = 0;\n";
|
||||
OS << " iter->count = num_elements;\n";
|
||||
OS << " iter->index = 0;\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "/// Get the header for the current value.\n";
|
||||
OS << "static inline ValuePackHeader getValuePackHeader(const "
|
||||
"ValuePackIterator *iter) {\n";
|
||||
OS << " const ValuePackHeader *header = (const ValuePackHeader "
|
||||
"*)iter->current;\n";
|
||||
OS << " return *header;\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "/// Get a pointer to the current value data.\n";
|
||||
OS << "static inline const void *getValuePackData(const ValuePackIterator "
|
||||
"*iter) {\n";
|
||||
OS << " // Skip header (8 bytes: size + type_id)\n";
|
||||
OS << " const char *data_start = iter->current + sizeof(ValuePackHeader);\n";
|
||||
OS << " // Calculate padding for 8-byte alignment\n";
|
||||
OS << " ValuePackHeader header = getValuePackHeader(iter);\n";
|
||||
OS << " uint32_t padding = (8 - (header.size % 8)) % 8;\n";
|
||||
OS << " // Skip padding\n";
|
||||
OS << " return data_start + padding;\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "/// Move to the next value in the pack.\n";
|
||||
OS << "static inline void nextValuePack(ValuePackIterator *iter) {\n";
|
||||
OS << " if (iter->index >= iter->count) {\n";
|
||||
OS << " iter->current = NULL;\n";
|
||||
OS << " return;\n";
|
||||
OS << " }\n";
|
||||
OS << " ValuePackHeader header = getValuePackHeader(iter);\n";
|
||||
OS << " uint32_t padding = (8 - (header.size % 8)) % 8;\n";
|
||||
OS << " uint64_t advance = sizeof(ValuePackHeader) + padding + "
|
||||
"header.size;\n";
|
||||
OS << " iter->current += advance;\n";
|
||||
OS << " iter->offset += advance;\n";
|
||||
OS << " iter->index++;\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "/// Get the current offset in bytes from the start of the pack.\n";
|
||||
OS << "static inline uint64_t getValuePackOffset(const ValuePackIterator "
|
||||
"*iter) {\n";
|
||||
OS << " return iter->offset;\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "/// Extract a specific value from a value pack by index.\n";
|
||||
OS << "///\n";
|
||||
OS << "/// \\param pack_ptr Pointer to the start of the value pack\n";
|
||||
OS << "/// \\param num_elements Number of elements in the pack\n";
|
||||
OS << "/// \\param index Zero-based index of the value to extract\n";
|
||||
OS << "/// \\param header Output parameter for the value header (can be "
|
||||
"NULL)\n";
|
||||
OS << "/// \\return Pointer to the value data, or NULL if index is out of "
|
||||
"bounds\n";
|
||||
OS << "static inline const void *getValuePackEntry(const void *pack_ptr, "
|
||||
"uint32_t num_elements,\n";
|
||||
OS << " uint32_t index, "
|
||||
"ValuePackHeader *header) {\n";
|
||||
OS << " if (!pack_ptr || index >= num_elements)\n";
|
||||
OS << " return NULL;\n\n";
|
||||
OS << " ValuePackIterator iter;\n";
|
||||
OS << " initValuePackIterator(&iter, pack_ptr, num_elements);\n\n";
|
||||
OS << " while (iter.current != NULL && iter.index < iter.count) {\n";
|
||||
OS << " ValuePackHeader h = getValuePackHeader(&iter);\n";
|
||||
OS << " if (iter.index == index) {\n";
|
||||
OS << " if (header)\n";
|
||||
OS << " *header = h;\n";
|
||||
OS << " return getValuePackData(&iter);\n";
|
||||
OS << " }\n";
|
||||
OS << " nextValuePack(&iter);\n";
|
||||
OS << " }\n\n";
|
||||
OS << " return NULL; // Index out of bounds\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
// LLVM Type IDs enum
|
||||
OS << "/// LLVM Type IDs for interpreting value pack data.\n";
|
||||
OS << "/// These correspond to llvm::Type::TypeID enum values.\n";
|
||||
OS << "enum LLVMTypeID {\n";
|
||||
OS << " HalfTyID = 0, ///< 16-bit floating point type\n";
|
||||
OS << " BFloatTyID, ///< 16-bit floating point type (7-bit "
|
||||
"significand)\n";
|
||||
OS << " FloatTyID, ///< 32-bit floating point type\n";
|
||||
OS << " DoubleTyID, ///< 64-bit floating point type\n";
|
||||
OS << " X86_FP80TyID, ///< 80-bit floating point type (X87)\n";
|
||||
OS << " FP128TyID, ///< 128-bit floating point type (112-bit "
|
||||
"significand)\n";
|
||||
OS << " PPC_FP128TyID, ///< 128-bit floating point type (two 64-bits, "
|
||||
"PowerPC)\n";
|
||||
OS << " VoidTyID, ///< type with no size\n";
|
||||
OS << " LabelTyID, ///< Labels\n";
|
||||
OS << " MetadataTyID, ///< Metadata\n";
|
||||
OS << " X86_AMXTyID, ///< AMX vectors (8192 bits, X86 specific)\n";
|
||||
OS << " TokenTyID, ///< Tokens\n";
|
||||
|
||||
OS << " // Derived types... see DerivedTypes.h file.\n";
|
||||
OS << " IntegerTyID, ///< Arbitrary bit width integers\n";
|
||||
OS << " ByteTyID, ///< Arbitrary bit width bytes\n";
|
||||
OS << " FunctionTyID, ///< Functions\n";
|
||||
OS << " PointerTyID, ///< Pointers\n";
|
||||
OS << " StructTyID, ///< Structures\n";
|
||||
OS << " ArrayTyID, ///< Arrays\n";
|
||||
OS << " FixedVectorTyID, ///< Fixed width SIMD vector type\n";
|
||||
OS << " ScalableVectorTyID, ///< Scalable SIMD vector type\n";
|
||||
OS << " TypedPointerTyID, ///< Typed pointer used by some GPU targets\n";
|
||||
OS << " TargetExtTyID, ///< Target extension type\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
// Type ID printer function
|
||||
OS << "/// Get the string name of an LLVM Type ID.\n";
|
||||
OS << "static inline const char *getLLVMTypeIDName(uint32_t type_id) {\n";
|
||||
OS << " switch (type_id) {\n";
|
||||
OS << " case HalfTyID: return \"half\";\n";
|
||||
OS << " case BFloatTyID: return \"bfloat\";\n";
|
||||
OS << " case FloatTyID: return \"float\";\n";
|
||||
OS << " case DoubleTyID: return \"double\";\n";
|
||||
OS << " case X86_FP80TyID: return \"x86_fp80\";\n";
|
||||
OS << " case FP128TyID: return \"fp128\";\n";
|
||||
OS << " case PPC_FP128TyID: return \"ppc_fp128\";\n";
|
||||
OS << " case VoidTyID: return \"void\";\n";
|
||||
OS << " case LabelTyID: return \"label\";\n";
|
||||
OS << " case MetadataTyID: return \"metadata\";\n";
|
||||
OS << " case X86_AMXTyID: return \"x86_amx\";\n";
|
||||
OS << " case TokenTyID: return \"token\";\n";
|
||||
OS << " case IntegerTyID: return \"integer\";\n";
|
||||
OS << " case ByteTyID: return \"integer\";\n";
|
||||
OS << " case FunctionTyID: return \"function\";\n";
|
||||
OS << " case PointerTyID: return \"pointer\";\n";
|
||||
OS << " case StructTyID: return \"struct\";\n";
|
||||
OS << " case ArrayTyID: return \"array\";\n";
|
||||
OS << " case FixedVectorTyID: return \"fixed_vector\";\n";
|
||||
OS << " case ScalableVectorTyID: return \"scalable_vector\";\n";
|
||||
OS << " case TypedPointerTyID: return \"typed_pointer\";\n";
|
||||
OS << " case TargetExtTyID: return \"target_ext\";\n";
|
||||
OS << " default: return \"unknown\";\n";
|
||||
OS << " }\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
// C++ overlays section
|
||||
OS << "#ifdef __cplusplus\n\n";
|
||||
|
||||
OS << "// C++ overlays for range-based iteration and quality of life "
|
||||
"improvements\n\n";
|
||||
|
||||
// ValuePackRange class
|
||||
OS << "/// Range wrapper for value packs enabling range-based for loops.\n";
|
||||
OS << "/// Example:\n";
|
||||
OS << "/// for (auto val : ValuePackRange(pack_ptr, num_elements)) {\n";
|
||||
OS << "/// // val provides access to header and data\n";
|
||||
OS << "/// }\n";
|
||||
OS << "class ValuePackRange {\n";
|
||||
OS << "public:\n";
|
||||
OS << " struct ValueRef {\n";
|
||||
OS << " ValuePackHeader header;\n";
|
||||
OS << " const void *data;\n\n";
|
||||
OS << " uint32_t type_id() const { return header.type_id; }\n";
|
||||
OS << " uint32_t size() const { return header.size; }\n";
|
||||
OS << " const char *type_name() const { return "
|
||||
"getLLVMTypeIDName(header.type_id); }\n\n";
|
||||
OS << " template <typename T> const T &as() const {\n";
|
||||
OS << " return *static_cast<const T*>(data);\n";
|
||||
OS << " }\n";
|
||||
OS << " template <typename T> const T *ptr() const {\n";
|
||||
OS << " return static_cast<const T*>(data);\n";
|
||||
OS << " }\n";
|
||||
OS << " };\n\n";
|
||||
|
||||
OS << " class iterator {\n";
|
||||
OS << " public:\n";
|
||||
OS << " iterator(const void *ptr, uint32_t num_elements, uint64_t "
|
||||
"max_offset)\n";
|
||||
OS << " : max_offset_(max_offset) {\n";
|
||||
OS << " initValuePackIterator(&iter_, ptr, num_elements);\n";
|
||||
OS << " if (ptr && !is_valid_position()) iter_.current = nullptr;\n";
|
||||
OS << " }\n\n";
|
||||
OS << " ValueRef operator*() const {\n";
|
||||
OS << " return ValueRef{\n";
|
||||
OS << " getValuePackHeader(&iter_),\n";
|
||||
OS << " getValuePackData(&iter_)\n";
|
||||
OS << " };\n";
|
||||
OS << " }\n\n";
|
||||
OS << " iterator &operator++() {\n";
|
||||
OS << " nextValuePack(&iter_);\n";
|
||||
OS << " if (!is_valid_position()) iter_.current = nullptr;\n";
|
||||
OS << " return *this;\n";
|
||||
OS << " }\n\n";
|
||||
OS << " bool operator!=(const iterator &other) const {\n";
|
||||
OS << " return iter_.current != other.iter_.current;\n";
|
||||
OS << " }\n\n";
|
||||
OS << " private:\n";
|
||||
OS << " bool is_valid_position() const {\n";
|
||||
OS << " if (!iter_.current) return false;\n";
|
||||
OS << " if (iter_.index >= iter_.count) return false;\n";
|
||||
OS << " if (max_offset_ > 0 && iter_.offset >= max_offset_) return "
|
||||
"false;\n";
|
||||
OS << " return true;\n";
|
||||
OS << " }\n\n";
|
||||
OS << " ValuePackIterator iter_;\n";
|
||||
OS << " uint64_t max_offset_;\n";
|
||||
OS << " };\n\n";
|
||||
|
||||
OS << " ValuePackRange(const void *ptr, uint32_t num_elements, uint64_t "
|
||||
"max_size = 0)\n";
|
||||
OS << " : ptr_(ptr), num_elements_(num_elements), max_size_(max_size) "
|
||||
"{}\n\n";
|
||||
OS << " iterator begin() const { return iterator(ptr_, num_elements_, "
|
||||
"max_size_); }\n";
|
||||
OS << " iterator end() const { return iterator(nullptr, 0, 0); }\n\n";
|
||||
OS << "private:\n";
|
||||
OS << " const void *ptr_;\n";
|
||||
OS << " uint32_t num_elements_;\n";
|
||||
OS << " uint64_t max_size_;\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
// Helper template functions
|
||||
OS << "/// Template helper to extract a typed value from a value pack by "
|
||||
"index.\n";
|
||||
OS << "template <typename T>\n";
|
||||
OS << "inline const T *getValueAs(const void *pack_ptr, uint32_t "
|
||||
"num_elements, uint32_t index) {\n";
|
||||
OS << " return static_cast<const T*>(getValuePackEntry(pack_ptr, "
|
||||
"num_elements, index, nullptr));\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "#endif // __cplusplus\n\n";
|
||||
|
||||
OS << "#endif // INSTRUMENTOR_RUNTIME_H\n";
|
||||
OS << InstrumentorRuntimeHelper;
|
||||
OS << "\n// Generated with runtime prefix: " << Prefix << "\n";
|
||||
}
|
||||
|
||||
void printRuntimeStub(const InstrumentationConfig &IConf,
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
// This header provides helper structures and functions for reading data
|
||||
// generated by the LLVM Instrumentor pass and passed to runtime functions.
|
||||
//
|
||||
// Generated with runtime prefix: __instrumentor_
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef INSTRUMENTOR_RUNTIME_H
|
||||
@@ -27,9 +25,8 @@ extern "C" {
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Header for each value in a value pack.
|
||||
/// Value packs are used to pass function arguments and other variable-length
|
||||
/// data to the runtime. The format is:
|
||||
/// Header for each value in a value pack. Value packs are used to pass function
|
||||
/// arguments and other variable-length data to the runtime. The format is:
|
||||
/// [ValueHeader][Padding][Value Data]
|
||||
/// where padding aligns the value data to 8-byte boundaries.
|
||||
typedef struct {
|
||||
@@ -39,17 +36,19 @@ typedef struct {
|
||||
|
||||
/// Iterator for reading values from a value pack.
|
||||
typedef struct {
|
||||
const char *current; // Current position in the pack
|
||||
uint64_t offset; // Byte offset from the start
|
||||
uint32_t count; // Number of elements in the pack
|
||||
uint32_t index; // Current element index
|
||||
const char *current; // Current position in the pack
|
||||
uint64_t offset; // Byte offset from the start
|
||||
uint32_t count; // Number of elements in the pack
|
||||
uint32_t index; // Current element index
|
||||
} ValuePackIterator;
|
||||
|
||||
/// Initialize a value pack iterator.
|
||||
/// \param iter The iterator to initialize
|
||||
/// \param pack_ptr Pointer to the start of the value pack
|
||||
/// \param num_elements Number of elements in the pack
|
||||
static inline void initValuePackIterator(ValuePackIterator *iter, const void *pack_ptr, uint32_t num_elements) {
|
||||
static inline void initValuePackIterator(ValuePackIterator *iter,
|
||||
const void *pack_ptr,
|
||||
uint32_t num_elements) {
|
||||
iter->current = (const char *)pack_ptr;
|
||||
iter->offset = 0;
|
||||
iter->count = num_elements;
|
||||
@@ -57,7 +56,8 @@ static inline void initValuePackIterator(ValuePackIterator *iter, const void *pa
|
||||
}
|
||||
|
||||
/// Get the header for the current value.
|
||||
static inline ValuePackHeader getValuePackHeader(const ValuePackIterator *iter) {
|
||||
static inline ValuePackHeader
|
||||
getValuePackHeader(const ValuePackIterator *iter) {
|
||||
const ValuePackHeader *header = (const ValuePackHeader *)iter->current;
|
||||
return *header;
|
||||
}
|
||||
@@ -99,8 +99,10 @@ static inline uint64_t getValuePackOffset(const ValuePackIterator *iter) {
|
||||
/// \param index Zero-based index of the value to extract
|
||||
/// \param header Output parameter for the value header (can be NULL)
|
||||
/// \return Pointer to the value data, or NULL if index is out of bounds
|
||||
static inline const void *getValuePackEntry(const void *pack_ptr, uint32_t num_elements,
|
||||
uint32_t index, ValuePackHeader *header) {
|
||||
static inline const void *getValuePackEntry(const void *pack_ptr,
|
||||
uint32_t num_elements,
|
||||
uint32_t index,
|
||||
ValuePackHeader *header) {
|
||||
if (!pack_ptr || index >= num_elements)
|
||||
return NULL;
|
||||
|
||||
@@ -151,29 +153,52 @@ enum LLVMTypeID {
|
||||
/// Get the string name of an LLVM Type ID.
|
||||
static inline const char *getLLVMTypeIDName(uint32_t type_id) {
|
||||
switch (type_id) {
|
||||
case HalfTyID: return "half";
|
||||
case BFloatTyID: return "bfloat";
|
||||
case FloatTyID: return "float";
|
||||
case DoubleTyID: return "double";
|
||||
case X86_FP80TyID: return "x86_fp80";
|
||||
case FP128TyID: return "fp128";
|
||||
case PPC_FP128TyID: return "ppc_fp128";
|
||||
case VoidTyID: return "void";
|
||||
case LabelTyID: return "label";
|
||||
case MetadataTyID: return "metadata";
|
||||
case X86_AMXTyID: return "x86_amx";
|
||||
case TokenTyID: return "token";
|
||||
case IntegerTyID: return "integer";
|
||||
case ByteTyID: return "integer";
|
||||
case FunctionTyID: return "function";
|
||||
case PointerTyID: return "pointer";
|
||||
case StructTyID: return "struct";
|
||||
case ArrayTyID: return "array";
|
||||
case FixedVectorTyID: return "fixed_vector";
|
||||
case ScalableVectorTyID: return "scalable_vector";
|
||||
case TypedPointerTyID: return "typed_pointer";
|
||||
case TargetExtTyID: return "target_ext";
|
||||
default: return "unknown";
|
||||
case HalfTyID:
|
||||
return "half";
|
||||
case BFloatTyID:
|
||||
return "bfloat";
|
||||
case FloatTyID:
|
||||
return "float";
|
||||
case DoubleTyID:
|
||||
return "double";
|
||||
case X86_FP80TyID:
|
||||
return "x86_fp80";
|
||||
case FP128TyID:
|
||||
return "fp128";
|
||||
case PPC_FP128TyID:
|
||||
return "ppc_fp128";
|
||||
case VoidTyID:
|
||||
return "void";
|
||||
case LabelTyID:
|
||||
return "label";
|
||||
case MetadataTyID:
|
||||
return "metadata";
|
||||
case X86_AMXTyID:
|
||||
return "x86_amx";
|
||||
case TokenTyID:
|
||||
return "token";
|
||||
case IntegerTyID:
|
||||
return "integer";
|
||||
case ByteTyID:
|
||||
return "integer";
|
||||
case FunctionTyID:
|
||||
return "function";
|
||||
case PointerTyID:
|
||||
return "pointer";
|
||||
case StructTyID:
|
||||
return "struct";
|
||||
case ArrayTyID:
|
||||
return "array";
|
||||
case FixedVectorTyID:
|
||||
return "fixed_vector";
|
||||
case ScalableVectorTyID:
|
||||
return "scalable_vector";
|
||||
case TypedPointerTyID:
|
||||
return "typed_pointer";
|
||||
case TargetExtTyID:
|
||||
return "target_ext";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,10 +222,10 @@ public:
|
||||
const char *type_name() const { return getLLVMTypeIDName(header.type_id); }
|
||||
|
||||
template <typename T> const T &as() const {
|
||||
return *static_cast<const T*>(data);
|
||||
return *static_cast<const T *>(data);
|
||||
}
|
||||
template <typename T> const T *ptr() const {
|
||||
return static_cast<const T*>(data);
|
||||
return static_cast<const T *>(data);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -209,19 +234,18 @@ public:
|
||||
iterator(const void *ptr, uint32_t num_elements, uint64_t max_offset)
|
||||
: max_offset_(max_offset) {
|
||||
initValuePackIterator(&iter_, ptr, num_elements);
|
||||
if (ptr && !is_valid_position()) iter_.current = nullptr;
|
||||
if (ptr && !is_valid_position())
|
||||
iter_.current = nullptr;
|
||||
}
|
||||
|
||||
ValueRef operator*() const {
|
||||
return ValueRef{
|
||||
getValuePackHeader(&iter_),
|
||||
getValuePackData(&iter_)
|
||||
};
|
||||
return ValueRef{getValuePackHeader(&iter_), getValuePackData(&iter_)};
|
||||
}
|
||||
|
||||
iterator &operator++() {
|
||||
nextValuePack(&iter_);
|
||||
if (!is_valid_position()) iter_.current = nullptr;
|
||||
if (!is_valid_position())
|
||||
iter_.current = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -231,9 +255,12 @@ public:
|
||||
|
||||
private:
|
||||
bool is_valid_position() const {
|
||||
if (!iter_.current) return false;
|
||||
if (iter_.index >= iter_.count) return false;
|
||||
if (max_offset_ > 0 && iter_.offset >= max_offset_) return false;
|
||||
if (!iter_.current)
|
||||
return false;
|
||||
if (iter_.index >= iter_.count)
|
||||
return false;
|
||||
if (max_offset_ > 0 && iter_.offset >= max_offset_)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -255,10 +282,14 @@ private:
|
||||
|
||||
/// Template helper to extract a typed value from a value pack by index.
|
||||
template <typename T>
|
||||
inline const T *getValueAs(const void *pack_ptr, uint32_t num_elements, uint32_t index) {
|
||||
return static_cast<const T*>(getValuePackEntry(pack_ptr, num_elements, index, nullptr));
|
||||
inline const T *getValueAs(const void *pack_ptr, uint32_t num_elements,
|
||||
uint32_t index) {
|
||||
return static_cast<const T *>(
|
||||
getValuePackEntry(pack_ptr, num_elements, index, nullptr));
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // INSTRUMENTOR_RUNTIME_H
|
||||
|
||||
// Generated with runtime prefix: __instrumentor_
|
||||
Reference in new issue
Block a user