LLVM 23.0.0git
Instrumentor.cpp
Go to the documentation of this file.
1//===-- Instrumentor.cpp - 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 implementation of the Instrumentor, a highly configurable instrumentation
10// pass.
11//
12//===----------------------------------------------------------------------===//
13
17
19#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/StringMap.h"
24#include "llvm/ADT/iterator.h"
26#include "llvm/IR/Constant.h"
27#include "llvm/IR/Constants.h"
28#include "llvm/IR/DataLayout.h"
31#include "llvm/IR/Function.h"
32#include "llvm/IR/IRBuilder.h"
33#include "llvm/IR/InstrTypes.h"
34#include "llvm/IR/Instruction.h"
37#include "llvm/IR/Intrinsics.h"
38#include "llvm/IR/LLVMContext.h"
39#include "llvm/IR/Metadata.h"
40#include "llvm/IR/Module.h"
41#include "llvm/IR/PassManager.h"
42#include "llvm/IR/Verifier.h"
46#include "llvm/Support/Regex.h"
50
51#include <cassert>
52#include <cstdint>
53#include <functional>
54#include <iterator>
55#include <memory>
56#include <string>
57#include <system_error>
58#include <type_traits>
59
60using namespace llvm;
61using namespace llvm::instrumentor;
62
63#define DEBUG_TYPE "instrumentor"
64
65namespace {
66
67/// The user option to specify an output JSON file to write the configuration.
68static cl::opt<std::string> OutputConfigFile(
69 "instrumentor-write-config-file",
71 "Write the instrumentor configuration into the specified JSON file"),
72 cl::init(""));
73
74/// The user option to specify input JSON files to read the configuration from.
76 ConfigFiles("instrumentor-read-config-files",
77 cl::desc("Read the instrumentor configuration from the "
78 "specified JSON files (comma separated)"),
80
81/// The user option to specify an input file to read the configuration file
82/// paths from.
83static cl::opt<std::string> ConfigPathsFile(
84 "instrumentor-read-config-paths-file",
85 cl::desc("Read the instrumentor configuration file "
86 "paths from the specified file (newline separated)"),
87 cl::init(""));
88
89/// Set the debug location, if not set, after changing the insertion point of
90/// the IR builder \p IRB.
91template <typename IRBuilderTy> void ensureDbgLoc(IRBuilderTy &IRB) {
92 if (IRB.getCurrentDebugLocation())
93 return;
94 auto *BB = IRB.GetInsertBlock();
95 if (auto *SP = BB->getParent()->getSubprogram())
96 IRB.SetCurrentDebugLocation(DILocation::get(BB->getContext(), 0, 0, SP));
97}
98
99/// Attempt to cast \p V to type \p Ty.
100template <typename IRBTy>
101Value *tryToCast(IRBTy &IRB, Value *V, Type *Ty, const DataLayout &DL,
102 bool AllowTruncate = false) {
103 if (!V)
104 return Constant::getAllOnesValue(Ty);
105 Type *VTy = V->getType();
106 if (VTy == Ty)
107 return V;
108 if (VTy->isAggregateType())
109 return V;
110 TypeSize RequestedSize = DL.getTypeSizeInBits(Ty);
111 TypeSize ValueSize = DL.getTypeSizeInBits(VTy);
112 bool ShouldTruncate = RequestedSize < ValueSize;
113 if (ShouldTruncate && !AllowTruncate)
114 return V;
115 if (ShouldTruncate && AllowTruncate)
116 return tryToCast(IRB,
117 IRB.CreateIntCast(V, IRB.getIntNTy(RequestedSize),
118 /*IsSigned=*/false),
119 Ty, DL, AllowTruncate);
120 if (VTy->isPointerTy() && Ty->isPointerTy())
121 return IRB.CreatePointerBitCastOrAddrSpaceCast(V, Ty);
122 if (VTy->isIntegerTy() && Ty->isIntegerTy())
123 return IRB.CreateIntCast(V, Ty, /*IsSigned=*/false);
124 if (VTy->isFloatingPointTy() && Ty->isIntOrPtrTy()) {
125 return tryToCast(IRB, IRB.CreateBitCast(V, IRB.getIntNTy(ValueSize)), Ty,
126 DL, AllowTruncate);
127 }
128 return IRB.CreateBitOrPointerCast(V, Ty);
129}
130
131/// Get a constant integer/boolean of type \p IT and value \p Val.
132template <typename Ty>
133Constant *getCI(Type *IT, Ty Val, bool IsSigned = false) {
134 return ConstantInt::get(IT, Val, IsSigned);
135}
136
137/// The core of the instrumentor pass, which instruments the module as the
138/// instrumentation configuration mandates.
139class InstrumentorImpl final {
140public:
141 /// Construct an instrumentor implementation using the configuration \p IConf.
142 InstrumentorImpl(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
143 Module &M)
144 : IConf(IConf), M(M), IIRB(IIRB) {}
145
146 /// Instrument the module, public entry point.
147 bool instrument();
148
149 // Reset the state to allow reuse of the instrumentor with a different
150 // configuration.
151 void clear() {
152 InstChoicesPRE.clear();
153 InstChoicesPOST.clear();
154 ParsedFunctionRegex = Regex();
155 }
156
157private:
158 /// Indicate if the module should be instrumented based on the target.
159 bool shouldInstrumentTarget();
160
161 /// Indicate if the function \p Fn should be instrumented.
162 bool shouldInstrumentFunction(Function &Fn);
163 bool shouldInstrumentGlobalVariable(GlobalVariable &GV);
164
165 /// Instrument instruction \p I if needed, and use the argument caches in \p
166 /// ICaches.
167 bool instrumentInstruction(Instruction &I, InstrumentationCaches &ICaches);
168
169 /// Instrument function \p Fn.
170 bool instrumentFunction(Function &Fn);
171 bool instrumentModule();
172
173 /// The instrumentation opportunities for instructions indexed by
174 /// their opcode.
176 InstChoicesPOST;
177
178 /// The instrumentor configuration.
180
181 /// The function regex filter, if any.
182 Regex ParsedFunctionRegex;
183
184 /// The underlying module.
185 Module &M;
186
187protected:
188 /// A special IR builder that keeps track of the inserted instructions.
190};
191
192} // end anonymous namespace
193
195 if (!Str.empty()) {
196 Regex RX(Str);
197 std::string ErrMsg;
198 if (!RX.isValid(ErrMsg)) {
200 Twine("failed to parse ") + Name + " regex: " + ErrMsg, DS_Error));
201 return Regex();
202 }
203 return RX;
204 }
205 return Regex();
206}
207
208bool InstrumentorImpl::shouldInstrumentTarget() {
209 const Triple &T = M.getTargetTriple();
210 const bool IsGPU = T.isAMDGPU() || T.isNVPTX();
211
212 bool RegexMatches = true;
213 Regex RX = createRegex(IConf.TargetRegex->getString(), "target", IIRB.Ctx);
214 if (RX.isValid())
215 RegexMatches = RX.match(T.str());
216
217 // Only instrument the module if the target has to be instrumented.
218 return ((IsGPU && IConf.GPUEnabled->getBool()) ||
219 (!IsGPU && IConf.HostEnabled->getBool())) &&
220 RegexMatches;
221}
222
223bool InstrumentorImpl::shouldInstrumentFunction(Function &Fn) {
224 if (Fn.isDeclaration())
225 return false;
226 bool RegexMatches = true;
227 if (ParsedFunctionRegex.isValid())
228 RegexMatches = ParsedFunctionRegex.match(Fn.getName());
229 return (RegexMatches && !Fn.getName().starts_with(IConf.getRTName())) ||
230 Fn.hasFnAttribute("instrument");
231}
232
233bool InstrumentorImpl::shouldInstrumentGlobalVariable(GlobalVariable &GV) {
234 return !GV.getName().starts_with("llvm.") &&
235 !GV.getName().starts_with(IConf.getRTName());
236}
237
238bool InstrumentorImpl::instrumentInstruction(Instruction &I,
239 InstrumentationCaches &ICaches) {
240 bool Changed = false;
241
242 // Skip instrumentation instructions.
243 if (IIRB.NewInsts.contains(&I))
244 return Changed;
245
246 // Count epochs eagerly.
247 ++IIRB.Epoch;
248
249 Value *IPtr = &I;
250 if (auto *IO = InstChoicesPRE.lookup(I.getOpcode())) {
251 IIRB.IRB.SetInsertPoint(&I);
252 ensureDbgLoc(IIRB.IRB);
253 Changed |= bool(IO->instrument(IPtr, IConf, IIRB, ICaches));
254 }
255
256 if (auto *IO = InstChoicesPOST.lookup(I.getOpcode())) {
257 IIRB.IRB.SetInsertPoint(I.getNextNode());
258 ensureDbgLoc(IIRB.IRB);
259 Changed |= bool(IO->instrument(IPtr, IConf, IIRB, ICaches));
260 }
261 IIRB.returnAllocas();
262
263 return Changed;
264}
265
266bool InstrumentorImpl::instrumentFunction(Function &Fn) {
267 bool Changed = false;
268 if (!shouldInstrumentFunction(Fn))
269 return Changed;
270
271 InstrumentationCaches ICaches;
273 ReversePostOrderTraversal<Function *> RPOT(&Fn);
274 for (auto &It : RPOT) {
275 for (auto &I : *It)
276 Changed |= instrumentInstruction(I, ICaches);
277
278 auto *TI = It->getTerminator();
279 if (!TI->getNumSuccessors())
280 FinalTIs.push_back(TI);
281 }
282
283 Value *FPtr = &Fn;
284 for (auto &[Name, IO] :
286 if (!IO->Enabled)
287 continue;
288 // Count epochs eagerly.
289 ++IIRB.Epoch;
290
291 IIRB.IRB.SetInsertPoint(
292 cast<Function>(FPtr)->getEntryBlock().getFirstInsertionPt());
293 ensureDbgLoc(IIRB.IRB);
294 Changed |= bool(IO->instrument(FPtr, IConf, IIRB, ICaches));
295 IIRB.returnAllocas();
296 }
297
298 for (auto &[Name, IO] :
300 if (!IO->Enabled)
301 continue;
302 // Count epochs eagerly.
303 ++IIRB.Epoch;
304
305 for (Instruction *FinalTI : FinalTIs) {
306 IIRB.IRB.SetInsertPoint(FinalTI);
307 ensureDbgLoc(IIRB.IRB);
308 Changed |= bool(IO->instrument(FPtr, IConf, IIRB, ICaches));
309 IIRB.returnAllocas();
310 }
311 }
312 return Changed;
313}
314
315bool InstrumentorImpl::instrumentModule() {
317 Globals.reserve(M.global_size());
318 for (GlobalVariable &GV : M.globals()) {
319 // llvm.metadata contains globals such as llvm.used.
320 if (GV.getSection() == "llvm.metadata" ||
321 GV.getName() == "llvm.global_dtors" ||
322 GV.getName() == "llvm.global_ctors")
323 continue;
324 Globals.push_back(&GV);
325 }
326
327 auto CreateYtor = [&](bool Ctor) {
328 Function *YtorFn = Function::Create(
329 FunctionType::get(IIRB.VoidTy, false), GlobalValue::PrivateLinkage,
330 IConf.getRTName(Ctor ? "ctor" : "dtor", ""), M);
331
332 auto *EntryBB = BasicBlock::Create(IIRB.Ctx, "entry", YtorFn);
333 IIRB.IRB.SetInsertPoint(EntryBB, EntryBB->begin());
334 ensureDbgLoc(IIRB.IRB);
335 IIRB.IRB.CreateRetVoid();
336
337 if (Ctor)
338 appendToGlobalCtors(M, YtorFn, 1000);
339 else
340 appendToGlobalDtors(M, YtorFn, 1000);
341 return YtorFn;
342 };
343
344 InstrumentationCaches ICaches;
345
346 Function *CtorFn = nullptr, *DtorFn = nullptr;
347 bool Changed = false;
350 bool IsPRE = InstrumentationLocation::isPRE(Loc);
351 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
352 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
353 auto *IO = ChoiceIt.second;
354 if (!IO->Enabled)
355 continue;
356 if (!YtorFn)
357 YtorFn = CreateYtor(IsPRE);
358 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
359 ensureDbgLoc(IIRB.IRB);
360 Value *YtorPtr = YtorFn;
361
362 // Count epochs eagerly.
363 ++IIRB.Epoch;
364
365 Changed |= bool(IO->instrument(YtorPtr, IConf, IIRB, ICaches));
366 IIRB.returnAllocas();
367 }
368 }
369
372 bool IsPRE = InstrumentationLocation::isPRE(Loc);
373 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
374 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
375 auto *IO = ChoiceIt.second;
376 if (!IO->Enabled)
377 continue;
378 if (!YtorFn)
379 YtorFn = CreateYtor(IsPRE);
380 for (GlobalVariable *GV : Globals) {
381 if (!shouldInstrumentGlobalVariable(*GV))
382 continue;
383 if (IsPRE)
384 IIRB.IRB.SetInsertPoint(YtorFn->getEntryBlock().getTerminator());
385 else
386 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
387 ensureDbgLoc(IIRB.IRB);
388 Value *GVPtr = GV;
389
390 // Count epochs eagerly.
391 ++IIRB.Epoch;
392
393 Changed |= bool(IO->instrument(GVPtr, IConf, IIRB, ICaches));
394 IIRB.returnAllocas();
395 }
396 }
397 }
398
399 return Changed;
400}
401
402bool InstrumentorImpl::instrument() {
403 bool Changed = false;
404 if (!shouldInstrumentTarget())
405 return Changed;
406
407 StringRef FunctionRegexStr = IConf.FunctionRegex->getString();
408 ParsedFunctionRegex = createRegex(FunctionRegexStr, "function", IIRB.Ctx);
409
410 for (auto &[Name, IO] :
412 if (IO->Enabled)
413 InstChoicesPRE[IO->getOpcode()] = IO;
414 for (auto &[Name, IO] :
416 if (IO->Enabled)
417 InstChoicesPOST[IO->getOpcode()] = IO;
418 Changed |= instrumentModule();
419
420 for (Function &Fn : M)
421 Changed |= instrumentFunction(Fn);
422
423 return Changed;
424}
425
427 InstrumentationConfig *IC,
428 InstrumentorIRBuilderTy *IIRB)
429 : FS(FS), UserIConf(IC), UserIIRB(IIRB) {
430 if (!FS)
431 this->FS = vfs::getRealFileSystem();
432}
433
434PreservedAnalyses InstrumentorPass::run(Module &M, InstrumentationConfig &IConf,
436 bool ReadConfig) {
437 bool Changed = false;
438 InstrumentorImpl Impl(IConf, IIRB, M);
439
440 // If this is a configuration driven run, iterate over all configurations
441 // provided by the user, if not, use the config as is and run the instrumentor
442 // once.
443 if (ReadConfig)
444 readConfigPathsFile(ConfigPathsFile, ConfigFiles, IIRB.Ctx, *FS);
445
446 bool MultipleConfigs = ConfigFiles.size() > 1;
447 unsigned Idx = 0;
448 do {
449 std::string ConfigFile =
450 ReadConfig && !ConfigFiles.empty() ? ConfigFiles[Idx] : "";
451
452 // Initialize the config to the base state but keep the caches around.
453 Impl.clear();
454 IConf.init(IIRB);
455
456 if (!readConfigFromJSON(IConf, ConfigFile, IIRB.Ctx, *FS))
457 continue;
458
459 writeConfigToJSON(IConf,
460 MultipleConfigs
461 ? OutputConfigFile + "." + std::to_string(Idx)
462 : OutputConfigFile,
463 IIRB.Ctx);
464
465 printRuntimeStub(IConf, IConf.RuntimeStubsFile->getString(), IIRB.Ctx);
466
467 Changed |= Impl.instrument();
468 } while (++Idx < ConfigFiles.size());
469
470 if (!Changed)
471 return PreservedAnalyses::all();
473}
474
476 // Only create them if the user did not provide them.
477 std::unique_ptr<InstrumentationConfig> IConfInt(
478 !UserIConf ? new InstrumentationConfig() : nullptr);
479 std::unique_ptr<InstrumentorIRBuilderTy> IIRBInt(
480 !UserIIRB ? new InstrumentorIRBuilderTy(M) : nullptr);
481
482 auto *IConf = IConfInt ? IConfInt.get() : UserIConf;
483 auto *IIRB = IIRBInt ? IIRBInt.get() : UserIIRB;
484
485 auto PA = run(M, *IConf, *IIRB, !UserIConf);
486
487 assert(!verifyModule(M, &errs()));
488 return PA;
489}
490
491std::unique_ptr<BaseConfigurationOption>
494 bool DefaultValue) {
495 auto BCO =
496 std::make_unique<BaseConfigurationOption>(Name, Description, BOOLEAN);
497 BCO->setBool(DefaultValue);
498 IConf.addBaseChoice(BCO.get());
499 return BCO;
500}
501
502std::unique_ptr<BaseConfigurationOption>
506 StringRef DefaultValue) {
507 auto BCO =
508 std::make_unique<BaseConfigurationOption>(Name, Description, STRING);
509 BCO->setString(DefaultValue);
510 IConf.addBaseChoice(BCO.get());
511 return BCO;
512}
513
515 /// List of all instrumentation opportunities.
516 ModuleIO::populate(*this, IIRB);
517 GlobalVarIO::populate(*this, IIRB);
518 FunctionIO::populate(*this, IIRB);
519 AllocaIO::populate(*this, IIRB);
520 UnreachableIO::populate(*this, IIRB);
521 LoadIO::populate(*this, IIRB);
522 StoreIO::populate(*this, IIRB);
523}
524
526 LLVMContext &Ctx) {
527 auto *&ICPtr = IChoices[IO.getLocationKind()][IO.getName()];
528 if (ICPtr) {
530 Twine("registered two instrumentation opportunities for the same "
531 "location (") +
532 ICPtr->getName() + Twine(" vs ") + IO.getName() + Twine(")"),
533 DS_Warning));
534 }
535 ICPtr = &IO;
536}
537
541 return getCI(&Ty, getIdFromEpoch(IIRB.Epoch));
542}
543
547 return getCI(&Ty, -getIdFromEpoch(IIRB.Epoch), /*IsSigned=*/true);
548}
549
552 if (V.getType()->isVoidTy())
553 return Ty.isVoidTy() ? &V : Constant::getNullValue(&Ty);
554 return tryToCast(IIRB.IRB, &V, &Ty,
555 IIRB.IRB.GetInsertBlock()->getDataLayout());
556}
557
561 if (V.getType()->isVoidTy())
562 return &V;
563
564 auto *NewVCasted = &NewV;
565 if (auto *I = dyn_cast<Instruction>(&NewV)) {
567 IIRB.IRB.SetInsertPoint(I->getNextNode());
568 ensureDbgLoc(IIRB.IRB);
569 NewVCasted = tryToCast(IIRB.IRB, &NewV, V.getType(), IIRB.DL,
570 /*AllowTruncate=*/true);
571 }
572 V.replaceUsesWithIf(NewVCasted, [&](Use &U) {
573 if (IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) == IIRB.Epoch)
574 return false;
575 return !isa<LifetimeIntrinsic>(U.getUser()) && !U.getUser()->isDroppable();
576 });
577
578 return &V;
579}
580
582 Type *RetTy)
583 : IO(IO), RetTy(RetTy) {
584 for (auto &It : IO.IRTArgs) {
585 if (!It.Enabled)
586 continue;
587 NumReplaceableArgs += bool(It.Flags & IRTArg::REPLACABLE);
588 MightRequireIndirection |= It.Flags & IRTArg::POTENTIALLY_INDIRECT;
589 }
592}
593
596 const DataLayout &DL, bool ForceIndirection) {
597 assert(((ForceIndirection && MightRequireIndirection) ||
598 (!ForceIndirection && !RequiresIndirection)) &&
599 "Wrong indirection setting!");
600
601 SmallVector<Type *> ParamTypes;
602 for (auto &It : IO.IRTArgs) {
603 if (!It.Enabled)
604 continue;
605 if (!ForceIndirection || !isPotentiallyIndirect(It)) {
606 ParamTypes.push_back(It.Ty);
607 if (!RetTy && NumReplaceableArgs == 1 && (It.Flags & IRTArg::REPLACABLE))
608 RetTy = It.Ty;
609 continue;
610 }
611
612 // The indirection pointer and the size of the value.
613 ParamTypes.push_back(IIRB.PtrTy);
614 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE))
615 ParamTypes.push_back(IIRB.Int32Ty);
616 }
617 if (!RetTy)
618 RetTy = IIRB.VoidTy;
619
620 return FunctionType::get(RetTy, ParamTypes, /*isVarArg=*/false);
621}
622
626 const DataLayout &DL,
627 InstrumentationCaches &ICaches) {
628 SmallVector<Value *> CallParams;
629
631 auto IP = IIRB.IRB.GetInsertPoint();
632
633 bool ForceIndirection = RequiresIndirection;
634 for (auto &It : IO.IRTArgs) {
635 if (!It.Enabled)
636 continue;
637 auto *&Param = ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
638 if (!Param || It.NoCache)
639 // Avoid passing the caches to the getter.
640 Param = It.GetterCB(*V, *It.Ty, IConf, IIRB);
641 assert(Param);
642
643 if (Param->getType()->isVoidTy()) {
644 Param = Constant::getNullValue(It.Ty);
645 } else if (Param->getType()->isAggregateType() ||
646 DL.getTypeSizeInBits(Param->getType()) >
647 DL.getTypeSizeInBits(It.Ty)) {
648 if (!isPotentiallyIndirect(It)) {
650 Twine("indirection needed for ") + It.Name + Twine(" in ") +
651 IO.getName() +
652 Twine(", but not indicated. Instrumentation is skipped"),
653 DS_Warning));
654 return nullptr;
655 }
656 ForceIndirection = true;
657 } else {
658 Param = tryToCast(IIRB.IRB, Param, It.Ty, DL);
659 }
660 CallParams.push_back(Param);
661 }
662
663 if (ForceIndirection) {
664 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
665
666 unsigned Offset = 0;
667 for (auto &It : IO.IRTArgs) {
668 if (!It.Enabled)
669 continue;
670
671 if (!isPotentiallyIndirect(It)) {
672 ++Offset;
673 continue;
674 }
675 auto *&CallParam = CallParams[Offset++];
676 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE)) {
677 CallParams.insert(&CallParam + 1, IIRB.IRB.getInt32(DL.getTypeStoreSize(
678 CallParam->getType())));
679 Offset += 1;
680 }
681
682 auto *&CachedParam =
683 ICaches.IndirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
684 if (CachedParam) {
685 CallParam = CachedParam;
686 continue;
687 }
688
689 auto *AI = IIRB.getAlloca(Fn, CallParam->getType());
690 IIRB.IRB.CreateStore(CallParam, AI);
691 CallParam = CachedParam = AI;
692 }
693 }
694
695 if (!ForceIndirection)
696 IIRB.IRB.SetInsertPoint(IP);
697 ensureDbgLoc(IIRB.IRB);
698
699 auto *FnTy = createLLVMSignature(IConf, IIRB, DL, ForceIndirection);
700 auto CompleteName =
701 IConf.getRTName(IO.IP.isPRE() ? "pre_" : "post_", IO.getName(),
702 ForceIndirection ? "_ind" : "");
703 auto FC = IIRB.IRB.GetInsertBlock()->getModule()->getOrInsertFunction(
704 CompleteName, FnTy);
705 auto *CI = IIRB.IRB.CreateCall(FC, CallParams);
706 CI->addFnAttr(Attribute::get(IIRB.Ctx, Attribute::WillReturn));
707
708 for (unsigned I = 0, E = IO.IRTArgs.size(); I < E; ++I) {
709 if (!IO.IRTArgs[I].Enabled)
710 continue;
711 if (!isReplacable(IO.IRTArgs[I]))
712 continue;
713 bool IsCustomReplaceable = IO.IRTArgs[I].Flags & IRTArg::REPLACABLE_CUSTOM;
714 Value *NewValue = FnTy->isVoidTy() || IsCustomReplaceable
715 ? ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(),
716 IO.IRTArgs[I].Name}]
717 : CI;
718 assert(NewValue);
719 if (ForceIndirection && !IsCustomReplaceable &&
720 isPotentiallyIndirect(IO.IRTArgs[I])) {
721 auto *Q =
722 ICaches
723 .IndirectArgCache[{IIRB.Epoch, IO.getName(), IO.IRTArgs[I].Name}];
724 NewValue = IIRB.IRB.CreateLoad(V->getType(), Q);
725 }
726 V = IO.IRTArgs[I].SetterCB(*V, *NewValue, IConf, IIRB);
727 }
728 return CI;
729}
730
731template <typename Ty> constexpr static Value *getValue(Ty &ValueOrUse) {
732 if constexpr (std::is_same<Ty, Use>::value)
733 return ValueOrUse.get();
734 else
735 return static_cast<Value *>(&ValueOrUse);
736}
737
738template <typename Range>
741 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
742 auto *I32Ty = IIRB.IRB.getInt32Ty();
743 SmallVector<Constant *> ConstantValues;
746 for (auto &RE : R) {
747 Value *V = getValue(RE);
748 if (!V->getType()->isSized())
749 continue;
750 auto VSize = IIRB.DL.getTypeAllocSize(V->getType());
751 ConstantValues.push_back(getCI(I32Ty, VSize));
752 Types.push_back(I32Ty);
753 ConstantValues.push_back(getCI(I32Ty, V->getType()->getTypeID()));
754 Types.push_back(I32Ty);
755 if (uint32_t MisAlign = VSize % 8) {
756 Types.push_back(ArrayType::get(IIRB.Int8Ty, 8 - MisAlign));
757 ConstantValues.push_back(ConstantArray::getNullValue(Types.back()));
758 }
759 Types.push_back(V->getType());
760 if (auto *C = dyn_cast<Constant>(V)) {
761 ConstantValues.push_back(C);
762 continue;
763 }
764 Values.push_back({V, ConstantValues.size()});
765 ConstantValues.push_back(Constant::getNullValue(V->getType()));
766 }
767 if (Types.empty())
768 return ConstantPointerNull::get(IIRB.PtrTy);
769
770 StructType *STy = StructType::get(Fn->getContext(), Types, /*isPacked=*/true);
771 Constant *Initializer = ConstantStruct::get(STy, ConstantValues);
772
773 GlobalVariable *&GV = IConf.ConstantGlobalsCache[Initializer];
774 if (!GV)
775 GV = new GlobalVariable(*Fn->getParent(), STy, false,
776 GlobalValue::InternalLinkage, Initializer,
777 IConf.getRTName("", "value_pack"));
778
779 auto *AI = IIRB.getAlloca(Fn, STy);
780 IIRB.IRB.CreateMemCpy(AI, AI->getAlign(), GV, MaybeAlign(GV->getAlignment()),
781 IIRB.DL.getTypeAllocSize(STy));
782 for (auto [Param, Idx] : Values) {
783 auto *Ptr = IIRB.IRB.CreateStructGEP(STy, AI, Idx);
784 IIRB.IRB.CreateStore(Param, Ptr);
785 }
786 return AI;
787}
788
789template <typename Range>
790static void readValuePack(const Range &R, Value &Pack,
792 function_ref<void(int, Value *)> SetterCB) {
793 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
794 auto &DL = Fn->getDataLayout();
795 SmallVector<Value *> ParameterValues;
796 unsigned Offset = 0;
797 for (const auto &[Idx, RE] : enumerate(R)) {
798 Value *V = getValue(RE);
799 if (!V->getType()->isSized())
800 continue;
801 Offset += 8;
802 auto VSize = DL.getTypeAllocSize(V->getType());
803 auto Padding = alignTo(VSize, 8) - VSize;
804 Offset += Padding;
805 auto *Ptr = IIRB.IRB.CreateConstInBoundsGEP1_32(IIRB.Int8Ty, &Pack, Offset);
806 auto *NewV = IIRB.IRB.CreateLoad(V->getType(), Ptr);
807 SetterCB(Idx, NewV);
808 Offset += VSize;
809 }
810}
811
812/// FunctionIO
813/// {
815 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
816 using namespace std::placeholders;
817 if (UserConfig)
818 Config = *UserConfig;
819
821 if (Config.has(PassAddress))
822 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "address", "The function address.",
824 if (Config.has(PassName))
825 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The function name.",
827 if (Config.has(PassNumArguments))
828 IRTArgs.push_back(
829 IRTArg(IIRB.Int32Ty, "num_arguments",
830 "Number of function arguments (without varargs).", IRTArg::NONE,
831 std::bind(&FunctionIO::getNumArguments, this, _1, _2, _3, _4)));
832 if (Config.has(PassArguments))
833 IRTArgs.push_back(
834 IRTArg(IIRB.PtrTy, "arguments", "Description of the arguments.",
836 : IRTArg::NONE,
837 std::bind(&FunctionIO::getArguments, this, _1, _2, _3, _4),
838 std::bind(&FunctionIO::setArguments, this, _1, _2, _3, _4)));
839 if (Config.has(PassIsMain))
840 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_main",
841 "Flag to indicate it is the main function.",
843 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
844 IConf.addChoice(*this, IIRB.Ctx);
845}
846
850 auto &Fn = cast<Function>(V);
851 if (Fn.isIntrinsic())
852 return Constant::getNullValue(&Ty);
853 return &V;
854}
858 auto &Fn = cast<Function>(V);
859 return IConf.getGlobalString(IConf.DemangleFunctionNames->getBool()
860 ? demangle(Fn.getName())
861 : Fn.getName(),
862 IIRB);
863}
867 auto &Fn = cast<Function>(V);
868 if (!Config.ArgFilter)
869 return getCI(&Ty, Fn.arg_size());
870 auto FRange = make_filter_range(Fn.args(), Config.ArgFilter);
871 return getCI(&Ty, std::distance(FRange.begin(), FRange.end()));
872}
876 auto &Fn = cast<Function>(V);
877 if (!Config.ArgFilter)
878 return createValuePack(Fn.args(), IConf, IIRB);
879 return createValuePack(make_filter_range(Fn.args(), Config.ArgFilter), IConf,
880 IIRB);
881}
885 auto &Fn = cast<Function>(V);
886 auto *AIt = Fn.arg_begin();
887 auto CB = [&](int Idx, Value *ReplV) {
888 while (Config.ArgFilter && !Config.ArgFilter(*AIt))
889 ++AIt;
890 Fn.getArg(Idx)->replaceUsesWithIf(ReplV, [&](Use &U) {
891 return IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) != IIRB.Epoch;
892 });
893 ++AIt;
894 };
895 if (!Config.ArgFilter)
896 readValuePack(Fn.args(), NewV, IIRB, CB);
897 else
898 readValuePack(make_filter_range(Fn.args(), Config.ArgFilter), NewV, IIRB,
899 CB);
900 return &Fn;
901}
905 auto &Fn = cast<Function>(V);
906 return getCI(&Ty, Fn.getName() == "main");
907}
908
909///}
910
911/// UnreachableIO
912///{
914 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
915 if (UserConfig)
916 Config = *UserConfig;
917 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
918 IConf.addChoice(*this, IIRB.Ctx);
919}
920///}
921
922/// AllocaIO
923///{
925 ConfigTy *UserConfig) {
926 if (UserConfig)
927 Config = *UserConfig;
928
930 if (!IsPRE && Config.has(PassAddress))
931 IRTArgs.push_back(
932 IRTArg(IIRB.PtrTy, "address", "The allocated memory address.",
936 if (Config.has(PassSize))
937 IRTArgs.push_back(IRTArg(
938 IIRB.Int64Ty, "size", "The allocation size.",
940 getSize, setSize));
941 if (Config.has(PassAlignment))
942 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
943 "The allocation alignment.", IRTArg::NONE,
944 getAlignment));
945
946 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
947 IConf.addChoice(*this, IIRB.Ctx);
948}
949
952 auto &AI = cast<AllocaInst>(V);
953 const DataLayout &DL = AI.getDataLayout();
954 Value *SizeValue = nullptr;
955 TypeSize TypeSize = DL.getTypeAllocSize(AI.getAllocatedType());
956 if (TypeSize.isFixed()) {
957 SizeValue = getCI(&Ty, TypeSize.getFixedValue());
958 } else {
959 auto *NullPtr = ConstantPointerNull::get(AI.getType());
960 SizeValue = IIRB.IRB.CreatePtrToInt(
961 IIRB.IRB.CreateGEP(AI.getAllocatedType(), NullPtr,
962 {IIRB.IRB.getInt32(1)}),
963 &Ty);
964 }
965 if (AI.isArrayAllocation())
966 SizeValue = IIRB.IRB.CreateMul(
967 SizeValue, IIRB.IRB.CreateZExtOrBitCast(AI.getArraySize(), &Ty));
968 return SizeValue;
969}
970
973 auto &AI = cast<AllocaInst>(V);
974 const DataLayout &DL = AI.getDataLayout();
975 auto *NewAI = IIRB.IRB.CreateAlloca(IIRB.IRB.getInt8Ty(),
976 DL.getAllocaAddrSpace(), &NewV);
977 NewAI->setAlignment(AI.getAlign());
978 AI.replaceAllUsesWith(NewAI);
979 IIRB.eraseLater(&AI);
980 return NewAI;
981}
982
985 return getCI(&Ty, cast<AllocaInst>(V).getAlign().value());
986}
987///}
988
990 ConfigTy *UserConfig) {
991 if (UserConfig)
992 Config = *UserConfig;
993
995 if (Config.has(PassPointer)) {
996 IRTArgs.push_back(
997 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
998 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
999 : IRTArg::NONE),
1001 }
1002 if (Config.has(PassPointerAS)) {
1003 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1004 "The address space of the accessed pointer.",
1006 }
1007 if (Config.has(PassStoredValue)) {
1008 IRTArgs.push_back(
1009 IRTArg(getValueType(IIRB), "value", "The stored value.",
1012 : IRTArg::NONE),
1013 getValue));
1014 }
1015 if (Config.has(PassStoredValueSize)) {
1016 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1017 "The size of the stored value.", IRTArg::NONE,
1018 getValueSize));
1019 }
1020 if (Config.has(PassAlignment)) {
1021 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1022 "The known access alignment.", IRTArg::NONE,
1023 getAlignment));
1024 }
1025 if (Config.has(PassValueTypeId)) {
1026 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1027 "The type id of the stored value.", IRTArg::NONE,
1029 }
1030 if (Config.has(PassAtomicityOrdering)) {
1031 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1032 "The atomicity ordering of the store.",
1034 }
1035 if (Config.has(PassSyncScopeId)) {
1036 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1037 "The sync scope id of the store.", IRTArg::NONE,
1039 }
1040 if (Config.has(PassIsVolatile)) {
1041 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1042 "Flag indicating a volatile store.", IRTArg::NONE,
1043 isVolatile));
1044 }
1045
1046 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1047 IConf.addChoice(*this, IIRB.Ctx);
1048}
1049
1052 auto &SI = cast<StoreInst>(V);
1053 return SI.getPointerOperand();
1054}
1055
1058 auto &SI = cast<StoreInst>(V);
1059 SI.setOperand(SI.getPointerOperandIndex(), &NewV);
1060 return &SI;
1061}
1062
1065 auto &SI = cast<StoreInst>(V);
1066 return getCI(&Ty, SI.getPointerAddressSpace());
1067}
1068
1071 auto &SI = cast<StoreInst>(V);
1072 return SI.getValueOperand();
1073}
1074
1077 auto &SI = cast<StoreInst>(V);
1078 auto &DL = SI.getDataLayout();
1079 return getCI(&Ty, DL.getTypeStoreSize(SI.getValueOperand()->getType()));
1080}
1081
1084 auto &SI = cast<StoreInst>(V);
1085 return getCI(&Ty, SI.getAlign().value());
1086}
1087
1090 auto &SI = cast<StoreInst>(V);
1091 return getCI(&Ty, SI.getValueOperand()->getType()->getTypeID());
1092}
1093
1095 InstrumentationConfig &IConf,
1097 auto &SI = cast<StoreInst>(V);
1098 return getCI(&Ty, uint64_t(SI.getOrdering()));
1099}
1100
1103 auto &SI = cast<StoreInst>(V);
1104 return getCI(&Ty, uint64_t(SI.getSyncScopeID()));
1105}
1106
1109 auto &SI = cast<StoreInst>(V);
1110 return getCI(&Ty, SI.isVolatile());
1111}
1112
1114 ConfigTy *UserConfig) {
1116 if (UserConfig)
1117 Config = *UserConfig;
1118 if (Config.has(PassPointer)) {
1119 IRTArgs.push_back(
1120 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1121 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1122 : IRTArg::NONE),
1124 }
1125 if (Config.has(PassPointerAS)) {
1126 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1127 "The address space of the accessed pointer.",
1129 }
1130 if (!IsPRE && Config.has(PassValue)) {
1131 IRTArgs.push_back(
1132 IRTArg(getValueType(IIRB), "value", "The loaded value.",
1133 Config.has(ReplaceValue)
1136 : IRTArg::NONE)
1137 : IRTArg::NONE,
1138 getValue, Config.has(ReplaceValue) ? replaceValue : nullptr));
1139 }
1140 if (Config.has(PassValueSize)) {
1141 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1142 "The size of the loaded value.", IRTArg::NONE,
1143 getValueSize));
1144 }
1145 if (Config.has(PassAlignment)) {
1146 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1147 "The known access alignment.", IRTArg::NONE,
1148 getAlignment));
1149 }
1150 if (Config.has(PassValueTypeId)) {
1151 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1152 "The type id of the loaded value.", IRTArg::NONE,
1154 }
1155 if (Config.has(PassAtomicityOrdering)) {
1156 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1157 "The atomicity ordering of the load.",
1159 }
1160 if (Config.has(PassSyncScopeId)) {
1161 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1162 "The sync scope id of the load.", IRTArg::NONE,
1164 }
1165 if (Config.has(PassIsVolatile)) {
1166 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1167 "Flag indicating a volatile load.", IRTArg::NONE,
1168 isVolatile));
1169 }
1170
1171 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1172 IConf.addChoice(*this, IIRB.Ctx);
1173}
1174
1177 auto &LI = cast<LoadInst>(V);
1178 return LI.getPointerOperand();
1179}
1180
1183 auto &LI = cast<LoadInst>(V);
1184 LI.setOperand(LI.getPointerOperandIndex(), &NewV);
1185 return &LI;
1186}
1187
1190 auto &LI = cast<LoadInst>(V);
1191 return getCI(&Ty, LI.getPointerAddressSpace());
1192}
1193
1196 return &V;
1197}
1198
1201 auto &LI = cast<LoadInst>(V);
1202 auto &DL = LI.getDataLayout();
1203 return getCI(&Ty, DL.getTypeStoreSize(LI.getType()));
1204}
1205
1208 auto &LI = cast<LoadInst>(V);
1209 return getCI(&Ty, LI.getAlign().value());
1210}
1211
1214 auto &LI = cast<LoadInst>(V);
1215 return getCI(&Ty, LI.getType()->getTypeID());
1216}
1217
1219 InstrumentationConfig &IConf,
1221 auto &LI = cast<LoadInst>(V);
1222 return getCI(&Ty, uint64_t(LI.getOrdering()));
1223}
1224
1227 auto &LI = cast<LoadInst>(V);
1228 return getCI(&Ty, uint64_t(LI.getSyncScopeID()));
1229}
1230
1233 auto &LI = cast<LoadInst>(V);
1234 return getCI(&Ty, LI.isVolatile());
1235}
1236
1238 ConfigTy *UserConfig) {
1239 if (UserConfig)
1240 Config = *UserConfig;
1241
1242 if (Config.has(PassName))
1243 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "module_name",
1244 "The module/translation unit name.",
1246 if (Config.has(PassTargetTriple))
1247 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "target_triple", "The target triple.",
1249
1250 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1251 IConf.addChoice(*this, IIRB.Ctx);
1252}
1255 // V is a constructor or destructor of the module we can place code in.
1256 auto &Fn = cast<Function>(V);
1257 return IConf.getGlobalString(Fn.getParent()->getName(), IIRB);
1258}
1260 InstrumentationConfig &IConf,
1262 // V is a constructor or destructor of the module we can place code in.
1263 auto &Fn = cast<Function>(V);
1264 return IConf.getGlobalString(Fn.getParent()->getTargetTriple().getTriple(),
1265 IIRB);
1266}
1267
1269 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1270 if (UserConfig)
1271 Config = *UserConfig;
1273 if (Config.has(PassAddress))
1274 IRTArgs.push_back(IRTArg(
1275 IIRB.PtrTy, "address",
1276 "The address of the global (replaceable for definitions).",
1279 if (Config.has(PassAS))
1280 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "address_space",
1281 "The address space of the global.", IRTArg::NONE,
1282 getAS));
1283 if (Config.has(PassDeclaredSize))
1284 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "declared_size",
1285 "The size of the declared type of the global.",
1287 if (Config.has(PassAlignment))
1288 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1289 "The allocation alignment.", IRTArg::NONE,
1290 getAlignment));
1291 if (Config.has(PassName))
1292 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The name of the global.",
1294 if (Config.has(PassInitialValue))
1295 IRTArgs.push_back(IRTArg(
1296 IIRB.Int64Ty, "initial_value", "The initial value of the global.",
1299 if (Config.has(PassIsConstant))
1300 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_constant",
1301 "Flag to indicate constant globals.", IRTArg::NONE,
1302 isConstant));
1303 if (Config.has(PassIsDefinition))
1304 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_definition",
1305 "Flag to indicate global definitions.",
1307 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1308 IConf.addChoice(*this, IIRB.Ctx);
1309}
1313 if (GV.getAddressSpace())
1314 return ConstantExpr::getAddrSpaceCast(&GV, IIRB.PtrTy);
1315 return &GV;
1316}
1318 InstrumentationConfig &IConf,
1321
1322 GlobalVariable *ShadowGV = nullptr;
1323 auto ShadowName = IConf.getRTName("shadow.", GV.getName());
1324 auto &DL = GV.getDataLayout();
1325 if (GV.isDeclaration()) {
1326 ShadowGV = new GlobalVariable(*GV.getParent(), GV.getType(), false,
1328 ShadowName, &GV, GV.getThreadLocalMode(),
1329 DL.getDefaultGlobalsAddressSpace());
1330 } else {
1331 ShadowGV = new GlobalVariable(
1332 *GV.getParent(), NewV.getType(), false, GV.getLinkage(),
1333 PoisonValue::get(NewV.getType()), ShadowName, &GV);
1334 IIRB.IRB.CreateStore(&NewV, ShadowGV);
1335 }
1336
1340 DenseMap<Value *, Instruction *> ConstToInstMap;
1342
1343 auto MakeInstForConst = [&](Use &U) {
1344 Instruction *&I = ConstToInstMap[U];
1345 if (I)
1346 return;
1347 if (U == &GV) {
1348 } else if (auto *CE = dyn_cast<ConstantExpr>(U)) {
1349 I = CE->getAsInstruction();
1350 }
1351 };
1352
1353 auto InsertConsts = [&](Instruction *UserI, Use &UserU) {
1355 auto *&Reload = ReloadMap[UserI->getFunction()];
1356 if (!Reload) {
1357 Reload = new LoadInst(
1358 GV.getType(), ShadowGV, GV.getName() + ".shadow_load",
1360 IIRB.NewInsts.insert({Reload, IIRB.Epoch});
1361 }
1362 Worklist.push_back({UserI, &UserU});
1363 while (!Worklist.empty()) {
1364 auto [I, U] = Worklist.pop_back_val();
1365 if (*U == &GV) {
1366 U->set(ReloadMap[I->getFunction()]);
1367 continue;
1368 }
1369 if (auto *CI = ConstToInstMap[*U]) {
1370 auto *CIClone = CI->clone();
1371 IIRB.NewInsts.insert({CIClone, IIRB.Epoch});
1372 if (auto *PHI = dyn_cast<PHINode>(I)) {
1373 auto *BB = PHI->getIncomingBlock(U->getOperandNo());
1374 CIClone->insertBefore(BB->getTerminator()->getIterator());
1375 } else {
1376 CIClone->insertBefore(I->getIterator());
1377 }
1378 U->set(CIClone);
1379 for (auto &CICUse : CIClone->operands()) {
1380 Worklist.push_back({CIClone, &CICUse});
1381 }
1382 }
1383 }
1384 };
1385
1386 SmallPtrSet<Use *, 8> Visited;
1387 while (!Worklist.empty()) {
1388 Use *U = Worklist.pop_back_val();
1389 if (!Done.insert(U).second)
1390 continue;
1391 MakeInstForConst(*U);
1392 auto *I = dyn_cast<Instruction>(U->getUser());
1393 if (!I) {
1394 append_range(Worklist, make_pointer_range(U->getUser()->uses()));
1395 continue;
1396 }
1397 if (IIRB.NewInsts.lookup(I) == IIRB.Epoch)
1398 continue;
1400 continue;
1401 if (auto *II = dyn_cast<IntrinsicInst>(I))
1402 if (II->getIntrinsicID() == Intrinsic::eh_typeid_for)
1403 continue;
1404 if (I->getParent())
1405 InsertConsts(I, *U);
1406 }
1407
1408 for (auto &It : ConstToInstMap)
1409 if (It.second)
1410 It.second->deleteValue();
1411
1412 return &V;
1413}
1417 return getCI(&Ty, GV.getAddressSpace());
1418}
1420 InstrumentationConfig &IConf,
1423 return getCI(&Ty, GV.getAlignment());
1424}
1426 InstrumentationConfig &IConf,
1429 auto &DL = GV.getDataLayout();
1430 return getCI(&Ty, DL.getTypeAllocSize(GV.getValueType()));
1431}
1433 InstrumentationConfig &IConf,
1436 return IConf.getGlobalString(GV.getName(), IIRB);
1437}
1448 return getCI(&Ty, GV.isConstant());
1449}
1451 InstrumentationConfig &IConf,
1454 return getCI(&Ty, !GV.isDeclaration());
1455}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
Rewrite undef for PHI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
This file contains the declarations for the subclasses of Constant, which represent the different fla...
post inline ee instrument
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static void readValuePack(const Range &R, Value &Pack, InstrumentorIRBuilderTy &IIRB, function_ref< void(int, Value *)> SetterCB)
static constexpr Value * getValue(Ty &ValueOrUse)
static Value * createValuePack(const Range &R, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Regex createRegex(StringRef Str, StringRef Name, LLVMContext &Ctx)
#define I(x, y, z)
Definition MD5.cpp:57
This file contains the declarations for metadata subclasses.
#define T
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
ModuleAnalysisManager MAM
if(PassOpts->AAPipeline)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
Defines the virtual file system interface vfs::FileSystem.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
LLVM_ABI const_iterator getFirstNonPHIOrDbgOrAlloca() const
Returns an iterator to the first instruction in this block that is not a PHINode, a debug intrinsic,...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
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)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Diagnostic information for IR instrumentation reporting.
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
const BasicBlock & getEntryBlock() const
Definition Function.h:809
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:362
iterator_range< arg_iterator > args()
Definition Function.h:892
arg_iterator arg_begin()
Definition Function.h:868
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition Function.h:251
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:358
size_t arg_size() const
Definition Function.h:901
Argument * getArg(unsigned i) const
Definition Function.h:886
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:728
StringRef getSection() const
Get the custom section of this global if it has one.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:337
LinkageTypes getLinkage() const
ThreadLocalMode getThreadLocalMode() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:141
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
@ WeakODRLinkage
Same, but only replaced by something equivalent.
Definition GlobalValue.h:58
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
uint64_t getAlignment() const
FIXME: Remove this function once transition to Align is over.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
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
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
An instruction for reading from memory.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1572
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition Module.h:283
size_t global_size() const
Definition Module.h:683
StringRef getName() const
Get a short "name" for the module.
Definition Module.h:271
iterator_range< global_iterator > globals()
Definition Module.h:686
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
LLVM_ABI bool isValid(std::string &Error) const
isValid - returns the error encountered during regex compilation, if any.
Definition Regex.cpp:69
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Definition Regex.cpp:83
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void reserve(size_type N)
iterator insert(iterator I, T &&Elt)
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.
Definition StringRef.h:56
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:483
const std::string & getTriple() const
Definition Triple.h:503
bool isAMDGPU() const
Definition Triple.h:910
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:284
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:321
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
Definition Value.cpp:557
iterator_range< use_iterator > uses()
Definition Value.h:380
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:318
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
Definition TypeSize.h:171
An efficient, type-erasing, non-owning reference to a callable.
Changed
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
initializer< Ty > init(const Ty &Val)
void writeConfigToJSON(InstrumentationConfig &IConf, StringRef OutputFile, LLVMContext &Ctx)
Write the configuration in /p IConf to the file with path OutputFile.
bool readConfigPathsFile(StringRef InputFile, cl::list< std::string > &Configs, LLVMContext &Ctx, vfs::FileSystem &FS)
Read the configuration paths from the file with path InputFile into Configs.
bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile, LLVMContext &Ctx, vfs::FileSystem &FS)
Read the configuration from the file with path InputFile into /p IConf.
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 IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:557
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
MaybeAlign getAlign(const CallInst &I, unsigned Index)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2553
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Done
Definition Threading.h:60
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2207
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:551
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
LLVM_ABI void appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Same as appendToGlobalCtors(), but for global dtors.
DEMANGLE_ABI std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.
Definition Demangle.cpp:21
LLVM_ABI bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106
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)
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...
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...
llvm::instrumentor::FunctionIO::ConfigTy Config
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
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)
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)
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.
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.
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.
Helper that represent the caches for instrumentation call arguments.
DenseMap< std::tuple< unsigned, StringRef, StringRef >, Value * > DirectArgCache
A cache for direct and indirect arguments.
DenseMap< std::tuple< unsigned, StringRef, StringRef >, Value * > IndirectArgCache
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.
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.
std::unique_ptr< BaseConfigurationOption > FunctionRegex
std::unique_ptr< BaseConfigurationOption > TargetRegex
EnumeratedArray< StringMap< InstrumentationOpportunity * >, InstrumentationLocation::KindTy > IChoices
The map registered instrumentation opportunities.
bool isPRE() const
Return whether the instrumentation location is before the event occurs.
Base class for instrumentation opportunities.
InstrumentationLocation::KindTy getLocationKind() const
Get the location kind of the instrumentation opportunity.
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)
}
static Value * getIdPost(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * replaceValue(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
virtual StringRef getName() const =0
Get the name of the instrumentation opportunity.
SmallVector< IRTArg > IRTArgs
The list of possible arguments for the instrumentation runtime function.
void addCommonArgs(InstrumentationConfig &IConf, LLVMContext &Ctx, bool PassId)
}
An IR builder augmented with extra information for the instrumentor pass.
IRBuilder< ConstantFolder, IRBuilderCallbackInserter > IRB
The underlying IR builder with insertion callback.
unsigned Epoch
The current epoch number.
AllocaInst * getAlloca(Function *Fn, Type *Ty, bool MatchType=false)
Get a temporary alloca to communicate (large) values with the runtime.
void returnAllocas()
Return the temporary allocas.
DenseMap< Instruction *, unsigned > NewInsts
A mapping from instrumentation instructions to the epoch they have been created.
void eraseLater(Instruction *I)
Save instruction I to be erased later.
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)
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
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)
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)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
}
BaseConfigTy< ConfigKind > ConfigTy