LLVM 23.0.0git
Instrumentor.h
Go to the documentation of this file.
1//===-- Instrumentor.h - Highly configurable instrumentation pass ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// The Instrumentor, a highly configurable instrumentation pass.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_TRANSFORMS_IPO_INSTRUMENTOR_H
14#define LLVM_TRANSFORMS_IPO_INSTRUMENTOR_H
15
16#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/StringMap.h"
20#include "llvm/ADT/StringRef.h"
22#include "llvm/IR/Constants.h"
23#include "llvm/IR/DataLayout.h"
24#include "llvm/IR/IRBuilder.h"
25#include "llvm/IR/Instruction.h"
27#include "llvm/IR/LLVMContext.h"
28#include "llvm/IR/Module.h"
29#include "llvm/IR/PassManager.h"
35
36#include <cstdint>
37#include <functional>
38#include <memory>
39#include <string>
40#include <tuple>
41
42namespace llvm {
43namespace instrumentor {
44
47
48/// Callback type for getting/setting a value for a instrumented opportunity.
49///{
50using GetterCallbackTy = std::function<Value *(
52using SetterCallbackTy = std::function<Value *(
54///}
55
56/// Helper to represent an argument to an instrumentation runtime function.
57struct IRTArg {
58 /// Flags describing the possible properties of an argument.
60 NONE = 0,
61 STRING = 1 << 0,
62 REPLACABLE = 1 << 1,
67 };
68
69 /// Construct an argument.
76
77 /// Whether the argument is enabled and should be passed to the function call.
78 bool Enabled;
79
80 /// The type of the argument.
82
83 /// A string with the name of the argument.
85
86 /// A string with the description of the argument.
88
89 /// The flags that describe the properties of the argument. Multiple flags may
90 /// be specified.
91 unsigned Flags;
92
93 /// The callback for getting the value of the argument.
95
96 /// The callback for consuming the output value of the argument.
98
99 /// Whether the argument value can be cached between the PRE and POST calls.
101};
102
103/// Helper to represent an instrumentation runtime function that is related to
104/// an instrumentation opportunity.
106 /// Construct an instrumentation function description linked to the \p IO
107 /// instrumentation opportunity and \p RetTy return type.
109
110 /// Create the type of the instrumentation function.
113 const DataLayout &DL,
114 bool ForceIndirection);
115
116 /// Create a call instruction that calls to the instrumentation function and
117 /// passes the corresponding arguments.
120 InstrumentationCaches &ICaches);
121
122 /// Create a string representation of the function declaration in C. Two
123 /// strings are returned: the function definition with direct arguments and
124 /// the function with any indirect argument.
125 std::pair<std::string, std::string>
126 createCSignature(const InstrumentationConfig &IConf) const;
127
128 /// Create a string representation of the function definition in C. The
129 /// function body implements a stub and only prints the passed arguments. Two
130 /// strings are returned: the function definition with direct arguments and
131 /// the function with any indirect argument.
132 std::pair<std::string, std::string> createCBodies() const;
133
134 /// Return whether the \p IRTA argument can be replaced.
135 bool isReplacable(IRTArg &IRTA) const {
137 }
138
139 /// Return whether the function may have any indirect argument.
140 bool isPotentiallyIndirect(IRTArg &IRTA) const {
141 return ((IRTA.Flags & IRTArg::POTENTIALLY_INDIRECT) ||
143 }
144
145 /// Whether the function requires indirection in some argument.
147
148 /// Whether any argument may require indirection.
150
151 /// The number of arguments that can be replaced.
152 unsigned NumReplaceableArgs = 0;
153
154 /// The instrumentation opportunity which it is linked to.
156
157 /// The return type of the instrumentation function.
158 Type *RetTy = nullptr;
159};
160
161/// Helper to represent an instrumentation location, which is composed of an
162/// instrumentation opportunity type and a position.
164 /// The supported location kinds, which are composed of a opportunity type and
165 /// position. The PRE position indicates the instrumentation function call is
166 /// inserted before the instrumented event occurs. The POST position indicates
167 /// the instrumentation call is inserted after the event occurs. Some
168 /// opportunity types may only support one position.
182
183 /// Construct an instrumentation location that is not instrumenting an
184 /// instruction.
185 InstrumentationLocation(KindTy Kind) : Kind(Kind) {
186 assert(Kind != INSTRUCTION_PRE && Kind != INSTRUCTION_POST &&
187 "Opcode required!");
188 }
189
190 /// Construct an instrumentation location belonging to the instrumentation of
191 /// an instruction.
192 InstrumentationLocation(unsigned Opcode, bool IsPRE)
193 : Kind(IsPRE ? INSTRUCTION_PRE : INSTRUCTION_POST), Opcode(Opcode) {}
194
195 /// Return the type and position.
196 KindTy getKind() const { return Kind; }
197
198 /// Return the string representation given a location kind. This is the string
199 /// used in the configuration file.
201 switch (Kind) {
202 case MODULE_PRE:
203 return "module_pre";
204 case MODULE_POST:
205 return "module_post";
206 case GLOBAL_PRE:
207 return "global_pre";
208 case GLOBAL_POST:
209 return "global_post";
210 case FUNCTION_PRE:
211 return "function_pre";
212 case FUNCTION_POST:
213 return "function_post";
214 case BASIC_BLOCK_PRE:
215 return "basic_block_pre";
216 case BASIC_BLOCK_POST:
217 return "basic_block_post";
218 case INSTRUCTION_PRE:
219 return "instruction_pre";
220 case INSTRUCTION_POST:
221 return "instruction_post";
222 }
223 llvm_unreachable("Invalid kind!");
224 }
225
226 /// Return the location kind described by a string.
228 return StringSwitch<KindTy>(S)
229 .Case("module_pre", MODULE_PRE)
230 .Case("module_post", MODULE_POST)
231 .Case("global_pre", GLOBAL_PRE)
232 .Case("global_post", GLOBAL_POST)
233 .Case("function_pre", FUNCTION_PRE)
234 .Case("function_post", FUNCTION_POST)
235 .Case("basic_block_pre", BASIC_BLOCK_PRE)
236 .Case("basic_block_post", BASIC_BLOCK_POST)
237 .Case("instruction_pre", INSTRUCTION_PRE)
238 .Case("instruction_post", INSTRUCTION_POST)
239 .Default(Last);
240 }
241
242 /// Return whether a location kind is positioned before the event occurs.
243 static bool isPRE(KindTy Kind) {
244 switch (Kind) {
245 case MODULE_PRE:
246 case GLOBAL_PRE:
247 case FUNCTION_PRE:
248 case BASIC_BLOCK_PRE:
249 case INSTRUCTION_PRE:
250 return true;
251 case MODULE_POST:
252 case GLOBAL_POST:
253 case FUNCTION_POST:
254 case BASIC_BLOCK_POST:
255 case INSTRUCTION_POST:
256 return false;
257 }
258 llvm_unreachable("Invalid kind!");
259 }
260
261 /// Return whether the instrumentation location is before the event occurs.
262 bool isPRE() const { return isPRE(Kind); }
263
264 /// Get the opcode of the instruction instrumentation location. This function
265 /// may not be called by a non-instruction instrumentation location.
266 unsigned getOpcode() const {
267 assert((Kind == INSTRUCTION_PRE || Kind == INSTRUCTION_POST) &&
268 "Expected instruction!");
269 return Opcode;
270 }
271
272private:
273 /// The kind (type and position) of the instrumentation location.
274 const KindTy Kind;
275
276 /// The opcode for instruction instrumentation locations.
277 const unsigned Opcode = -1;
278};
279
280/// An option for the base configuration.
282 /// The possible types of options.
287
288 /// Create a boolean option with \p Name name, \p Description description and
289 /// \p DefaultValue as boolean default value.
290 static std::unique_ptr<BaseConfigurationOption>
292 StringRef Description, bool DefaultValue);
293
294 /// Create a string option with \p Name name, \p Description description and
295 /// \p DefaultValue as string default value.
296 static std::unique_ptr<BaseConfigurationOption>
298 StringRef Description, StringRef DefaultValue);
299
300 /// Helper union that holds any possible option type.
301 union ValueTy {
302 bool Bool;
304 };
305
306 /// Set and get of the boolean value. Only valid if it is a boolean option.
307 ///{
308 void setBool(bool B) {
309 assert(Kind == BOOLEAN && "Not a boolean!");
310 Value.Bool = B;
311 }
312 bool getBool() const {
313 assert(Kind == BOOLEAN && "Not a boolean!");
314 return Value.Bool;
315 }
316 ///}
317
318 /// Set and get the string value. Only valid if it is a boolean option.
319 ///{
321 assert(Kind == STRING && "Not a string!");
322 Value.String = S;
323 }
325 assert(Kind == STRING && "Not a string!");
326 return Value.String;
327 }
328 ///}
329
330 /// The information of the option.
331 ///{
336 ///}
337
338 /// Construct a base configuration option.
341};
342
343/// The class that contains the configuration for the instrumentor. It holds the
344/// information for each instrumented opportunity, including the base
345/// configuration options. Another class may inherit from this one to modify the
346/// default behavior.
349
350 /// Construct an instrumentation configuration with the base options.
352
353 /// Initialize the config to a clean base state without loosing cached values
354 /// that can be reused across configurations.
356 // Clear previous configurations but not the caches.
358 for (auto &Map : IChoices)
359 Map.clear();
360
362 *this, "runtime_prefix", "The runtime API prefix.", "__instrumentor_");
364 *this, "runtime_stubs_file",
365 "The file into which runtime stubs should be written.", "");
367 *this, "target_regex",
368 "Regular expression to be matched against the module target. "
369 "Only targets that match this regex will be instrumented.",
370 "");
372 *this, "function_regex",
373 "Regular expression to be matched against a function name. "
374 "Only functions that match this regex will be instrumented.",
375 "");
377 *this, "demangle_function_names",
378 "Demangle functions names passed to the runtime.", true);
380 *this, "host_enabled", "Instrument non-GPU targets", true);
382 *this, "gpu_enabled", "Instrument GPU targets", true);
383 populate(IIRB);
384 }
385
386 /// Populate the instrumentation opportunities.
387 virtual void populate(InstrumentorIRBuilderTy &IIRB);
388
389 /// Get the runtime prefix for the instrumentation runtime functions.
390 StringRef getRTName() const { return RuntimePrefix->getString(); }
391
392 /// Get the instrumentation function name.
393 std::string getRTName(StringRef Prefix, StringRef Name,
394 StringRef Suffix1 = "", StringRef Suffix2 = "") const {
395 return (getRTName() + Prefix + Name + Suffix1 + Suffix2).str();
396 }
397
398 /// Add the base configuration option \p BCO into the list of base options.
400 BaseConfigurationOptions.push_back(BCO);
401 }
402
403 /// Register instrumentation opportunity \p IO.
405
406 /// Allocate an object of type \p Ty using a bump allocator and construct it
407 /// with the \p Args arguments. The object may not be freed manually.
408 template <typename Ty, typename... ArgsTy>
409 static Ty *allocate(ArgsTy &&...Args) {
411 Ty *Obj = Allocator.Allocate();
412 new (Obj) Ty(std::forward<ArgsTy>(Args)...);
413 return Obj;
414 }
415
416 /// Mapping to remember global strings passed to the runtime.
418
419 /// Mapping from constants to globals with the constant as initializer.
421
423 Constant *&V = GlobalStringsMap[SS.save(S)];
424 if (!V) {
425 auto &M = *IIRB.IRB.GetInsertBlock()->getModule();
426 V = IIRB.IRB.CreateGlobalString(
427 S, getRTName() + ".str",
428 M.getDataLayout().getDefaultGlobalsAddressSpace(), &M);
429 if (V->getType() != IIRB.IRB.getPtrTy())
430 V = ConstantExpr::getAddrSpaceCast(V, IIRB.IRB.getPtrTy());
431 }
432 return V;
433 }
434 /// The list of enabled base configuration options.
436
437 /// The base configuration options.
438 std::unique_ptr<BaseConfigurationOption> RuntimePrefix;
439 std::unique_ptr<BaseConfigurationOption> RuntimeStubsFile;
440 std::unique_ptr<BaseConfigurationOption> DemangleFunctionNames;
441 std::unique_ptr<BaseConfigurationOption> TargetRegex;
442 std::unique_ptr<BaseConfigurationOption> FunctionRegex;
443 std::unique_ptr<BaseConfigurationOption> HostEnabled;
444 std::unique_ptr<BaseConfigurationOption> GPUEnabled;
445
446 /// The map registered instrumentation opportunities. The map is indexed by
447 /// the instrumentation location kind and then by the opportunity name. Notice
448 /// that an instrumentation location may have more than one instrumentation
449 /// opportunity registered.
453
454 /// Utilities for allocating and building strings.
455 ///{
458 ///}
459};
460
461/// Base class for instrumentation opportunities. All opportunities should
462/// inherit from this class and implement the virtual class members.
465
466 /// Construct an opportunity with location \p IP.
468
469 /// The instrumentation location of the opportunity.
471
472 /// The list of possible arguments for the instrumentation runtime function.
473 /// The order within the array determines the order of arguments. Arguments
474 /// may be disabled and will not be passed to the function call.
476
477 /// Whether the opportunity is enabled.
478 bool Enabled = true;
479
480 /// A filter expression to be matched against runtime property values. If the
481 /// filter is non-empty, only instrumentations matching the filter will be
482 /// executed. The filter syntax supports:
483 /// - Integer comparisons: ==, !=, <, >, <=, >=
484 /// - String comparisons: ==, != (with quoted strings)
485 /// - String prefix check: startswith("prefix")
486 /// - Logical operators: &&, ||
487 /// Examples:
488 /// "sync_scope_id==3 && atomicity_ordering>0"
489 /// "name==\"foo\" || name.startswith(\"test_\")"
490 /// If a property value is dynamic (not a constant), the filter is assumed to
491 /// pass (true).
493
494 /// Helpers to cast values, pass them to the runtime, and replace them. To be
495 /// used as part of the getter/setter of a InstrumentationOpportunity.
496 ///{
497 static Value *forceCast(Value &V, Type &Ty, InstrumentorIRBuilderTy &IIRB);
500 return forceCast(V, Ty, IIRB);
501 }
502 static Value *replaceValue(Value &V, Value &NewV,
505 ///}
506
507 /// Instrument the value \p V using the configuration \p IConf, and
508 /// potentially, the caches \p ICaches.
511 InstrumentationCaches &ICaches) {
512 if (CB && !CB(*V))
513 return nullptr;
514
515 // Check if the filter matches before instrumenting
516 if (!evaluateFilter(*V, *this, IConf, IIRB))
517 return nullptr;
518
519 const DataLayout &DL = IIRB.IRB.GetInsertBlock()->getDataLayout();
520 IRTCallDescription IRTCallDesc(*this, getRetTy(V->getContext()));
521 auto *CI = IRTCallDesc.createLLVMCall(V, IConf, IIRB, DL, ICaches);
522 return CI;
523 }
524
525 /// Get the return type for the instrumentation runtime function.
526 virtual Type *getRetTy(LLVMContext &Ctx) const { return nullptr; }
527
528 /// Get the name of the instrumentation opportunity.
529 virtual StringRef getName() const = 0;
530
531 /// Get the opcode of the instruction instrumentation opportunity. Only valid
532 /// if it is instruction instrumentation.
533 unsigned getOpcode() const { return IP.getOpcode(); }
534
535 /// Get the location kind of the instrumentation opportunity.
537 return IP.getKind();
538 }
539
540 /// An optional callback that takes the value that is about to be
541 /// instrumented and can return false if it should be skipped.
542 ///{
543 using CallbackTy = std::function<bool(Value &)>;
544 CallbackTy CB = nullptr;
545 ///}
546
547 /// Add arguments available in all instrumentation opportunities.
549 bool PassId) {
550 const auto CB = IP.isPRE() ? getIdPre : getIdPost;
551 if (PassId) {
552 IRTArgs.push_back(
554 "A unique ID associated with the given instrumentor call",
555 IRTArg::NONE, CB, nullptr, true, true));
556 }
557 }
558
559 /// Get the opportunity identifier for the pre and post positions.
560 ///{
561 static Value *getIdPre(Value &V, Type &Ty, InstrumentationConfig &IConf,
563 static Value *getIdPost(Value &V, Type &Ty, InstrumentationConfig &IConf,
565 ///}
566
567 /// Compute the opportunity identifier for the current instrumentation epoch
568 /// \p CurrentEpoch. The identifiers are assigned consecutively as the epoch
569 /// advances. Epochs may have no identifier assigned (e.g., because no id was
570 /// requested). This function always returns the same identifier when called
571 /// multiple times with the same epoch.
572 static int32_t getIdFromEpoch(uint32_t CurrentEpoch) {
573 static DenseMap<uint32_t, int32_t> EpochIdMap;
574 static int32_t GlobalId = 0;
575 int32_t &EpochId = EpochIdMap[CurrentEpoch];
576 if (EpochId == 0)
577 EpochId = ++GlobalId;
578 return EpochId;
579 }
580};
581
582/// The base instrumentation opportunity class for instruction opportunities.
583/// Each instruction opportunity should inherit from this class and implement
584/// the virtual class members.
585template <unsigned Opcode>
587 virtual ~InstructionIO() {}
588
589 /// Construct an instruction opportunity.
592
593 /// Get the name of the instruction.
594 StringRef getName() const override {
595 return Instruction::getOpcodeName(Opcode);
596 }
597};
598
599/// The instrumentation opportunity for functions.
606
617
618 struct ConfigTy final : public BaseConfigTy<ConfigKind> {
619 std::function<bool(Argument &)> ArgFilter;
620
623
624 StringRef getName() const override { return "function"; }
625
627 ConfigTy *UserConfig = nullptr);
628
629 static Value *getFunctionAddress(Value &V, Type &Ty,
632 static Value *getFunctionName(Value &V, Type &Ty,
641 static Value *isMainFunction(Value &V, Type &Ty, InstrumentationConfig &IConf,
643
644 static void populate(InstrumentationConfig &IConf,
646 auto *PreIO = IConf.allocate<FunctionIO>(true);
647 PreIO->init(IConf, IIRB);
648 auto *PostIO = IConf.allocate<FunctionIO>(false);
649 PostIO->init(IConf, IIRB);
650 }
651};
652
653/// The instrumentation opportunity for alloca instructions.
654struct AllocaIO final : public InstructionIO<Instruction::Alloca> {
655 AllocaIO(bool IsPRE) : InstructionIO(IsPRE) {}
656
666
669
671 ConfigTy *UserConfig = nullptr);
672
673 static Value *getSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
675 static Value *setSize(Value &V, Value &NewV, InstrumentationConfig &IConf,
677 static Value *getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf,
679
680 static void populate(InstrumentationConfig &IConf,
682 auto *PreIO = IConf.allocate<AllocaIO>(true);
683 PreIO->init(IConf, IIRB);
684 auto *PostIO = IConf.allocate<AllocaIO>(false);
685 PostIO->init(IConf, IIRB);
686 }
687};
688
689struct UnreachableIO final : public InstructionIO<Instruction::Unreachable> {
690 UnreachableIO() : InstructionIO<Instruction::Unreachable>(/*IsPRE=*/true) {}
691
696
699
701 ConfigTy *UserConfig = nullptr);
702
703 static void populate(InstrumentationConfig &IConf,
705 auto *PreIO = IConf.allocate<UnreachableIO>();
706 PreIO->init(IConf, IIRB);
707 }
708};
709
710// Module instrumentation opportunity.
712 ModuleIO(bool IsPRE)
714 IsPRE ? InstrumentationLocation::MODULE_PRE
715 : InstrumentationLocation::MODULE_POST)) {}
716
723
726
727 StringRef getName() const override { return "module"; }
728
730 ConfigTy *UserConfig = nullptr);
731
732 static Value *getModuleName(Value &V, Type &Ty, InstrumentationConfig &IConf,
734 static Value *getTargetTriple(Value &V, Type &Ty,
737
738 static void populate(InstrumentationConfig &IConf,
740 auto *PreIO = IConf.allocate<ModuleIO>(true);
741 PreIO->init(IConf, IIRB);
742 auto *PostIO = IConf.allocate<ModuleIO>(false);
743 PostIO->init(IConf, IIRB);
744 }
745};
746
747// Global variable instrumentation opportunity.
753
767
770
771 StringRef getName() const override { return "global"; }
772
774 ConfigTy *UserConfig = nullptr);
775
776 static Value *getAddress(Value &V, Type &Ty, InstrumentationConfig &IConf,
778 static Value *setAddress(Value &V, Value &NewV, InstrumentationConfig &IConf,
780 static Value *getAS(Value &V, Type &Ty, InstrumentationConfig &IConf,
782 static Value *getDeclaredSize(Value &V, Type &Ty,
785 static Value *getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf,
787 static Value *getSymbolName(Value &V, Type &Ty, InstrumentationConfig &IConf,
789 static Value *getInitialValue(Value &V, Type &Ty,
792 static Value *isConstant(Value &V, Type &Ty, InstrumentationConfig &IConf,
794 static Value *isDefinition(Value &V, Type &Ty, InstrumentationConfig &IConf,
796
797 static void populate(InstrumentationConfig &IConf,
799 auto *PreIO = IConf.allocate<GlobalVarIO>(true);
800 PreIO->init(IConf, IIRB);
801 auto *PostIO = IConf.allocate<GlobalVarIO>(false);
802 PostIO->init(IConf, IIRB);
803 }
804};
805
806/// The instrumentation opportunity for store instructions.
807struct StoreIO : public InstructionIO<Instruction::Store> {
808 virtual ~StoreIO() {};
809
810 /// Construct a store instruction opportunity.
811 StoreIO(bool IsPRE) : InstructionIO(IsPRE) {}
812
813 /// The selector of arguments for store opportunities.
814 ///{
829
832 ///}
833
834 /// Get the type of the stored value.
836 return IIRB.Int64Ty;
837 }
838
839 /// Initialize the store opportunity using the instrumentation config \p IConf
840 /// and the user config \p UserConfig.
842 ConfigTy *UserConfig = nullptr);
843
844 /// Getters and setters for the arguments of the instrumentation function for
845 /// the store opportunity.
846 ///{
847 static Value *getPointer(Value &V, Type &Ty, InstrumentationConfig &IConf,
849 static Value *setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf,
851 static Value *getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf,
853 static Value *getValue(Value &V, Type &Ty, InstrumentationConfig &IConf,
855 static Value *getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
857 static Value *getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf,
859 static Value *getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
861 static Value *getAtomicityOrdering(Value &V, Type &Ty,
864 static Value *getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
866 static Value *isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf,
868 ///}
869
870 /// Create the store opportunities for pre and post positions. The
871 /// opportunities are also initialized with the arguments for their
872 /// instrumentation calls.
873 static void populate(InstrumentationConfig &IConf,
875 auto *PreIO = IConf.allocate<StoreIO>(true);
876 PreIO->init(IConf, IIRB);
877 auto *PostIO = IConf.allocate<StoreIO>(false);
878 PostIO->init(IConf, IIRB);
879 }
880};
881
882/// The instrumentation opportunity for load instructions.
883struct LoadIO : public InstructionIO<Instruction::Load> {
884 virtual ~LoadIO() {};
885
886 /// Construct a load opportunity.
887 LoadIO(bool IsPRE) : InstructionIO(IsPRE) {}
888
889 /// The selector of arguments for load opportunities.
890 ///{
906
909 ///}
910
911 /// Get the type of the loaded value.
913 return IIRB.Int64Ty;
914 }
915
916 /// Initialize the load opportunity using the instrumentation config \p IConf
917 /// and the user config \p UserConfig.
919 ConfigTy *UserConfig = nullptr);
920
921 /// Getters and setters for the arguments of the instrumentation function for
922 /// the load opportunity.
923 ///{
924 static Value *getPointer(Value &V, Type &Ty, InstrumentationConfig &IConf,
926 static Value *setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf,
928 static Value *getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf,
930 static Value *getValue(Value &V, Type &Ty, InstrumentationConfig &IConf,
932 static Value *getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
934 static Value *getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf,
936 static Value *getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
938 static Value *getAtomicityOrdering(Value &V, Type &Ty,
941 static Value *getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
943 static Value *isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf,
945 ///}
946
947 /// Create the store opportunities for PRE and POST positions.
948 static void populate(InstrumentationConfig &IConf,
950 auto *PreIO = IConf.allocate<LoadIO>(true);
951 PreIO->init(IConf, IIRB);
952 auto *PostIO = IConf.allocate<LoadIO>(false);
953 PostIO->init(IConf, IIRB);
954 }
955};
956
957} // namespace instrumentor
958
959/// The Instrumentor pass.
960class InstrumentorPass : public RequiredPassInfoMixin<InstrumentorPass> {
961 using InstrumentationConfig = instrumentor::InstrumentationConfig;
962 using InstrumentorIRBuilderTy = instrumentor::InstrumentorIRBuilderTy;
963
964 /// File system to be used for read operations.
966
967 /// The configuration and IR builder provided by the user.
968 InstrumentationConfig *UserIConf;
969 InstrumentorIRBuilderTy *UserIIRB;
970
971 PreservedAnalyses run(Module &M, InstrumentationConfig &IConf,
972 InstrumentorIRBuilderTy &IIRB, bool ReadConfig);
973
974public:
975 /// Construct an instrumentor pass that will use the instrumentation
976 /// configuration \p IC and the IR builder \p IIRB. If an IR builder is not
977 /// provided, a default builder is used. When the configuration is not
978 /// provided, it is read from the config file if available and otherwise a
979 /// default configuration is used.
981 InstrumentationConfig *IC = nullptr,
982 InstrumentorIRBuilderTy *IIRB = nullptr);
983
985};
986
987} // end namespace llvm
988
989#endif // LLVM_TRANSFORMS_IPO_INSTRUMENTOR_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines an array type that can be indexed using scoped enum values.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
ModuleAnalysisManager MAM
Basic Register Allocator
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This is an important base class in LLVM.
Definition Constant.h:43
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Class to represent function types.
const char * getOpcodeName() const
InstrumentorPass(IntrusiveRefCntPtr< vfs::FileSystem > FS=nullptr, InstrumentationConfig *IC=nullptr, InstrumentorIRBuilderTy *IIRB=nullptr)
Construct an instrumentor pass that will use the instrumentation configuration IC and the IR builder ...
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
Definition Allocator.h:390
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.
Definition StringSaver.h:22
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:313
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::function< Value *( Value &, Value &, InstrumentationConfig &, InstrumentorIRBuilderTy &)> SetterCallbackTy
LLVM_ABI bool evaluateFilter(Value &V, InstrumentationOpportunity &IO, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Evaluate the filter expression against the current instrumentation opportunity.
std::function< Value *( Value &, Type &, InstrumentationConfig &, InstrumentorIRBuilderTy &)> GetterCallbackTy
Callback type for getting/setting a value for a instrumented opportunity.
This is an optimization pass for GlobalISel generic memory operations.
Op::Description Desc
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1916
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:383
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
@ Enable
Enable colors.
Definition WithColor.h:47
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:874
A CRTP mix-in for passes that should not be skipped.
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
}
BaseConfigTy< ConfigKind > ConfigTy
static Value * getSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * setSize(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Boolean option bitset with a compile-time number of bits to store as many options as the enumeration ...
An option for the base configuration.
void setBool(bool B)
Set and get of the boolean value.
static std::unique_ptr< BaseConfigurationOption > createStringOption(InstrumentationConfig &IC, StringRef Name, StringRef Description, StringRef DefaultValue)
Create a string option with Name name, Description description and DefaultValue as string default val...
BaseConfigurationOption(StringRef Name, StringRef Desc, KindTy Kind)
}
KindTy
The possible types of options.
static std::unique_ptr< BaseConfigurationOption > createBoolOption(InstrumentationConfig &IC, StringRef Name, StringRef Description, bool DefaultValue)
Create a boolean option with Name name, Description description and DefaultValue as boolean default v...
std::function< bool(Argument &)> ArgFilter
llvm::instrumentor::FunctionIO::ConfigTy Config
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
StringRef getName() const override
Get the name of the instrumentation opportunity.
Value * setArguments(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getFunctionAddress(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * isMainFunction(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Value * getArguments(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Value * getNumArguments(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getFunctionName(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
FunctionIO {.
static Value * setAddress(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
static Value * getAS(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getInitialValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * isDefinition(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getDeclaredSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
StringRef getName() const override
Get the name of the instrumentation opportunity.
static Value * getSymbolName(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAddress(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static Value * isConstant(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
GetterCallbackTy GetterCB
The callback for getting the value of the argument.
StringRef Description
A string with the description of the argument.
unsigned Flags
The flags that describe the properties of the argument.
Type * Ty
The type of the argument.
IRTArg(Type *Ty, StringRef Name, StringRef Description, unsigned Flags, GetterCallbackTy GetterCB, SetterCallbackTy SetterCB=nullptr, bool Enabled=true, bool NoCache=false)
Construct an argument.
bool Enabled
Whether the argument is enabled and should be passed to the function call.
SetterCallbackTy SetterCB
The callback for consuming the output value of the argument.
StringRef Name
A string with the name of the argument.
bool NoCache
Whether the argument value can be cached between the PRE and POST calls.
IRArgFlagTy
Flags describing the possible properties of an argument.
Helper to represent an instrumentation runtime function that is related to an instrumentation opportu...
bool isReplacable(IRTArg &IRTA) const
Return whether the IRTA argument can be replaced.
IRTCallDescription(InstrumentationOpportunity &IO, Type *RetTy=nullptr)
Construct an instrumentation function description linked to the IO instrumentation opportunity and Re...
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.
CallInst * createLLVMCall(Value *&V, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, const DataLayout &DL, InstrumentationCaches &ICaches)
Create a call instruction that calls to the instrumentation function and passes the corresponding arg...
Type * RetTy
The return type of the instrumentation function.
InstrumentationOpportunity & IO
The instrumentation opportunity which it is linked to.
FunctionType * createLLVMSignature(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, const DataLayout &DL, bool ForceIndirection)
Create the type of the instrumentation function.
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.
InstructionIO(bool IsPRE)
Construct an instruction opportunity.
StringRef getName() const override
Get the name of the instruction.
Helper that represent the caches for instrumentation call arguments.
The class that contains the configuration for the instrumentor.
virtual void populate(InstrumentorIRBuilderTy &IIRB)
Populate the instrumentation opportunities.
void addChoice(InstrumentationOpportunity &IO, LLVMContext &Ctx)
Register instrumentation opportunity IO.
Constant * getGlobalString(StringRef S, InstrumentorIRBuilderTy &IIRB)
std::unique_ptr< BaseConfigurationOption > HostEnabled
std::unique_ptr< BaseConfigurationOption > DemangleFunctionNames
void init(InstrumentorIRBuilderTy &IIRB)
Initialize the config to a clean base state without loosing cached values that can be reused across c...
std::unique_ptr< BaseConfigurationOption > GPUEnabled
DenseMap< Constant *, GlobalVariable * > ConstantGlobalsCache
Mapping from constants to globals with the constant as initializer.
BumpPtrAllocator StringAllocator
Utilities for allocating and building strings.
std::string getRTName(StringRef Prefix, StringRef Name, StringRef Suffix1="", StringRef Suffix2="") const
Get the instrumentation function name.
std::unique_ptr< BaseConfigurationOption > RuntimeStubsFile
StringRef getRTName() const
Get the runtime prefix for the instrumentation runtime functions.
void addBaseChoice(BaseConfigurationOption *BCO)
Add the base configuration option BCO into the list of base options.
static Ty * allocate(ArgsTy &&...Args)
Allocate an object of type Ty using a bump allocator and construct it with the Args arguments.
SmallVector< BaseConfigurationOption * > BaseConfigurationOptions
The list of enabled base configuration options.
InstrumentationConfig()
Construct an instrumentation configuration with the base options.
std::unique_ptr< BaseConfigurationOption > FunctionRegex
std::unique_ptr< BaseConfigurationOption > TargetRegex
std::unique_ptr< BaseConfigurationOption > RuntimePrefix
The base configuration options.
EnumeratedArray< StringMap< InstrumentationOpportunity * >, InstrumentationLocation::KindTy > IChoices
The map registered instrumentation opportunities.
DenseMap< StringRef, Constant * > GlobalStringsMap
Mapping to remember global strings passed to the runtime.
Helper to represent an instrumentation location, which is composed of an instrumentation opportunity ...
unsigned getOpcode() const
Get the opcode of the instruction instrumentation location.
KindTy getKind() const
Return the type and position.
InstrumentationLocation(KindTy Kind)
Construct an instrumentation location that is not instrumenting an instruction.
static KindTy getKindFromStr(StringRef S)
Return the location kind described by a string.
static StringRef getKindStr(KindTy Kind)
Return the string representation given a location kind.
KindTy
The supported location kinds, which are composed of a opportunity type and position.
static bool isPRE(KindTy Kind)
Return whether a location kind is positioned before the event occurs.
bool isPRE() const
Return whether the instrumentation location is before the event occurs.
InstrumentationLocation(unsigned Opcode, bool IsPRE)
Construct an instrumentation location belonging to the instrumentation of an instruction.
Base class for instrumentation opportunities.
InstrumentationLocation::KindTy getLocationKind() const
Get the location kind of the instrumentation opportunity.
bool Enabled
Whether the opportunity is enabled.
static Value * getIdPre(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Get the opportunity identifier for the pre and post positions.
static Value * forceCast(Value &V, Type &Ty, InstrumentorIRBuilderTy &IIRB)
Helpers to cast values, pass them to the runtime, and replace them.
static int32_t getIdFromEpoch(uint32_t CurrentEpoch)
}
std::function< bool(Value &)> CallbackTy
An optional callback that takes the value that is about to be instrumented and can return false if it...
static Value * getIdPost(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
virtual Value * instrument(Value *&V, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, InstrumentationCaches &ICaches)
}
static Value * replaceValue(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
unsigned getOpcode() const
Get the opcode of the instruction instrumentation opportunity.
virtual StringRef getName() const =0
Get the name of the instrumentation opportunity.
InstrumentationLocation IP
The instrumentation location of the opportunity.
InstrumentationOpportunity(const InstrumentationLocation IP)
Construct an opportunity with location IP.
SmallVector< IRTArg > IRTArgs
The list of possible arguments for the instrumentation runtime function.
void addCommonArgs(InstrumentationConfig &IConf, LLVMContext &Ctx, bool PassId)
}
virtual Type * getRetTy(LLVMContext &Ctx) const
Get the return type for the instrumentation runtime function.
StringRef Filter
A filter expression to be matched against runtime property values.
An IR builder augmented with extra information for the instrumentor pass.
IRBuilder< ConstantFolder, IRBuilderCallbackInserter > IRB
The underlying IR builder with insertion callback.
LoadIO(bool IsPRE)
Construct a load opportunity.
static Value * getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAtomicityOrdering(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
virtual Type * getValueType(InstrumentorIRBuilderTy &IIRB) const
}
static Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
ConfigKind
The selector of arguments for load opportunities.
static Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getPointer(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Getters and setters for the arguments of the instrumentation function for the load opportunity.
static Value * isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static Value * getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
}
static Value * getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
Initialize the load opportunity using the instrumentation config IConf and the user config UserConfig...
static Value * getModuleName(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getTargetTriple(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
BaseConfigTy< ConfigKind > ConfigTy
StringRef getName() const override
Get the name of the instrumentation opportunity.
static Value * getPointer(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Getters and setters for the arguments of the instrumentation function for the store opportunity.
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
}
static Value * getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
virtual Type * getValueType(InstrumentorIRBuilderTy &IIRB) const
}
static Value * getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
ConfigKind
The selector of arguments for store opportunities.
static Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
Initialize the store opportunity using the instrumentation config IConf and the user config UserConfi...
static Value * getAtomicityOrdering(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
StoreIO(bool IsPRE)
Construct a store instruction opportunity.
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
}
BaseConfigTy< ConfigKind > ConfigTy
Helper union that holds any possible option type.