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 IO->instrument(IPtr, Changed, IConf, IIRB, ICaches);
254 }
255
256 if (auto *IO = InstChoicesPOST.lookup(I.getOpcode())) {
257 IIRB.IRB.SetInsertPoint(I.getNextNode());
258 ensureDbgLoc(IIRB.IRB);
259 IO->instrument(IPtr, Changed, 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 IO->instrument(FPtr, Changed, 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 IO->instrument(FPtr, Changed, 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 Changed = true;
359 }
360 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
361 ensureDbgLoc(IIRB.IRB);
362 Value *YtorPtr = YtorFn;
363
364 // Count epochs eagerly.
365 ++IIRB.Epoch;
366
367 IO->instrument(YtorPtr, Changed, IConf, IIRB, ICaches);
368 IIRB.returnAllocas();
369 }
370 }
371
374 bool IsPRE = InstrumentationLocation::isPRE(Loc);
375 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
376 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
377 auto *IO = ChoiceIt.second;
378 if (!IO->Enabled)
379 continue;
380 if (!YtorFn) {
381 YtorFn = CreateYtor(IsPRE);
382 Changed = true;
383 }
384 for (GlobalVariable *GV : Globals) {
385 if (!shouldInstrumentGlobalVariable(*GV))
386 continue;
387 if (IsPRE)
388 IIRB.IRB.SetInsertPoint(YtorFn->getEntryBlock().getTerminator());
389 else
390 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
391 ensureDbgLoc(IIRB.IRB);
392 Value *GVPtr = GV;
393
394 // Count epochs eagerly.
395 ++IIRB.Epoch;
396
397 IO->instrument(GVPtr, Changed, IConf, IIRB, ICaches);
398 IIRB.returnAllocas();
399 }
400 }
401 }
402
403 return Changed;
404}
405
406bool InstrumentorImpl::instrument() {
407 bool Changed = false;
408 if (!shouldInstrumentTarget())
409 return Changed;
410
411 StringRef FunctionRegexStr = IConf.FunctionRegex->getString();
412 ParsedFunctionRegex = createRegex(FunctionRegexStr, "function", IIRB.Ctx);
413
414 for (auto &[Name, IO] :
416 if (IO->Enabled)
417 InstChoicesPRE[IO->getOpcode()] = IO;
418 for (auto &[Name, IO] :
420 if (IO->Enabled)
421 InstChoicesPOST[IO->getOpcode()] = IO;
422
423 Changed |= instrumentModule();
424
425 for (Function &Fn : M)
426 Changed |= instrumentFunction(Fn);
427
428 return Changed;
429}
430
432 InstrumentationConfig *IC,
433 InstrumentorIRBuilderTy *IIRB)
434 : FS(FS), UserIConf(IC), UserIIRB(IIRB) {
435 if (!FS)
436 this->FS = vfs::getRealFileSystem();
437}
438
439PreservedAnalyses InstrumentorPass::run(Module &M, InstrumentationConfig &IConf,
441 bool ReadConfig) {
442 bool Changed = false;
443 InstrumentorImpl Impl(IConf, IIRB, M);
444
445 // If this is a configuration driven run, iterate over all configurations
446 // provided by the user, if not, use the config as is and run the instrumentor
447 // once.
448 if (ReadConfig)
449 readConfigPathsFile(ConfigPathsFile, ConfigFiles, IIRB.Ctx, *FS);
450
451 bool MultipleConfigs = ConfigFiles.size() > 1;
452 unsigned Idx = 0;
453 do {
454 std::string ConfigFile =
455 ReadConfig && !ConfigFiles.empty() ? ConfigFiles[Idx] : "";
456
457 // Initialize the config to the base state but keep the caches around.
458 Impl.clear();
459 IConf.init(IIRB);
460
461 if (!readConfigFromJSON(IConf, ConfigFile, IIRB.Ctx, *FS))
462 continue;
463
464 writeConfigToJSON(IConf,
465 MultipleConfigs
466 ? OutputConfigFile + "." + std::to_string(Idx)
467 : OutputConfigFile,
468 IIRB.Ctx);
469
470 printRuntimeStub(IConf, IConf.RuntimeStubsFile->getString(), IIRB.Ctx);
471
472 Changed |= Impl.instrument();
473 } while (++Idx < ConfigFiles.size());
474
475 if (!Changed)
476 return PreservedAnalyses::all();
478}
479
481 // Only create them if the user did not provide them.
482 std::unique_ptr<InstrumentationConfig> IConfInt(
483 !UserIConf ? new InstrumentationConfig() : nullptr);
484 std::unique_ptr<InstrumentorIRBuilderTy> IIRBInt(
485 !UserIIRB ? new InstrumentorIRBuilderTy(M) : nullptr);
486
487 auto *IConf = IConfInt ? IConfInt.get() : UserIConf;
488 auto *IIRB = IIRBInt ? IIRBInt.get() : UserIIRB;
489
490 auto PA = run(M, *IConf, *IIRB, !UserIConf);
491
492 assert(!verifyModule(M, &errs()));
493 return PA;
494}
495
496std::unique_ptr<BaseConfigurationOption>
499 bool DefaultValue) {
500 auto BCO =
501 std::make_unique<BaseConfigurationOption>(Name, Description, BOOLEAN);
502 BCO->setBool(DefaultValue);
503 IConf.addBaseChoice(BCO.get());
504 return BCO;
505}
506
507std::unique_ptr<BaseConfigurationOption>
511 StringRef DefaultValue) {
512 auto BCO =
513 std::make_unique<BaseConfigurationOption>(Name, Description, STRING);
514 BCO->setString(DefaultValue);
515 IConf.addBaseChoice(BCO.get());
516 return BCO;
517}
518
520 /// List of all instrumentation opportunities.
521 ModuleIO::populate(*this, IIRB);
522 GlobalVarIO::populate(*this, IIRB);
523 FunctionIO::populate(*this, IIRB);
524 AllocaIO::populate(*this, IIRB);
525 UnreachableIO::populate(*this, IIRB);
526 LoadIO::populate(*this, IIRB);
527 StoreIO::populate(*this, IIRB);
528}
529
531 LLVMContext &Ctx) {
532 auto *&ICPtr = IChoices[IO.getLocationKind()][IO.getName()];
533 if (ICPtr) {
535 Twine("registered two instrumentation opportunities for the same "
536 "location (") +
537 ICPtr->getName() + Twine(" vs ") + IO.getName() + Twine(")"),
538 DS_Warning));
539 }
540 ICPtr = &IO;
541}
542
546 return getCI(&Ty, getIdFromEpoch(IIRB.Epoch));
547}
548
552 return getCI(&Ty, -getIdFromEpoch(IIRB.Epoch), /*IsSigned=*/true);
553}
554
557 if (V.getType()->isVoidTy())
558 return Ty.isVoidTy() ? &V : Constant::getNullValue(&Ty);
559 return tryToCast(IIRB.IRB, &V, &Ty,
560 IIRB.IRB.GetInsertBlock()->getDataLayout());
561}
562
566 if (V.getType()->isVoidTy())
567 return &V;
568
569 auto *NewVCasted = &NewV;
570 if (auto *I = dyn_cast<Instruction>(&NewV)) {
572 IIRB.IRB.SetInsertPoint(I->getNextNode());
573 ensureDbgLoc(IIRB.IRB);
574 NewVCasted = tryToCast(IIRB.IRB, &NewV, V.getType(), IIRB.DL,
575 /*AllowTruncate=*/true);
576 }
577 V.replaceUsesWithIf(NewVCasted, [&](Use &U) {
578 if (IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) == IIRB.Epoch)
579 return false;
580 return !isa<LifetimeIntrinsic>(U.getUser()) && !U.getUser()->isDroppable();
581 });
582
583 return &V;
584}
585
587 Type *RetTy)
588 : IO(IO), RetTy(RetTy) {
589 for (auto &It : IO.IRTArgs) {
590 if (!It.Enabled)
591 continue;
592 NumReplaceableArgs += bool(It.Flags & IRTArg::REPLACABLE);
593 MightRequireIndirection |= It.Flags & IRTArg::POTENTIALLY_INDIRECT;
594 }
597}
598
601 const DataLayout &DL, bool ForceIndirection) {
602 assert(((ForceIndirection && MightRequireIndirection) ||
603 (!ForceIndirection && !RequiresIndirection)) &&
604 "Wrong indirection setting!");
605
606 SmallVector<Type *> ParamTypes;
607 for (auto &It : IO.IRTArgs) {
608 if (!It.Enabled)
609 continue;
610 if (!ForceIndirection || !isPotentiallyIndirect(It)) {
611 ParamTypes.push_back(It.Ty);
612 if (!RetTy && NumReplaceableArgs == 1 && (It.Flags & IRTArg::REPLACABLE))
613 RetTy = It.Ty;
614 continue;
615 }
616
617 // The indirection pointer and the size of the value.
618 ParamTypes.push_back(IIRB.PtrTy);
619 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE))
620 ParamTypes.push_back(IIRB.Int32Ty);
621 }
622 if (!RetTy)
623 RetTy = IIRB.VoidTy;
624
625 return FunctionType::get(RetTy, ParamTypes, /*isVarArg=*/false);
626}
627
631 const DataLayout &DL,
632 InstrumentationCaches &ICaches) {
633 SmallVector<Value *> CallParams;
634
636 auto IP = IIRB.IRB.GetInsertPoint();
637
638 bool ForceIndirection = RequiresIndirection;
639 for (auto &It : IO.IRTArgs) {
640 if (!It.Enabled)
641 continue;
642 auto *&Param = ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
643 if (!Param || It.NoCache)
644 // Avoid passing the caches to the getter.
645 Param = It.GetterCB(*V, *It.Ty, IConf, IIRB);
646 assert(Param);
647
648 if (Param->getType()->isVoidTy()) {
649 Param = Constant::getNullValue(It.Ty);
650 } else if (Param->getType()->isAggregateType() ||
651 DL.getTypeSizeInBits(Param->getType()) >
652 DL.getTypeSizeInBits(It.Ty)) {
653 if (!isPotentiallyIndirect(It)) {
655 Twine("indirection needed for ") + It.Name + Twine(" in ") +
656 IO.getName() +
657 Twine(", but not indicated. Instrumentation is skipped"),
658 DS_Warning));
659 return nullptr;
660 }
661 ForceIndirection = true;
662 } else {
663 Param = tryToCast(IIRB.IRB, Param, It.Ty, DL);
664 }
665 CallParams.push_back(Param);
666 }
667
668 if (ForceIndirection) {
669 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
670
671 unsigned Offset = 0;
672 for (auto &It : IO.IRTArgs) {
673 if (!It.Enabled)
674 continue;
675
676 if (!isPotentiallyIndirect(It)) {
677 ++Offset;
678 continue;
679 }
680 auto *&CallParam = CallParams[Offset++];
681 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE)) {
682 CallParams.insert(&CallParam + 1, IIRB.IRB.getInt32(DL.getTypeStoreSize(
683 CallParam->getType())));
684 Offset += 1;
685 }
686
687 auto *&CachedParam =
688 ICaches.IndirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
689 if (CachedParam) {
690 CallParam = CachedParam;
691 continue;
692 }
693
694 auto *AI = IIRB.getAlloca(Fn, CallParam->getType());
695 IIRB.IRB.CreateStore(CallParam, AI);
696 CallParam = CachedParam = AI;
697 }
698 }
699
700 if (!ForceIndirection)
701 IIRB.IRB.SetInsertPoint(IP);
702 ensureDbgLoc(IIRB.IRB);
703
704 auto *FnTy = createLLVMSignature(IConf, IIRB, DL, ForceIndirection);
705 auto CompleteName =
706 IConf.getRTName(IO.IP.isPRE() ? "pre_" : "post_", IO.getName(),
707 ForceIndirection ? "_ind" : "");
708 auto FC = IIRB.IRB.GetInsertBlock()->getModule()->getOrInsertFunction(
709 CompleteName, FnTy);
710 auto *CI = IIRB.IRB.CreateCall(FC, CallParams);
711 CI->addFnAttr(Attribute::get(IIRB.Ctx, Attribute::WillReturn));
712
713 for (unsigned I = 0, E = IO.IRTArgs.size(); I < E; ++I) {
714 if (!IO.IRTArgs[I].Enabled)
715 continue;
716 if (!isReplacable(IO.IRTArgs[I]))
717 continue;
718 bool IsCustomReplaceable = IO.IRTArgs[I].Flags & IRTArg::REPLACABLE_CUSTOM;
719 Value *NewValue = FnTy->isVoidTy() || IsCustomReplaceable
720 ? ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(),
721 IO.IRTArgs[I].Name}]
722 : CI;
723 assert(NewValue);
724 if (ForceIndirection && !IsCustomReplaceable &&
725 isPotentiallyIndirect(IO.IRTArgs[I])) {
726 auto *Q =
727 ICaches
728 .IndirectArgCache[{IIRB.Epoch, IO.getName(), IO.IRTArgs[I].Name}];
729 NewValue = IIRB.IRB.CreateLoad(V->getType(), Q);
730 }
731 V = IO.IRTArgs[I].SetterCB(*V, *NewValue, IConf, IIRB);
732 }
733 return CI;
734}
735
736template <typename Ty> constexpr static Value *getValue(Ty &ValueOrUse) {
737 if constexpr (std::is_same<Ty, Use>::value)
738 return ValueOrUse.get();
739 else
740 return static_cast<Value *>(&ValueOrUse);
741}
742
743template <typename Range>
746 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
747 auto *I32Ty = IIRB.IRB.getInt32Ty();
748 SmallVector<Constant *> ConstantValues;
751 for (auto &RE : R) {
752 Value *V = getValue(RE);
753 if (!V->getType()->isSized())
754 continue;
755 auto VSize = IIRB.DL.getTypeAllocSize(V->getType());
756 ConstantValues.push_back(getCI(I32Ty, VSize));
757 Types.push_back(I32Ty);
758 ConstantValues.push_back(getCI(I32Ty, V->getType()->getTypeID()));
759 Types.push_back(I32Ty);
760 if (uint32_t MisAlign = VSize % 8) {
761 Types.push_back(ArrayType::get(IIRB.Int8Ty, 8 - MisAlign));
762 ConstantValues.push_back(ConstantArray::getNullValue(Types.back()));
763 }
764 Types.push_back(V->getType());
765 if (auto *C = dyn_cast<Constant>(V)) {
766 ConstantValues.push_back(C);
767 continue;
768 }
769 Values.push_back({V, ConstantValues.size()});
770 ConstantValues.push_back(Constant::getNullValue(V->getType()));
771 }
772 if (Types.empty())
773 return ConstantPointerNull::get(IIRB.PtrTy);
774
775 StructType *STy = StructType::get(Fn->getContext(), Types, /*isPacked=*/true);
776 Constant *Initializer = ConstantStruct::get(STy, ConstantValues);
777
778 GlobalVariable *&GV = IConf.ConstantGlobalsCache[Initializer];
779 if (!GV)
780 GV = new GlobalVariable(*Fn->getParent(), STy, false,
781 GlobalValue::InternalLinkage, Initializer,
782 IConf.getRTName("", "value_pack"));
783
784 auto *AI = IIRB.getAlloca(Fn, STy);
785 IIRB.IRB.CreateMemCpy(AI, AI->getAlign(), GV, MaybeAlign(GV->getAlignment()),
786 IIRB.DL.getTypeAllocSize(STy));
787 for (auto [Param, Idx] : Values) {
788 auto *Ptr = IIRB.IRB.CreateStructGEP(STy, AI, Idx);
789 IIRB.IRB.CreateStore(Param, Ptr);
790 }
791 return AI;
792}
793
794template <typename Range>
795static void readValuePack(const Range &R, Value &Pack,
797 function_ref<void(int, Value *)> SetterCB) {
798 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
799 auto &DL = Fn->getDataLayout();
800 SmallVector<Value *> ParameterValues;
801 unsigned Offset = 0;
802 for (const auto &[Idx, RE] : enumerate(R)) {
803 Value *V = getValue(RE);
804 if (!V->getType()->isSized())
805 continue;
806 Offset += 8;
807 auto VSize = DL.getTypeAllocSize(V->getType());
808 auto Padding = alignTo(VSize, 8) - VSize;
809 Offset += Padding;
810 auto *Ptr = IIRB.IRB.CreateConstInBoundsGEP1_32(IIRB.Int8Ty, &Pack, Offset);
811 auto *NewV = IIRB.IRB.CreateLoad(V->getType(), Ptr);
812 SetterCB(Idx, NewV);
813 Offset += VSize;
814 }
815}
816
817/// FunctionIO
818/// {
820 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
821 using namespace std::placeholders;
822 if (UserConfig)
823 Config = *UserConfig;
824
826 if (Config.has(PassAddress))
827 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "address", "The function address.",
829 if (Config.has(PassName))
830 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The function name.",
832 if (Config.has(PassNumArguments))
833 IRTArgs.push_back(
834 IRTArg(IIRB.Int32Ty, "num_arguments",
835 "Number of function arguments (without varargs).", IRTArg::NONE,
836 std::bind(&FunctionIO::getNumArguments, this, _1, _2, _3, _4)));
837 if (Config.has(PassArguments))
838 IRTArgs.push_back(
839 IRTArg(IIRB.PtrTy, "arguments", "Description of the arguments.",
841 : IRTArg::NONE,
842 std::bind(&FunctionIO::getArguments, this, _1, _2, _3, _4),
843 std::bind(&FunctionIO::setArguments, this, _1, _2, _3, _4)));
844 if (Config.has(PassIsMain))
845 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_main",
846 "Flag to indicate it is the main function.",
848 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
849 IConf.addChoice(*this, IIRB.Ctx);
850}
851
855 auto &Fn = cast<Function>(V);
856 if (Fn.isIntrinsic())
857 return Constant::getNullValue(&Ty);
858 return &V;
859}
863 auto &Fn = cast<Function>(V);
864 return IConf.getGlobalString(IConf.DemangleFunctionNames->getBool()
865 ? demangle(Fn.getName())
866 : Fn.getName(),
867 IIRB);
868}
872 auto &Fn = cast<Function>(V);
873 if (!Config.ArgFilter)
874 return getCI(&Ty, Fn.arg_size());
875 auto FRange = make_filter_range(Fn.args(), Config.ArgFilter);
876 return getCI(&Ty, std::distance(FRange.begin(), FRange.end()));
877}
881 auto &Fn = cast<Function>(V);
882 if (!Config.ArgFilter)
883 return createValuePack(Fn.args(), IConf, IIRB);
884 return createValuePack(make_filter_range(Fn.args(), Config.ArgFilter), IConf,
885 IIRB);
886}
890 auto &Fn = cast<Function>(V);
891 auto *AIt = Fn.arg_begin();
892 auto CB = [&](int Idx, Value *ReplV) {
893 while (Config.ArgFilter && !Config.ArgFilter(*AIt))
894 ++AIt;
895 Fn.getArg(Idx)->replaceUsesWithIf(ReplV, [&](Use &U) {
896 return IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) != IIRB.Epoch;
897 });
898 ++AIt;
899 };
900 if (!Config.ArgFilter)
901 readValuePack(Fn.args(), NewV, IIRB, CB);
902 else
903 readValuePack(make_filter_range(Fn.args(), Config.ArgFilter), NewV, IIRB,
904 CB);
905 return &Fn;
906}
910 auto &Fn = cast<Function>(V);
911 return getCI(&Ty, Fn.getName() == "main");
912}
913
914///}
915
916/// UnreachableIO
917///{
919 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
920 if (UserConfig)
921 Config = *UserConfig;
922 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
923 IConf.addChoice(*this, IIRB.Ctx);
924}
925///}
926
927/// AllocaIO
928///{
930 ConfigTy *UserConfig) {
931 if (UserConfig)
932 Config = *UserConfig;
933
935 if (!IsPRE && Config.has(PassAddress))
936 IRTArgs.push_back(
937 IRTArg(IIRB.PtrTy, "address", "The allocated memory address.",
941 if (Config.has(PassSize))
942 IRTArgs.push_back(IRTArg(
943 IIRB.Int64Ty, "size", "The allocation size.",
945 getSize, setSize));
946 if (Config.has(PassAlignment))
947 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
948 "The allocation alignment.", IRTArg::NONE,
949 getAlignment));
950
951 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
952 IConf.addChoice(*this, IIRB.Ctx);
953}
954
957 auto &AI = cast<AllocaInst>(V);
958 const DataLayout &DL = AI.getDataLayout();
959 Value *SizeValue = nullptr;
960 TypeSize TypeSize = DL.getTypeAllocSize(AI.getAllocatedType());
961 if (TypeSize.isFixed()) {
962 SizeValue = getCI(&Ty, TypeSize.getFixedValue());
963 } else {
964 auto *NullPtr = ConstantPointerNull::get(AI.getType());
965 SizeValue = IIRB.IRB.CreatePtrToInt(
966 IIRB.IRB.CreateGEP(AI.getAllocatedType(), NullPtr,
967 {IIRB.IRB.getInt32(1)}),
968 &Ty);
969 }
970 if (AI.isArrayAllocation())
971 SizeValue = IIRB.IRB.CreateMul(
972 SizeValue, IIRB.IRB.CreateZExtOrBitCast(AI.getArraySize(), &Ty));
973 return SizeValue;
974}
975
978 auto &AI = cast<AllocaInst>(V);
979 const DataLayout &DL = AI.getDataLayout();
980 auto *NewAI = IIRB.IRB.CreateAlloca(IIRB.IRB.getInt8Ty(),
981 DL.getAllocaAddrSpace(), &NewV);
982 NewAI->setAlignment(AI.getAlign());
983 AI.replaceAllUsesWith(NewAI);
984 IIRB.eraseLater(&AI);
985 return NewAI;
986}
987
990 return getCI(&Ty, cast<AllocaInst>(V).getAlign().value());
991}
992///}
993
995 ConfigTy *UserConfig) {
996 if (UserConfig)
997 Config = *UserConfig;
998
1000 if (Config.has(PassPointer)) {
1001 IRTArgs.push_back(
1002 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1003 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1004 : IRTArg::NONE),
1006 }
1007 if (Config.has(PassPointerAS)) {
1008 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1009 "The address space of the accessed pointer.",
1011 }
1012 if (Config.has(PassStoredValue)) {
1013 IRTArgs.push_back(
1014 IRTArg(getValueType(IIRB), "value", "The stored value.",
1017 : IRTArg::NONE),
1018 getValue));
1019 }
1020 if (Config.has(PassStoredValueSize)) {
1021 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1022 "The size of the stored value.", IRTArg::NONE,
1023 getValueSize));
1024 }
1025 if (Config.has(PassAlignment)) {
1026 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1027 "The known access alignment.", IRTArg::NONE,
1028 getAlignment));
1029 }
1030 if (Config.has(PassValueTypeId)) {
1031 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1032 "The type id of the stored value.", IRTArg::NONE,
1034 }
1035 if (Config.has(PassAtomicityOrdering)) {
1036 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1037 "The atomicity ordering of the store.",
1039 }
1040 if (Config.has(PassSyncScopeId)) {
1041 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1042 "The sync scope id of the store.", IRTArg::NONE,
1044 }
1045 if (Config.has(PassIsVolatile)) {
1046 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1047 "Flag indicating a volatile store.", IRTArg::NONE,
1048 isVolatile));
1049 }
1050
1051 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1052 IConf.addChoice(*this, IIRB.Ctx);
1053}
1054
1057 auto &SI = cast<StoreInst>(V);
1058 return SI.getPointerOperand();
1059}
1060
1063 auto &SI = cast<StoreInst>(V);
1064 SI.setOperand(SI.getPointerOperandIndex(), &NewV);
1065 return &SI;
1066}
1067
1070 auto &SI = cast<StoreInst>(V);
1071 return getCI(&Ty, SI.getPointerAddressSpace());
1072}
1073
1076 auto &SI = cast<StoreInst>(V);
1077 return SI.getValueOperand();
1078}
1079
1082 auto &SI = cast<StoreInst>(V);
1083 auto &DL = SI.getDataLayout();
1084 return getCI(&Ty, DL.getTypeStoreSize(SI.getValueOperand()->getType()));
1085}
1086
1089 auto &SI = cast<StoreInst>(V);
1090 return getCI(&Ty, SI.getAlign().value());
1091}
1092
1095 auto &SI = cast<StoreInst>(V);
1096 return getCI(&Ty, SI.getValueOperand()->getType()->getTypeID());
1097}
1098
1100 InstrumentationConfig &IConf,
1102 auto &SI = cast<StoreInst>(V);
1103 return getCI(&Ty, uint64_t(SI.getOrdering()));
1104}
1105
1108 auto &SI = cast<StoreInst>(V);
1109 return getCI(&Ty, uint64_t(SI.getSyncScopeID()));
1110}
1111
1114 auto &SI = cast<StoreInst>(V);
1115 return getCI(&Ty, SI.isVolatile());
1116}
1117
1119 ConfigTy *UserConfig) {
1121 if (UserConfig)
1122 Config = *UserConfig;
1123 if (Config.has(PassPointer)) {
1124 IRTArgs.push_back(
1125 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1126 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1127 : IRTArg::NONE),
1129 }
1130 if (Config.has(PassPointerAS)) {
1131 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1132 "The address space of the accessed pointer.",
1134 }
1135 if (!IsPRE && Config.has(PassValue)) {
1136 IRTArgs.push_back(
1137 IRTArg(getValueType(IIRB), "value", "The loaded value.",
1138 Config.has(ReplaceValue)
1141 : IRTArg::NONE)
1142 : IRTArg::NONE,
1143 getValue, Config.has(ReplaceValue) ? replaceValue : nullptr));
1144 }
1145 if (Config.has(PassValueSize)) {
1146 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1147 "The size of the loaded value.", IRTArg::NONE,
1148 getValueSize));
1149 }
1150 if (Config.has(PassAlignment)) {
1151 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1152 "The known access alignment.", IRTArg::NONE,
1153 getAlignment));
1154 }
1155 if (Config.has(PassValueTypeId)) {
1156 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1157 "The type id of the loaded value.", IRTArg::NONE,
1159 }
1160 if (Config.has(PassAtomicityOrdering)) {
1161 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1162 "The atomicity ordering of the load.",
1164 }
1165 if (Config.has(PassSyncScopeId)) {
1166 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1167 "The sync scope id of the load.", IRTArg::NONE,
1169 }
1170 if (Config.has(PassIsVolatile)) {
1171 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1172 "Flag indicating a volatile load.", IRTArg::NONE,
1173 isVolatile));
1174 }
1175
1176 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1177 IConf.addChoice(*this, IIRB.Ctx);
1178}
1179
1182 auto &LI = cast<LoadInst>(V);
1183 return LI.getPointerOperand();
1184}
1185
1188 auto &LI = cast<LoadInst>(V);
1189 LI.setOperand(LI.getPointerOperandIndex(), &NewV);
1190 return &LI;
1191}
1192
1195 auto &LI = cast<LoadInst>(V);
1196 return getCI(&Ty, LI.getPointerAddressSpace());
1197}
1198
1201 return &V;
1202}
1203
1206 auto &LI = cast<LoadInst>(V);
1207 auto &DL = LI.getDataLayout();
1208 return getCI(&Ty, DL.getTypeStoreSize(LI.getType()));
1209}
1210
1213 auto &LI = cast<LoadInst>(V);
1214 return getCI(&Ty, LI.getAlign().value());
1215}
1216
1219 auto &LI = cast<LoadInst>(V);
1220 return getCI(&Ty, LI.getType()->getTypeID());
1221}
1222
1224 InstrumentationConfig &IConf,
1226 auto &LI = cast<LoadInst>(V);
1227 return getCI(&Ty, uint64_t(LI.getOrdering()));
1228}
1229
1232 auto &LI = cast<LoadInst>(V);
1233 return getCI(&Ty, uint64_t(LI.getSyncScopeID()));
1234}
1235
1238 auto &LI = cast<LoadInst>(V);
1239 return getCI(&Ty, LI.isVolatile());
1240}
1241
1243 ConfigTy *UserConfig) {
1244 if (UserConfig)
1245 Config = *UserConfig;
1246
1247 if (Config.has(PassName))
1248 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "module_name",
1249 "The module/translation unit name.",
1251 if (Config.has(PassTargetTriple))
1252 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "target_triple", "The target triple.",
1254
1255 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1256 IConf.addChoice(*this, IIRB.Ctx);
1257}
1260 // V is a constructor or destructor of the module we can place code in.
1261 auto &Fn = cast<Function>(V);
1262 return IConf.getGlobalString(Fn.getParent()->getName(), IIRB);
1263}
1265 InstrumentationConfig &IConf,
1267 // V is a constructor or destructor of the module we can place code in.
1268 auto &Fn = cast<Function>(V);
1269 return IConf.getGlobalString(Fn.getParent()->getTargetTriple().getTriple(),
1270 IIRB);
1271}
1272
1274 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1275 if (UserConfig)
1276 Config = *UserConfig;
1278 if (Config.has(PassAddress))
1279 IRTArgs.push_back(IRTArg(
1280 IIRB.PtrTy, "address",
1281 "The address of the global (replaceable for definitions).",
1284 if (Config.has(PassAS))
1285 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "address_space",
1286 "The address space of the global.", IRTArg::NONE,
1287 getAS));
1288 if (Config.has(PassDeclaredSize))
1289 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "declared_size",
1290 "The size of the declared type of the global.",
1292 if (Config.has(PassAlignment))
1293 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1294 "The allocation alignment.", IRTArg::NONE,
1295 getAlignment));
1296 if (Config.has(PassName))
1297 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The name of the global.",
1299 if (Config.has(PassInitialValue))
1300 IRTArgs.push_back(IRTArg(
1301 IIRB.Int64Ty, "initial_value", "The initial value of the global.",
1304 if (Config.has(PassIsConstant))
1305 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_constant",
1306 "Flag to indicate constant globals.", IRTArg::NONE,
1307 isConstant));
1308 if (Config.has(PassIsDefinition))
1309 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_definition",
1310 "Flag to indicate global definitions.",
1312 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1313 IConf.addChoice(*this, IIRB.Ctx);
1314}
1318 if (GV.getAddressSpace())
1319 return ConstantExpr::getAddrSpaceCast(&GV, IIRB.PtrTy);
1320 return &GV;
1321}
1323 InstrumentationConfig &IConf,
1326
1327 GlobalVariable *ShadowGV = nullptr;
1328 auto ShadowName = IConf.getRTName("shadow.", GV.getName());
1329 auto &DL = GV.getDataLayout();
1330 if (GV.isDeclaration()) {
1331 ShadowGV = new GlobalVariable(*GV.getParent(), GV.getType(), false,
1333 ShadowName, &GV, GV.getThreadLocalMode(),
1334 DL.getDefaultGlobalsAddressSpace());
1335 } else {
1336 ShadowGV = new GlobalVariable(
1337 *GV.getParent(), NewV.getType(), false, GV.getLinkage(),
1338 PoisonValue::get(NewV.getType()), ShadowName, &GV);
1339 IIRB.IRB.CreateStore(&NewV, ShadowGV);
1340 }
1341
1345 DenseMap<Value *, Instruction *> ConstToInstMap;
1347
1348 auto MakeInstForConst = [&](Use &U) {
1349 Instruction *&I = ConstToInstMap[U];
1350 if (I)
1351 return;
1352 if (U == &GV) {
1353 } else if (auto *CE = dyn_cast<ConstantExpr>(U)) {
1354 I = CE->getAsInstruction();
1355 }
1356 };
1357
1358 auto InsertConsts = [&](Instruction *UserI, Use &UserU) {
1360 auto *&Reload = ReloadMap[UserI->getFunction()];
1361 if (!Reload) {
1362 Reload = new LoadInst(
1363 GV.getType(), ShadowGV, GV.getName() + ".shadow_load",
1365 IIRB.NewInsts.insert({Reload, IIRB.Epoch});
1366 }
1367 Worklist.push_back({UserI, &UserU});
1368 while (!Worklist.empty()) {
1369 auto [I, U] = Worklist.pop_back_val();
1370 if (*U == &GV) {
1371 U->set(ReloadMap[I->getFunction()]);
1372 continue;
1373 }
1374 if (auto *CI = ConstToInstMap[*U]) {
1375 auto *CIClone = CI->clone();
1376 IIRB.NewInsts.insert({CIClone, IIRB.Epoch});
1377 if (auto *PHI = dyn_cast<PHINode>(I)) {
1378 auto *BB = PHI->getIncomingBlock(U->getOperandNo());
1379 CIClone->insertBefore(BB->getTerminator()->getIterator());
1380 } else {
1381 CIClone->insertBefore(I->getIterator());
1382 }
1383 U->set(CIClone);
1384 for (auto &CICUse : CIClone->operands()) {
1385 Worklist.push_back({CIClone, &CICUse});
1386 }
1387 }
1388 }
1389 };
1390
1391 SmallPtrSet<Use *, 8> Visited;
1392 while (!Worklist.empty()) {
1393 Use *U = Worklist.pop_back_val();
1394 if (!Done.insert(U).second)
1395 continue;
1396 MakeInstForConst(*U);
1397 auto *I = dyn_cast<Instruction>(U->getUser());
1398 if (!I) {
1399 append_range(Worklist, make_pointer_range(U->getUser()->uses()));
1400 continue;
1401 }
1402 if (IIRB.NewInsts.lookup(I) == IIRB.Epoch)
1403 continue;
1405 continue;
1406 if (auto *II = dyn_cast<IntrinsicInst>(I))
1407 if (II->getIntrinsicID() == Intrinsic::eh_typeid_for)
1408 continue;
1409 if (I->getParent())
1410 InsertConsts(I, *U);
1411 }
1412
1413 for (auto &It : ConstToInstMap)
1414 if (It.second)
1415 It.second->deleteValue();
1416
1417 return &V;
1418}
1422 return getCI(&Ty, GV.getAddressSpace());
1423}
1425 InstrumentationConfig &IConf,
1428 return getCI(&Ty, GV.getAlignment());
1429}
1431 InstrumentationConfig &IConf,
1434 auto &DL = GV.getDataLayout();
1435 return getCI(&Ty, DL.getTypeAllocSize(GV.getValueType()));
1436}
1438 InstrumentationConfig &IConf,
1441 return IConf.getGlobalString(GV.getName(), IIRB);
1442}
1453 return getCI(&Ty, GV.isConstant());
1454}
1456 InstrumentationConfig &IConf,
1459 return getCI(&Ty, !GV.isDeclaration());
1460}
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:558
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...
EnumeratedArray< MapVector< StringRef, InstrumentationOpportunity * >, InstrumentationLocation::KindTy > IChoices
The map registered instrumentation opportunities.
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
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