14#include "llvm/Transforms/IPO/InstrumentorVariables.inc"
25#include <system_error>
36 if (Ty->isIntegerTy()) {
37 auto BW = Ty->getIntegerBitWidth();
39 return {
"bool ",
"bool *"};
40 auto S =
"int" + std::to_string(BW) +
"_t ";
43 if (Ty->isPointerTy())
46 return {
"float ",
"float *"};
48 return {
"double ",
"double *"};
56 if (Ty->isIntegerTy()) {
57 if (Ty->getIntegerBitWidth() > 32) {
58 assert(Ty->getIntegerBitWidth() == 64);
59 return "%\" PRId64 \"";
61 return "%\" PRId32 \"";
63 if (Ty->isPointerTy())
73 std::string DirectFormat =
"printf(\"" +
IO.getName().str() +
74 (
IO.IP.isPRE() ?
" pre" :
" post") +
" -- ";
75 std::string IndirectFormat = DirectFormat;
76 std::string DirectArg, IndirectArg, DirectReturnValue, IndirectReturnValue;
78 auto AddToFormats = [&](
Twine S) {
79 DirectFormat += S.str();
80 IndirectFormat += S.str();
82 auto AddToArgs = [&](
Twine S) {
84 IndirectArg += S.str();
87 for (
auto &IRArg :
IO.IRTArgs) {
93 AddToArgs(
", " + IRArg.Name);
94 AddToFormats(IRArg.Name +
": ");
96 DirectReturnValue = IRArg.Name;
98 IndirectReturnValue = IRArg.Name;
103 DirectFormat +=
"[value pack at %p]";
104 IndirectFormat +=
"[value pack at %p]";
112 IndirectFormat +=
"%p";
113 IndirectArg +=
"_ptr";
116 IndirectFormat +=
", " + IRArg.Name.str() +
"_size: %\" PRId32 \"";
117 IndirectArg +=
", " + IRArg.Name.str() +
"_size";
122 std::string DirectBody = DirectFormat +
"\\n\"" + DirectArg +
");\n";
123 std::string IndirectBody = IndirectFormat +
"\\n\"" + IndirectArg +
");\n";
126 for (
size_t ArgIdx = 0; ArgIdx <
IO.IRTArgs.size(); ++ArgIdx) {
127 auto &IRArg =
IO.IRTArgs[ArgIdx];
132 std::string CountParam;
133 for (
int PrevIdx = ArgIdx - 1; PrevIdx >= 0; --PrevIdx) {
134 if (
IO.IRTArgs[PrevIdx].Enabled &&
135 IO.IRTArgs[PrevIdx].Name.equals_insensitive(
136 (
"num_" + IRArg.Name).str())) {
137 CountParam =
IO.IRTArgs[PrevIdx].Name.str();
143 if (CountParam.empty())
144 CountParam =
"0 /* count not enabled! */";
146 auto AddToBodies = [&](
Twine T) {
147 DirectBody +=
T.str();
148 IndirectBody +=
T.str();
152 AddToBodies(
" ValuePackIterator iter_" + IRArg.Name.str() +
";\n");
153 AddToBodies(
" initValuePackIterator(&iter_" + IRArg.Name.str() +
", " +
154 IRArg.Name.str() +
", " + CountParam +
");\n");
155 AddToBodies(
" while (iter_" + IRArg.Name.str() +
".index < iter_" +
156 IRArg.Name.str() +
".count) {\n");
157 AddToBodies(
" ValuePackHeader header_" + IRArg.Name.str() +
158 " = getValuePackHeader(&iter_" + IRArg.Name.str() +
");\n");
159 AddToBodies(
" const void *data_" + IRArg.Name.str() +
160 " = getValuePackData(&iter_" + IRArg.Name.str() +
");\n");
161 AddToBodies(
" printf(\" [%" PRIu32
"] type=%s size=%" PRIu32
162 " data=%p\\n\", iter_" +
163 IRArg.Name.str() +
".index, getLLVMTypeIDName(header_" +
164 IRArg.Name.str() +
".type_id), header_" + IRArg.Name.str() +
165 ".size, data_" + IRArg.Name.str() +
");\n");
166 AddToBodies(
" nextValuePack(&iter_" + IRArg.Name.str() +
");\n");
171 IndirectReturnValue = DirectReturnValue =
"0";
172 if (!DirectReturnValue.empty())
173 DirectBody +=
" return " + DirectReturnValue +
";\n";
174 if (!IndirectReturnValue.empty())
175 IndirectBody +=
" return " + IndirectReturnValue +
";\n";
176 return {DirectBody, IndirectBody};
179std::pair<std::string, std::string>
182 std::string DirectRetTy =
"void ", IndirectRetTy =
"void ";
183 for (
auto &IRArg :
IO.IRTArgs) {
186 const auto &[DirectArgTy, IndirectArgTy] =
188 std::string DirectArg = DirectArgTy + IRArg.Name.str();
189 std::string IndirectArg = IndirectArgTy + IRArg.Name.str() +
"_ptr";
190 std::string IndirectArgSize =
"int32_t " + IRArg.Name.str() +
"_size";
193 DirectRetTy = DirectArgTy;
195 IndirectRetTy = DirectArgTy;
207 IConf.
getRTName(
IO.IP.isPRE() ?
"pre_" :
"post_",
IO.getName(),
"");
209 IConf.
getRTName(
IO.IP.isPRE() ?
"pre_" :
"post_",
IO.getName(),
"_ind");
210 auto MakeSignature = [&](std::string &
RetTy, std::string &Name,
212 return RetTy + Name +
"(" +
join(Args,
", ") +
")";
217 assert((DirectRetTy == UserRetTy || DirectRetTy ==
"void ") &&
218 (IndirectRetTy == UserRetTy || IndirectRetTy ==
"void ") &&
219 "Explicit return type but also implicit one!");
220 IndirectRetTy = DirectRetTy = UserRetTy;
223 return {
"", MakeSignature(IndirectRetTy, IndirectName, IndirectArgs)};
225 return {MakeSignature(DirectRetTy, DirectName, DirectArgs),
""};
226 return {MakeSignature(DirectRetTy, DirectName, DirectArgs),
227 MakeSignature(IndirectRetTy, IndirectName, IndirectArgs)};
232 if (HeaderFileName.
empty())
239 Twine(
"failed to open instrumentor runtime header file for writing: ") +
246 OS << InstrumentorRuntimeHelper;
247 OS <<
"\n// Generated with runtime prefix: " << Prefix <<
"\n";
252 if (StubRuntimeName.
empty())
259 Twine(
"failed to open instrumentor stub runtime file for writing: ") +
266 std::string HeaderFileName = StubRuntimeName.
str();
267 size_t DotPos = HeaderFileName.rfind(
'.');
268 if (DotPos != std::string::npos)
269 HeaderFileName = HeaderFileName.substr(0, DotPos);
270 HeaderFileName +=
".h";
273 OS <<
"//===-- Instrumentor Runtime Stub "
274 "-----------------------------------------===//\n";
276 OS <<
"// Part of the LLVM Project, under the Apache License v2.0 with LLVM "
278 OS <<
"// See https://llvm.org/LICENSE.txt for license information.\n";
279 OS <<
"// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n";
282 "===-------------------------------------------------------------------"
285 OS <<
"// This file is auto-generated by the LLVM Instrumentor pass.\n";
286 OS <<
"// It provides stub implementations of instrumentation runtime "
288 OS <<
"// that print human-readable information about instrumentation "
291 OS <<
"// Generated with runtime prefix: " << Prefix <<
"\n";
294 "===-------------------------------------------------------------------"
296 OS <<
"#include <inttypes.h>\n";
297 OS <<
"#include <stdint.h>\n";
298 OS <<
"#include <stdio.h>\n";
300 OS <<
"#ifdef __cplusplus\n";
301 OS <<
"extern \"C\" {\n";
304 for (
auto &ChoiceMap : IConf.
IChoices) {
305 for (
auto &[
_, IO] : ChoiceMap) {
311 if (!Signatures.first.empty()) {
312 OS << Signatures.first <<
" {\n";
313 OS <<
" " << Bodies.first <<
"}\n\n";
315 if (!Signatures.second.empty()) {
316 OS << Signatures.second <<
" {\n";
317 OS <<
" " << Bodies.second <<
"}\n\n";
322 OS <<
"#ifdef __cplusplus\n";
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the SmallVector class.
This is an important class for using LLVM in a threaded context.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
constexpr bool empty() const
Check if the string is empty.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
A raw_ostream that writes to a file descriptor.
static std::string getPrintfFormatString(Type *Ty, unsigned Flags)
Get the string representation of the C printf format of an argument with type Ty.
void printRuntimeHeader(const InstrumentationConfig &IConf, StringRef HeaderFileName, LLVMContext &Ctx)
Print the runtime header file that provides helper structures and functions for reading data generate...
static std::pair< std::string, std::string > getAsCType(Type *Ty, unsigned Flags)
Get the string representation of an argument with type Ty.
void printRuntimeStub(const InstrumentationConfig &IConf, StringRef StubRuntimeName, LLVMContext &Ctx)
Print a runtime stub file with the implementation of the instrumentation runtime functions correspond...
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
This is an optimization pass for GlobalISel generic memory operations.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
Helper to represent an instrumentation runtime function that is related to an instrumentation opportu...
bool MightRequireIndirection
Whether any argument may require indirection.
std::pair< std::string, std::string > createCBodies() const
Create a string representation of the function definition in C.
Type * RetTy
The return type of the instrumentation function.
InstrumentationOpportunity & IO
The instrumentation opportunity which it is linked to.
std::pair< std::string, std::string > createCSignature(const InstrumentationConfig &IConf) const
Create a string representation of the function declaration in C.
unsigned NumReplaceableArgs
The number of arguments that can be replaced.
bool RequiresIndirection
Whether the function requires indirection in some argument.
bool isPotentiallyIndirect(IRTArg &IRTA) const
Return whether the function may have any indirect argument.
The class that contains the configuration for the instrumentor.
EnumeratedArray< MapVector< StringRef, InstrumentationOpportunity * >, InstrumentationLocation::KindTy > IChoices
The map registered instrumentation opportunities.
StringRef getRTName() const
Get the runtime prefix for the instrumentation runtime functions.