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
18
20#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/iterator.h"
28#include "llvm/IR/Constant.h"
29#include "llvm/IR/Constants.h"
30#include "llvm/IR/DataLayout.h"
33#include "llvm/IR/Function.h"
34#include "llvm/IR/IRBuilder.h"
35#include "llvm/IR/InstrTypes.h"
36#include "llvm/IR/Instruction.h"
39#include "llvm/IR/Intrinsics.h"
40#include "llvm/IR/LLVMContext.h"
41#include "llvm/IR/Metadata.h"
42#include "llvm/IR/Module.h"
43#include "llvm/IR/PassManager.h"
44#include "llvm/IR/Verifier.h"
48#include "llvm/Support/Regex.h"
52
53#include <cassert>
54#include <cstdint>
55#include <functional>
56#include <iterator>
57#include <memory>
58#include <string>
59#include <system_error>
60#include <type_traits>
61
62using namespace llvm;
63using namespace llvm::instrumentor;
64
65#define DEBUG_TYPE "instrumentor"
66
67namespace {
68
69/// The user option to specify an output JSON file to write the configuration.
70static cl::opt<std::string> OutputConfigFile(
71 "instrumentor-write-config-file",
73 "Write the instrumentor configuration into the specified JSON file"),
74 cl::init(""));
75
76/// The user option to specify input JSON files to read the configuration from.
78 ConfigFiles("instrumentor-read-config-files",
79 cl::desc("Read the instrumentor configuration from the "
80 "specified JSON files (comma separated)"),
82
83/// The user option to specify an input file to read the configuration file
84/// paths from.
85static cl::opt<std::string> ConfigPathsFile(
86 "instrumentor-read-config-paths-file",
87 cl::desc("Read the instrumentor configuration file "
88 "paths from the specified file (newline separated)"),
89 cl::init(""));
90
91/// Set the debug location, if not set, after changing the insertion point of
92/// the IR builder \p IRB.
93template <typename IRBuilderTy> void ensureDbgLoc(IRBuilderTy &IRB) {
94 if (IRB.getCurrentDebugLocation())
95 return;
96 auto *BB = IRB.GetInsertBlock();
97 if (auto *SP = BB->getParent()->getSubprogram())
98 IRB.SetCurrentDebugLocation(DILocation::get(BB->getContext(), 0, 0, SP));
99}
100
101/// Attempt to cast \p V to type \p Ty using only bit-preserving casts.
102/// This ensures that floating-point values are converted via bitcast (not
103/// fptosi/fptoui) to preserve their exact bit representation.
104template <typename IRBTy>
105Value *tryToCast(IRBTy &IRB, Value *V, Type *Ty, const DataLayout &DL,
106 bool AllowTruncate = false) {
107 if (!V)
108 return Constant::getAllOnesValue(Ty);
109 Type *VTy = V->getType();
110 if (VTy == Ty)
111 return V;
112 if (VTy->isAggregateType() || VTy->isVectorTy())
113 return V;
114 TypeSize RequestedSize = DL.getTypeSizeInBits(Ty);
115 TypeSize ValueSize = DL.getTypeSizeInBits(VTy);
116 bool ShouldTruncate = RequestedSize < ValueSize;
117 if (ShouldTruncate && !AllowTruncate)
118 return V;
119 if (ShouldTruncate && AllowTruncate) {
120 // First convert to integer of the same size if needed.
121 Value *IntV = V;
122 if (VTy->isFloatingPointTy())
123 IntV = IRB.CreateBitCast(V, IRB.getIntNTy(ValueSize));
124 return tryToCast(IRB,
125 IRB.CreateIntCast(IntV, IRB.getIntNTy(RequestedSize),
126 /*IsSigned=*/false),
127 Ty, DL, AllowTruncate);
128 }
129 if (VTy->isPointerTy() && Ty->isPointerTy())
130 return IRB.CreatePointerBitCastOrAddrSpaceCast(V, Ty);
131 if (VTy->isIntegerTy() && Ty->isIntegerTy())
132 return IRB.CreateIntCast(V, Ty, /*IsSigned=*/false);
133 // Use bit-preserving casts for floating-point values: convert float to int
134 // of the same size via bitcast, then extend/truncate the integer if needed.
135 if (VTy->isFloatingPointTy() && Ty->isIntOrPtrTy()) {
136 return tryToCast(IRB, IRB.CreateBitCast(V, IRB.getIntNTy(ValueSize)), Ty,
137 DL, AllowTruncate);
138 }
139 // When converting int to float, never use sitofp/uitofp as they perform value
140 // conversion, not bit-preserving cast.
141 if (VTy->isIntegerTy() && Ty->isFloatingPointTy()) {
142 if (ValueSize == RequestedSize)
143 return IRB.CreateBitCast(V, Ty);
144 return tryToCast(
145 IRB,
146 IRB.CreateIntCast(V, IRB.getIntNTy(RequestedSize), /*IsSigned=*/false),
147 Ty, DL, AllowTruncate);
148 }
149 return IRB.CreateBitOrPointerCast(V, Ty);
150}
151
152/// Get a constant integer/boolean of type \p IT and value \p Val.
153template <typename Ty>
154Constant *getCI(Type *IT, Ty Val, bool IsSigned = false) {
155 return ConstantInt::get(IT, Val, IsSigned);
156}
157
158Constant *getSubTypeID(Type &OpTy, Type &ReqTy) {
159 switch (OpTy.getTypeID()) {
160 case Type::TypeID::ArrayTyID:
161 case Type::TypeID::FixedVectorTyID:
162 case Type::TypeID::ScalableVectorTyID:
163 return getCI(&ReqTy, OpTy.getContainedType(0)->getTypeID());
164 default:
165 break;
166 }
167
168 return getCI(&ReqTy, -1, /*IsSigned=*/true);
169}
170
171/// The core of the instrumentor pass, which instruments the module as the
172/// instrumentation configuration mandates.
173class InstrumentorImpl final {
174public:
175 /// Construct an instrumentor implementation using the configuration \p IConf.
176 InstrumentorImpl(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
177 Module &M)
178 : IConf(IConf), M(M), IIRB(IIRB) {}
179
180 /// Instrument the module, public entry point.
181 bool instrument();
182
183 // Reset the state to allow reuse of the instrumentor with a different
184 // configuration.
185 void clear() {
186 InstChoicesPRE.clear();
187 InstChoicesPOST.clear();
188 ParsedFunctionRegex = Regex();
189 }
190
191private:
192 /// Indicate if the module should be instrumented based on the target.
193 bool shouldInstrumentTarget();
194
195 /// Indicate if the function \p Fn should be instrumented.
196 bool shouldInstrumentFunction(Function &Fn);
197 bool shouldInstrumentGlobalVariable(GlobalVariable &GV);
198
199 /// Instrument instruction \p I if needed, and use the argument caches in \p
200 /// ICaches.
201 bool instrumentInstruction(Instruction &I, InstrumentationCaches &ICaches);
202
203 /// Instrument function \p Fn.
204 bool instrumentFunction(Function &Fn);
205 bool instrumentModule();
206
207 /// The instrumentation opportunities for instructions indexed by
208 /// their opcode.
210 InstChoicesPOST;
211
212 /// The instrumentor configuration.
214
215 /// The function regex filter, if any.
216 Regex ParsedFunctionRegex;
217
218 /// The underlying module.
219 Module &M;
220
221protected:
222 /// A special IR builder that keeps track of the inserted instructions.
224};
225
226} // end anonymous namespace
227
229 if (!Str.empty()) {
230 Regex RX(Str);
231 std::string ErrMsg;
232 if (!RX.isValid(ErrMsg)) {
234 Twine("failed to parse ") + Name + " regex: " + ErrMsg, DS_Error));
235 return Regex();
236 }
237 return RX;
238 }
239 return Regex();
240}
241
242bool InstrumentorImpl::shouldInstrumentTarget() {
243 const Triple &T = M.getTargetTriple();
244 const bool IsGPU = T.isAMDGPU() || T.isNVPTX();
245
246 bool RegexMatches = true;
247 Regex RX = createRegex(IConf.TargetRegex->getString(), "target", IIRB.Ctx);
248 if (RX.isValid())
249 RegexMatches = RX.match(T.str());
250
251 // Only instrument the module if the target has to be instrumented.
252 return ((IsGPU && IConf.GPUEnabled->getBool()) ||
253 (!IsGPU && IConf.HostEnabled->getBool())) &&
254 RegexMatches;
255}
256
257bool InstrumentorImpl::shouldInstrumentFunction(Function &Fn) {
258 if (Fn.isDeclaration())
259 return false;
260 bool RegexMatches = true;
261 if (ParsedFunctionRegex.isValid())
262 RegexMatches = ParsedFunctionRegex.match(Fn.getName());
263 return (RegexMatches && !Fn.getName().starts_with(IConf.getRTName())) ||
264 Fn.hasFnAttribute("instrument");
265}
266
267bool InstrumentorImpl::shouldInstrumentGlobalVariable(GlobalVariable &GV) {
268 return !GV.getName().starts_with("llvm.") &&
269 !GV.getName().starts_with(IConf.getRTName());
270}
271
272bool InstrumentorImpl::instrumentInstruction(Instruction &I,
273 InstrumentationCaches &ICaches) {
274 bool Changed = false;
275
276 // Skip instrumentation instructions.
277 if (IIRB.NewInsts.contains(&I))
278 return Changed;
279
280 // Count epochs eagerly.
281 ++IIRB.Epoch;
282
283 Value *IPtr = &I;
284 if (auto *IO = InstChoicesPRE.lookup(I.getOpcode())) {
285 IIRB.IRB.SetInsertPoint(&I);
286 ensureDbgLoc(IIRB.IRB);
287 IO->instrument(IPtr, Changed, IConf, IIRB, ICaches);
288 }
289
290 if (auto *IO = InstChoicesPOST.lookup(I.getOpcode())) {
291 IIRB.IRB.SetInsertPoint(I.getNextNode());
292 ensureDbgLoc(IIRB.IRB);
293 IO->instrument(IPtr, Changed, IConf, IIRB, ICaches);
294 }
295 IIRB.returnAllocas();
296
297 return Changed;
298}
299
300bool InstrumentorImpl::instrumentFunction(Function &Fn) {
301 bool Changed = false;
302 if (!shouldInstrumentFunction(Fn))
303 return Changed;
304
305 InstrumentationCaches ICaches;
307 ReversePostOrderTraversal<Function *> RPOT(&Fn);
308 for (auto &It : RPOT) {
309 for (auto &I : *It)
310 Changed |= instrumentInstruction(I, ICaches);
311
312 auto *TI = It->getTerminator();
313 if (!TI->getNumSuccessors())
314 FinalTIs.push_back(TI);
315 }
316
317 Value *FPtr = &Fn;
318 for (auto &[Name, IO] :
320 if (!IO->Enabled)
321 continue;
322 // Count epochs eagerly.
323 ++IIRB.Epoch;
324
325 IIRB.IRB.SetInsertPoint(
326 cast<Function>(FPtr)->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
327 ensureDbgLoc(IIRB.IRB);
328 IO->instrument(FPtr, Changed, IConf, IIRB, ICaches);
329 IIRB.returnAllocas();
330 }
331
332 for (auto &[Name, IO] :
334 if (!IO->Enabled)
335 continue;
336 // Count epochs eagerly.
337 ++IIRB.Epoch;
338
339 for (Instruction *FinalTI : FinalTIs) {
340 IIRB.IRB.SetInsertPoint(FinalTI);
341 ensureDbgLoc(IIRB.IRB);
342 IO->instrument(FPtr, Changed, IConf, IIRB, ICaches);
343 IIRB.returnAllocas();
344 }
345 }
346 return Changed;
347}
348
349bool InstrumentorImpl::instrumentModule() {
351 Globals.reserve(M.global_size());
352 for (GlobalVariable &GV : M.globals()) {
353 // llvm.metadata contains globals such as llvm.used.
354 if (GV.getSection() == "llvm.metadata" ||
355 GV.getName() == "llvm.global_dtors" ||
356 GV.getName() == "llvm.global_ctors")
357 continue;
358 Globals.push_back(&GV);
359 }
360
361 auto CreateYtor = [&](bool Ctor) {
362 Function *YtorFn = Function::Create(
363 FunctionType::get(IIRB.VoidTy, false), GlobalValue::PrivateLinkage,
364 IConf.getRTName(Ctor ? "ctor" : "dtor", ""), M);
365
366 auto *EntryBB = BasicBlock::Create(IIRB.Ctx, "entry", YtorFn);
367 IIRB.IRB.SetInsertPoint(EntryBB, EntryBB->begin());
368 ensureDbgLoc(IIRB.IRB);
369 IIRB.IRB.CreateRetVoid();
370
371 if (Ctor)
372 appendToGlobalCtors(M, YtorFn, 1000);
373 else
374 appendToGlobalDtors(M, YtorFn, 1000);
375 return YtorFn;
376 };
377
378 InstrumentationCaches ICaches;
379
380 Function *CtorFn = nullptr, *DtorFn = nullptr;
381 bool Changed = false;
384 bool IsPRE = InstrumentationLocation::isPRE(Loc);
385 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
386 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
387 auto *IO = ChoiceIt.second;
388 if (!IO->Enabled)
389 continue;
390 if (!YtorFn) {
391 YtorFn = CreateYtor(IsPRE);
392 Changed = true;
393 }
394 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
395 ensureDbgLoc(IIRB.IRB);
396 Value *YtorPtr = YtorFn;
397
398 // Count epochs eagerly.
399 ++IIRB.Epoch;
400
401 IO->instrument(YtorPtr, Changed, IConf, IIRB, ICaches);
402 IIRB.returnAllocas();
403 }
404 }
405
408 bool IsPRE = InstrumentationLocation::isPRE(Loc);
409 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
410 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
411 auto *IO = ChoiceIt.second;
412 if (!IO->Enabled)
413 continue;
414 if (!YtorFn) {
415 YtorFn = CreateYtor(IsPRE);
416 Changed = true;
417 }
418 for (GlobalVariable *GV : Globals) {
419 if (!shouldInstrumentGlobalVariable(*GV))
420 continue;
421 if (IsPRE)
422 IIRB.IRB.SetInsertPoint(YtorFn->getEntryBlock().getTerminator());
423 else
424 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
425 ensureDbgLoc(IIRB.IRB);
426 Value *GVPtr = GV;
427
428 // Count epochs eagerly.
429 ++IIRB.Epoch;
430
431 IO->instrument(GVPtr, Changed, IConf, IIRB, ICaches);
432 IIRB.returnAllocas();
433 }
434 }
435 }
436
437 return Changed;
438}
439
440bool InstrumentorImpl::instrument() {
441 bool Changed = false;
442 if (!shouldInstrumentTarget())
443 return Changed;
444
445 StringRef FunctionRegexStr = IConf.FunctionRegex->getString();
446 ParsedFunctionRegex = createRegex(FunctionRegexStr, "function", IIRB.Ctx);
447
448 // Helper to register an IO for all its opcodes.
449 auto RegisterForAllOpcodes = [](auto &InstChoices,
450 InstrumentationOpportunity *IO) {
451 ArrayRef<unsigned> Opcodes = IO->getAllOpcodes();
452 // Register for all opcodes.
453 for (unsigned Opcode : Opcodes)
454 InstChoices[Opcode] = IO;
455 };
456
457 for (auto &[Name, IO] :
459 if (IO->Enabled)
460 RegisterForAllOpcodes(InstChoicesPRE, IO);
461 for (auto &[Name, IO] :
463 if (IO->Enabled)
464 RegisterForAllOpcodes(InstChoicesPOST, IO);
465 Changed |= instrumentModule();
466
467 for (Function &Fn : M)
468 Changed |= instrumentFunction(Fn);
469
470 return Changed;
471}
472
474 InstrumentationConfig *IC,
475 InstrumentorIRBuilderTy *IIRB)
476 : FS(FS), UserIConf(IC), UserIIRB(IIRB) {
477 if (!FS)
478 this->FS = vfs::getRealFileSystem();
479}
480
481PreservedAnalyses InstrumentorPass::run(Module &M, InstrumentationConfig &IConf,
483 bool ReadConfig) {
484 bool Changed = false;
485 InstrumentorImpl Impl(IConf, IIRB, M);
486
487 // If this is a configuration driven run, iterate over all configurations
488 // provided by the user, if not, use the config as is and run the instrumentor
489 // once.
490 if (ReadConfig)
491 readConfigPathsFile(ConfigPathsFile, ConfigFiles, IIRB.Ctx, *FS);
492
493 bool MultipleConfigs = ConfigFiles.size() > 1;
494 unsigned Idx = 0;
495 do {
496 std::string ConfigFile =
497 ReadConfig && !ConfigFiles.empty() ? ConfigFiles[Idx] : "";
498
499 // Initialize the config to the base state but keep the caches around.
500 Impl.clear();
501 IConf.init(IIRB);
502
503 if (!readConfigFromJSON(IConf, ConfigFile, IIRB.Ctx, *FS))
504 continue;
505
506 writeConfigToJSON(IConf,
507 MultipleConfigs
508 ? OutputConfigFile + "." + std::to_string(Idx)
509 : OutputConfigFile,
510 IIRB.Ctx);
511
512 printRuntimeStub(IConf, IConf.RuntimeStubsFile->getString(), IIRB.Ctx);
513
514 Changed |= Impl.instrument();
515 } while (++Idx < ConfigFiles.size());
516
517 if (!Changed)
518 return PreservedAnalyses::all();
520}
521
523 // Only create them if the user did not provide them.
524 std::unique_ptr<InstrumentationConfig> IConfInt(
525 !UserIConf ? new InstrumentationConfig() : nullptr);
526 std::unique_ptr<InstrumentorIRBuilderTy> IIRBInt(
527 !UserIIRB ? new InstrumentorIRBuilderTy(M) : nullptr);
528
529 auto *IConf = IConfInt ? IConfInt.get() : UserIConf;
530 auto *IIRB = IIRBInt ? IIRBInt.get() : UserIIRB;
531
532 auto PA = run(M, *IConf, *IIRB, !UserIConf);
533
534 assert(!verifyModule(M, &errs()));
535 return PA;
536}
537
538std::unique_ptr<BaseConfigurationOption>
541 bool DefaultValue) {
542 auto BCO =
543 std::make_unique<BaseConfigurationOption>(Name, Description, BOOLEAN);
544 BCO->setBool(DefaultValue);
545 IConf.addBaseChoice(BCO.get());
546 return BCO;
547}
548
549std::unique_ptr<BaseConfigurationOption>
553 StringRef DefaultValue) {
554 auto BCO =
555 std::make_unique<BaseConfigurationOption>(Name, Description, STRING);
556 BCO->setString(DefaultValue);
557 IConf.addBaseChoice(BCO.get());
558 return BCO;
559}
560
562 /// List of all instrumentation opportunities.
563 BasePointerIO::populate(*this, IIRB);
564 ModuleIO::populate(*this, IIRB);
565 GlobalVarIO::populate(*this, IIRB);
566 FunctionIO::populate(*this, IIRB);
567 AllocaIO::populate(*this, IIRB);
568 UnreachableIO::populate(*this, IIRB);
569 LoadIO::populate(*this, IIRB);
570 StoreIO::populate(*this, IIRB);
571 CastIO::populate(*this, IIRB);
572 NumericIO::populate(*this, IIRB);
573 CompareIO::populate(*this, IIRB);
574}
575
577 LLVMContext &Ctx) {
578 auto *&ICPtr = IChoices[IO.getLocationKind()][IO.getName()];
579 if (ICPtr) {
581 Twine("registered two instrumentation opportunities for the same "
582 "location (") +
583 ICPtr->getName() + Twine(" vs ") + IO.getName() + Twine(")"),
584 DS_Warning));
585 }
586 ICPtr = &IO;
587}
588
589Value *
592 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
593
594 Value *Obj;
595 {
596 Value *&UnderlyingObj = UnderlyingObjsMap[&V];
597 if (!UnderlyingObj)
598 UnderlyingObj = const_cast<Value *>(getUnderlyingObjectAggressive(&V));
599 Obj = UnderlyingObj;
600 }
601
602 Value *&BPI = BasePointerInfoMap[{Obj, Fn}];
603 if (BPI)
604 return BPI;
605
606 auto *BPIO =
608 if (!BPIO || !BPIO->Enabled) {
610 "Base pointer info disabled but required, passing nullptr.",
611 DS_Warning));
612 return BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
613 }
614
616 if (auto *BasePtrI = dyn_cast<Instruction>(Obj)) {
617 std::optional<BasicBlock::iterator> IP =
618 BasePtrI->getInsertionPointAfterDef();
619 if (IP) {
620 IIRB.IRB.SetInsertPoint(*IP);
621 } else {
623 "Base pointer info could not be placed, passing nullptr.",
624 DS_Warning));
625 return BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
626 }
627 } else if (isa<Constant>(Obj) || isa<Argument>(Obj)) {
628 IIRB.IRB.SetInsertPointPastAllocas(IIRB.IRB.GetInsertBlock()->getParent());
629 } else {
630 LLVM_DEBUG(Obj->dump());
631 llvm_unreachable("Unexpected base pointer!");
632 }
633 ensureDbgLoc(IIRB.IRB);
634
635 // Use fresh caches for safety, as this function may be called from
636 // another instrumentation opportunity.
637 bool Changed;
638 InstrumentationCaches ICaches;
639 BPI = BPIO->instrument(Obj, Changed, *this, IIRB, ICaches);
640 IIRB.returnAllocas();
641 if (!BPI)
642 BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
643 return BPI;
644}
645
649 return getCI(&Ty, getIdFromEpoch(IIRB.Epoch));
650}
651
655 return getCI(&Ty, -getIdFromEpoch(IIRB.Epoch), /*IsSigned=*/true);
656}
657
660 if (V.getType()->isVoidTy())
661 return Ty.isVoidTy() ? &V : Constant::getNullValue(&Ty);
662 return tryToCast(IIRB.IRB, &V, &Ty,
663 IIRB.IRB.GetInsertBlock()->getDataLayout());
664}
665
669 if (V.getType()->isVoidTy())
670 return &V;
671
672 auto *NewVCasted = &NewV;
673 if (auto *I = dyn_cast<Instruction>(&NewV)) {
675 IIRB.IRB.SetInsertPoint(I->getNextNode());
676 ensureDbgLoc(IIRB.IRB);
677 NewVCasted = tryToCast(IIRB.IRB, &NewV, V.getType(), IIRB.DL,
678 /*AllowTruncate=*/true);
679 }
680 V.replaceUsesWithIf(NewVCasted, [&](Use &U) {
681 if (IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) == IIRB.Epoch)
682 return false;
683 return !isa<LifetimeIntrinsic>(U.getUser()) && !U.getUser()->isDroppable();
684 });
685
686 return &V;
687}
688
690 Type *RetTy)
691 : IO(IO), RetTy(RetTy) {
692 for (auto &It : IO.IRTArgs) {
693 if (!It.Enabled)
694 continue;
695 NumReplaceableArgs += bool(It.Flags & IRTArg::REPLACABLE);
696 MightRequireIndirection |= It.Flags & IRTArg::POTENTIALLY_INDIRECT;
697 }
700}
701
704 const DataLayout &DL, bool ForceIndirection) {
705 assert(((ForceIndirection && MightRequireIndirection) ||
706 (!ForceIndirection && !RequiresIndirection)) &&
707 "Wrong indirection setting!");
708
709 SmallVector<Type *> ParamTypes;
710 for (auto &It : IO.IRTArgs) {
711 if (!It.Enabled)
712 continue;
713 if (!ForceIndirection || !isPotentiallyIndirect(It)) {
714 ParamTypes.push_back(It.Ty);
715 if (!RetTy && NumReplaceableArgs == 1 && (It.Flags & IRTArg::REPLACABLE))
716 RetTy = It.Ty;
717 continue;
718 }
719
720 // The indirection pointer and the size of the value.
721 ParamTypes.push_back(IIRB.PtrTy);
722 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE))
723 ParamTypes.push_back(IIRB.Int32Ty);
724 }
725 if (!RetTy)
726 RetTy = IIRB.VoidTy;
727
728 return FunctionType::get(RetTy, ParamTypes, /*isVarArg=*/false);
729}
730
734 const DataLayout &DL,
735 InstrumentationCaches &ICaches) {
736 SmallVector<Value *> CallParams;
737
739 auto IP = IIRB.IRB.GetInsertPoint();
740
741 bool ForceIndirection = RequiresIndirection;
742 for (auto &It : IO.IRTArgs) {
743 if (!It.Enabled)
744 continue;
745 auto *&Param = ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
746 if (!Param || It.NoCache)
747 // Avoid passing the caches to the getter.
748 Param = It.GetterCB(*V, *It.Ty, IConf, IIRB);
749 assert(Param);
750
751 if (Param->getType()->isVoidTy()) {
752 Param = Constant::getNullValue(It.Ty);
753 } else if (Param->getType()->isAggregateType() ||
754 Param->getType()->isVectorTy() ||
755 DL.getTypeSizeInBits(Param->getType()) >
756 DL.getTypeSizeInBits(It.Ty)) {
757 if (!isPotentiallyIndirect(It)) {
759 Twine("indirection needed for ") + It.Name + Twine(" in ") +
760 IO.getName() +
761 Twine(", but not indicated. Instrumentation is skipped"),
762 DS_Warning));
763 return nullptr;
764 }
765 ForceIndirection = true;
766 } else {
767 Param = tryToCast(IIRB.IRB, Param, It.Ty, DL);
768 }
769 CallParams.push_back(Param);
770 }
771
772 if (ForceIndirection) {
773 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
774
775 unsigned Offset = 0;
776 for (auto &It : IO.IRTArgs) {
777 if (!It.Enabled)
778 continue;
779
780 if (!isPotentiallyIndirect(It)) {
781 ++Offset;
782 continue;
783 }
784 auto *&CallParam = CallParams[Offset++];
785 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE)) {
786 CallParams.insert(&CallParam + 1, IIRB.IRB.getInt32(DL.getTypeStoreSize(
787 CallParam->getType())));
788 Offset += 1;
789 }
790
791 auto *&CachedParam =
792 ICaches.IndirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
793 if (CachedParam) {
794 CallParam = CachedParam;
795 continue;
796 }
797
798 auto *AI = IIRB.getAlloca(Fn, CallParam->getType());
799 IIRB.IRB.CreateStore(CallParam, AI);
800 CallParam = CachedParam = AI;
801 }
802 }
803
804 if (!ForceIndirection)
805 IIRB.IRB.SetInsertPoint(IP);
806 ensureDbgLoc(IIRB.IRB);
807
808 auto *FnTy = createLLVMSignature(IConf, IIRB, DL, ForceIndirection);
809 auto CompleteName =
810 IConf.getRTName(IO.IP.isPRE() ? "pre_" : "post_", IO.getName(),
811 ForceIndirection ? "_ind" : "");
812 auto FC = IIRB.IRB.GetInsertBlock()->getModule()->getOrInsertFunction(
813 CompleteName, FnTy);
814 auto *CI = IIRB.IRB.CreateCall(FC, CallParams);
815 CI->addFnAttr(Attribute::get(IIRB.Ctx, Attribute::WillReturn));
816
817 for (unsigned I = 0, E = IO.IRTArgs.size(); I < E; ++I) {
818 if (!IO.IRTArgs[I].Enabled)
819 continue;
820 if (!isReplacable(IO.IRTArgs[I]))
821 continue;
822 bool IsCustomReplaceable = IO.IRTArgs[I].Flags & IRTArg::REPLACABLE_CUSTOM;
823 Value *NewValue = FnTy->isVoidTy() || IsCustomReplaceable
824 ? ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(),
825 IO.IRTArgs[I].Name}]
826 : CI;
827 assert(NewValue);
828 if (ForceIndirection && !IsCustomReplaceable &&
829 isPotentiallyIndirect(IO.IRTArgs[I])) {
830 auto *Q =
831 ICaches
832 .IndirectArgCache[{IIRB.Epoch, IO.getName(), IO.IRTArgs[I].Name}];
833 NewValue = IIRB.IRB.CreateLoad(V->getType(), Q);
834 }
835 V = IO.IRTArgs[I].SetterCB(*V, *NewValue, IConf, IIRB);
836 }
837 return CI;
838}
839
840template <typename Ty> constexpr static Value *getValue(Ty &ValueOrUse) {
841 if constexpr (std::is_same<Ty, Use>::value)
842 return ValueOrUse.get();
843 else
844 return static_cast<Value *>(&ValueOrUse);
845}
846
847template <typename Range>
850 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
851 auto *I32Ty = IIRB.IRB.getInt32Ty();
852 SmallVector<Constant *> ConstantValues;
855 for (auto &RE : R) {
856 Value *V = getValue(RE);
857 if (!V->getType()->isSized())
858 continue;
859 auto VSize = IIRB.DL.getTypeAllocSize(V->getType());
860 ConstantValues.push_back(getCI(I32Ty, VSize));
861 Types.push_back(I32Ty);
862 ConstantValues.push_back(getCI(I32Ty, V->getType()->getTypeID()));
863 Types.push_back(I32Ty);
864 if (uint32_t MisAlign = VSize % 8) {
865 Types.push_back(ArrayType::get(IIRB.Int8Ty, 8 - MisAlign));
866 ConstantValues.push_back(ConstantArray::getNullValue(Types.back()));
867 }
868 Types.push_back(V->getType());
869 if (auto *C = dyn_cast<Constant>(V)) {
870 ConstantValues.push_back(C);
871 continue;
872 }
873 Values.push_back({V, ConstantValues.size()});
874 ConstantValues.push_back(Constant::getNullValue(V->getType()));
875 }
876 if (Types.empty())
877 return ConstantPointerNull::get(IIRB.PtrTy);
878
879 StructType *STy = StructType::get(Fn->getContext(), Types, /*isPacked=*/true);
880 Constant *Initializer = ConstantStruct::get(STy, ConstantValues);
881
882 GlobalVariable *&GV = IConf.ConstantGlobalsCache[Initializer];
883 if (!GV)
884 GV = new GlobalVariable(*Fn->getParent(), STy, false,
885 GlobalValue::InternalLinkage, Initializer,
886 IConf.getRTName("", "value_pack"));
887
888 auto *AI = IIRB.getAlloca(Fn, STy);
889 IIRB.IRB.CreateMemCpy(AI, AI->getAlign(), GV, MaybeAlign(GV->getAlignment()),
890 IIRB.DL.getTypeAllocSize(STy));
891 for (auto [Param, Idx] : Values) {
892 auto *Ptr = IIRB.IRB.CreateStructGEP(STy, AI, Idx);
893 IIRB.IRB.CreateStore(Param, Ptr);
894 }
895 return AI;
896}
897
898template <typename Range>
899static void readValuePack(const Range &R, Value &Pack,
901 function_ref<void(int, Value *)> SetterCB) {
902 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
903 auto &DL = Fn->getDataLayout();
904 SmallVector<Value *> ParameterValues;
905 unsigned Offset = 0;
906 for (const auto &[Idx, RE] : enumerate(R)) {
907 Value *V = getValue(RE);
908 if (!V->getType()->isSized())
909 continue;
910 Offset += 8;
911 auto VSize = DL.getTypeAllocSize(V->getType());
912 auto Padding = alignTo(VSize, 8) - VSize;
913 Offset += Padding;
914 auto *Ptr = IIRB.IRB.CreateConstInBoundsGEP1_32(IIRB.Int8Ty, &Pack, Offset);
915 auto *NewV = IIRB.IRB.CreateLoad(V->getType(), Ptr);
916 SetterCB(Idx, NewV);
917 Offset += VSize;
918 }
919}
920
924 auto &I = cast<Instruction>(V);
925 return getCI(&Ty, I.getOpcode());
926}
927
931 auto &I = cast<Instruction>(V);
932 auto &DL = I.getDataLayout();
933 return getCI(&Ty, DL.getTypeStoreSize(V.getType()));
934}
935
939 auto &I = cast<Instruction>(V);
940 return I.getOperand(0);
941}
942
946 auto &I = cast<Instruction>(V);
947 if (I.getNumOperands() > 1)
948 return I.getOperand(1);
949 return PoisonValue::get(&Ty);
950}
951
955 return getCI(&Ty, V.getType()->getTypeID());
956}
957
961 return getSubTypeID(*V.getType(), Ty);
962}
963
964/// FunctionIO
965/// {
967 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
968 using namespace std::placeholders;
969 if (UserConfig)
970 Config = *UserConfig;
971
973 if (Config.has(PassAddress))
974 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "address", "The function address.",
976 if (Config.has(PassName))
977 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The function name.",
979 if (Config.has(PassNumArguments))
980 IRTArgs.push_back(
981 IRTArg(IIRB.Int32Ty, "num_arguments",
982 "Number of function arguments (without varargs).", IRTArg::NONE,
983 std::bind(&FunctionIO::getNumArguments, this, _1, _2, _3, _4)));
984 if (Config.has(PassArguments))
985 IRTArgs.push_back(IRTArg(
986 IIRB.PtrTy, "arguments", "Description of the arguments.",
988 : IRTArg::NONE) |
990 std::bind(&FunctionIO::getArguments, this, _1, _2, _3, _4),
991 std::bind(&FunctionIO::setArguments, this, _1, _2, _3, _4)));
992 if (Config.has(PassIsMain))
993 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_main",
994 "Flag to indicate it is the main function.",
996 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
997 IConf.addChoice(*this, IIRB.Ctx);
998}
999
1001 InstrumentationConfig &IConf,
1003 auto &Fn = cast<Function>(V);
1004 if (Fn.isIntrinsic())
1005 return Constant::getNullValue(&Ty);
1006 return &V;
1007}
1009 InstrumentationConfig &IConf,
1011 auto &Fn = cast<Function>(V);
1012 return IConf.getGlobalString(IConf.DemangleFunctionNames->getBool()
1013 ? demangle(Fn.getName())
1014 : Fn.getName(),
1015 IIRB);
1016}
1018 InstrumentationConfig &IConf,
1020 auto &Fn = cast<Function>(V);
1021 if (!Config.ArgFilter)
1022 return getCI(&Ty, Fn.arg_size());
1023 auto FRange = make_filter_range(Fn.args(), Config.ArgFilter);
1024 return getCI(&Ty, std::distance(FRange.begin(), FRange.end()));
1025}
1027 InstrumentationConfig &IConf,
1029 auto &Fn = cast<Function>(V);
1030 if (!Config.ArgFilter)
1031 return createValuePack(Fn.args(), IConf, IIRB);
1032 return createValuePack(make_filter_range(Fn.args(), Config.ArgFilter), IConf,
1033 IIRB);
1034}
1036 InstrumentationConfig &IConf,
1038 auto &Fn = cast<Function>(V);
1039 auto *AIt = Fn.arg_begin();
1040 auto CB = [&](int Idx, Value *ReplV) {
1041 while (Config.ArgFilter && !Config.ArgFilter(*AIt))
1042 ++AIt;
1043 Fn.getArg(Idx)->replaceUsesWithIf(ReplV, [&](Use &U) {
1044 return IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) != IIRB.Epoch;
1045 });
1046 ++AIt;
1047 };
1048 if (!Config.ArgFilter)
1049 readValuePack(Fn.args(), NewV, IIRB, CB);
1050 else
1051 readValuePack(make_filter_range(Fn.args(), Config.ArgFilter), NewV, IIRB,
1052 CB);
1053 return &Fn;
1054}
1056 InstrumentationConfig &IConf,
1058 auto &Fn = cast<Function>(V);
1059 return getCI(&Ty, Fn.getName() == "main");
1060}
1061
1062/// UnreachableIO
1063///{
1065 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1066 if (UserConfig)
1067 Config = *UserConfig;
1068 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1069 IConf.addChoice(*this, IIRB.Ctx);
1070}
1071///}
1072
1073/// AllocaIO
1074///{
1076 ConfigTy *UserConfig) {
1077 if (UserConfig)
1078 Config = *UserConfig;
1079
1081 if (!IsPRE && Config.has(PassAddress))
1082 IRTArgs.push_back(
1083 IRTArg(IIRB.PtrTy, "address", "The allocated memory address.",
1087 if (Config.has(PassSize))
1088 IRTArgs.push_back(IRTArg(
1089 IIRB.Int64Ty, "size", "The allocation size.",
1091 getSize, setSize));
1092 if (Config.has(PassAlignment))
1093 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1094 "The allocation alignment.", IRTArg::NONE,
1095 getAlignment));
1096
1097 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1098 IConf.addChoice(*this, IIRB.Ctx);
1099}
1100
1103 auto &AI = cast<AllocaInst>(V);
1104 const DataLayout &DL = AI.getDataLayout();
1105 Value *SizeValue = nullptr;
1106 TypeSize TypeSize = DL.getTypeAllocSize(AI.getAllocatedType());
1107 if (TypeSize.isFixed()) {
1108 SizeValue = getCI(&Ty, TypeSize.getFixedValue());
1109 } else {
1110 auto *NullPtr = ConstantPointerNull::get(AI.getType());
1111 SizeValue = IIRB.IRB.CreatePtrToInt(
1112 IIRB.IRB.CreateGEP(AI.getAllocatedType(), NullPtr,
1113 {IIRB.IRB.getInt32(1)}),
1114 &Ty);
1115 }
1116 if (AI.isArrayAllocation())
1117 SizeValue = IIRB.IRB.CreateMul(
1118 SizeValue, IIRB.IRB.CreateZExtOrBitCast(AI.getArraySize(), &Ty));
1119 return SizeValue;
1120}
1121
1124 auto &AI = cast<AllocaInst>(V);
1125 const DataLayout &DL = AI.getDataLayout();
1126 auto *NewAI = IIRB.IRB.CreateAlloca(IIRB.IRB.getInt8Ty(),
1127 DL.getAllocaAddrSpace(), &NewV);
1128 NewAI->setAlignment(AI.getAlign());
1129 AI.replaceAllUsesWith(NewAI);
1130 IIRB.eraseLater(&AI);
1131 return NewAI;
1132}
1133
1136 return getCI(&Ty, cast<AllocaInst>(V).getAlign().value());
1137}
1138///}
1139
1141 ConfigTy *UserConfig) {
1142 if (UserConfig)
1143 Config = *UserConfig;
1144
1146 if (Config.has(PassPointer)) {
1147 IRTArgs.push_back(
1148 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1149 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1150 : IRTArg::NONE),
1152 }
1153 if (Config.has(PassPointerAS)) {
1154 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1155 "The address space of the accessed pointer.",
1157 }
1158 if (Config.has(PassBasePointerInfo)) {
1159 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1160 "The runtime provided base pointer info.",
1162 }
1163 if (Config.has(PassStoredValue)) {
1164 IRTArgs.push_back(
1165 IRTArg(getValueType(IIRB), "value", "The stored value.",
1168 : IRTArg::NONE),
1169 getValue));
1170 }
1171 if (Config.has(PassStoredValueSize)) {
1172 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1173 "The size of the stored value.", IRTArg::NONE,
1174 getValueSize));
1175 }
1176 if (Config.has(PassAlignment)) {
1177 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1178 "The known access alignment.", IRTArg::NONE,
1179 getAlignment));
1180 }
1181 if (Config.has(PassValueTypeId)) {
1182 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1183 "The type id of the stored value.", IRTArg::TYPEID,
1185 }
1186 if (Config.has(PassValueSubTypeId)) {
1187 IRTArgs.push_back(IRTArg(
1188 IIRB.Int32Ty, "value_sub_type_id",
1189 "The type id of the stored value (for arrays and vectors, or -1).",
1191 }
1192 if (Config.has(PassAtomicityOrdering)) {
1193 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1194 "The atomicity ordering of the store.",
1196 }
1197 if (Config.has(PassSyncScopeId)) {
1198 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1199 "The sync scope id of the store.", IRTArg::NONE,
1201 }
1202 if (Config.has(PassIsVolatile)) {
1203 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1204 "Flag indicating a volatile store.", IRTArg::NONE,
1205 isVolatile));
1206 }
1207
1208 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1209 IConf.addChoice(*this, IIRB.Ctx);
1210}
1211
1214 auto &SI = cast<StoreInst>(V);
1215 return SI.getPointerOperand();
1216}
1217
1220 auto &SI = cast<StoreInst>(V);
1221 SI.setOperand(SI.getPointerOperandIndex(), &NewV);
1222 return &SI;
1223}
1224
1227 auto &SI = cast<StoreInst>(V);
1228 return getCI(&Ty, SI.getPointerAddressSpace());
1229}
1230
1232 InstrumentationConfig &IConf,
1234 auto &SI = cast<StoreInst>(V);
1235 return IConf.getBasePointerInfo(*SI.getPointerOperand(), IIRB);
1236}
1237
1240 auto &SI = cast<StoreInst>(V);
1241 return SI.getValueOperand();
1242}
1243
1246 auto &SI = cast<StoreInst>(V);
1247 auto &DL = SI.getDataLayout();
1248 return getCI(&Ty, DL.getTypeStoreSize(SI.getValueOperand()->getType()));
1249}
1250
1253 auto &SI = cast<StoreInst>(V);
1254 return getCI(&Ty, SI.getAlign().value());
1255}
1256
1259 auto &SI = cast<StoreInst>(V);
1260 return getCI(&Ty, SI.getValueOperand()->getType()->getTypeID());
1261}
1262
1264 InstrumentationConfig &IConf,
1266 auto &SI = cast<StoreInst>(V);
1267 return getSubTypeID(*SI.getValueOperand()->getType(), Ty);
1268}
1269
1271 InstrumentationConfig &IConf,
1273 auto &SI = cast<StoreInst>(V);
1274 return getCI(&Ty, uint64_t(SI.getOrdering()));
1275}
1276
1279 auto &SI = cast<StoreInst>(V);
1280 return getCI(&Ty, uint64_t(SI.getSyncScopeID()));
1281}
1282
1285 auto &SI = cast<StoreInst>(V);
1286 return getCI(&Ty, SI.isVolatile());
1287}
1288
1290 ConfigTy *UserConfig) {
1292 if (UserConfig)
1293 Config = *UserConfig;
1294 if (Config.has(PassPointer)) {
1295 IRTArgs.push_back(
1296 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1297 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1298 : IRTArg::NONE),
1300 }
1301 if (Config.has(PassPointerAS)) {
1302 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1303 "The address space of the accessed pointer.",
1305 }
1306 if (Config.has(PassBasePointerInfo)) {
1307 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1308 "The runtime provided base pointer info.",
1310 }
1311 if (!IsPRE && Config.has(PassValue)) {
1312 IRTArgs.push_back(
1313 IRTArg(getValueType(IIRB), "value", "The loaded value.",
1314 Config.has(ReplaceValue)
1317 : IRTArg::NONE)
1318 : IRTArg::NONE,
1319 getValue, Config.has(ReplaceValue) ? replaceValue : nullptr));
1320 }
1321 if (Config.has(PassValueSize)) {
1322 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1323 "The size of the loaded value.", IRTArg::NONE,
1324 getValueSize));
1325 }
1326 if (Config.has(PassAlignment)) {
1327 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1328 "The known access alignment.", IRTArg::NONE,
1329 getAlignment));
1330 }
1331 if (Config.has(PassValueTypeId)) {
1332 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1333 "The type id of the loaded value.", IRTArg::TYPEID,
1335 }
1336 if (Config.has(PassValueSubTypeId)) {
1337 IRTArgs.push_back(IRTArg(
1338 IIRB.Int32Ty, "value_sub_type_id",
1339 "The sub type id of the loaded value (for arrays and vectors, or -1).",
1341 }
1342 if (Config.has(PassAtomicityOrdering)) {
1343 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1344 "The atomicity ordering of the load.",
1346 }
1347 if (Config.has(PassSyncScopeId)) {
1348 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1349 "The sync scope id of the load.", IRTArg::NONE,
1351 }
1352 if (Config.has(PassIsVolatile)) {
1353 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1354 "Flag indicating a volatile load.", IRTArg::NONE,
1355 isVolatile));
1356 }
1357
1358 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1359 IConf.addChoice(*this, IIRB.Ctx);
1360}
1361
1364 auto &LI = cast<LoadInst>(V);
1365 return LI.getPointerOperand();
1366}
1367
1370 auto &LI = cast<LoadInst>(V);
1371 LI.setOperand(LI.getPointerOperandIndex(), &NewV);
1372 return &LI;
1373}
1374
1377 auto &LI = cast<LoadInst>(V);
1378 return getCI(&Ty, LI.getPointerAddressSpace());
1379}
1380
1382 InstrumentationConfig &IConf,
1384 auto &LI = cast<LoadInst>(V);
1385 return IConf.getBasePointerInfo(*LI.getPointerOperand(), IIRB);
1386}
1387
1390 return &V;
1391}
1392
1395 auto &LI = cast<LoadInst>(V);
1396 auto &DL = LI.getDataLayout();
1397 return getCI(&Ty, DL.getTypeStoreSize(LI.getType()));
1398}
1399
1402 auto &LI = cast<LoadInst>(V);
1403 return getCI(&Ty, LI.getAlign().value());
1404}
1405
1408 auto &LI = cast<LoadInst>(V);
1409 return getCI(&Ty, LI.getType()->getTypeID());
1410}
1411
1413 InstrumentationConfig &IConf,
1415 auto &LI = cast<LoadInst>(V);
1416 return getSubTypeID(*LI.getType(), Ty);
1417}
1418
1420 InstrumentationConfig &IConf,
1422 auto &LI = cast<LoadInst>(V);
1423 return getCI(&Ty, uint64_t(LI.getOrdering()));
1424}
1425
1428 auto &LI = cast<LoadInst>(V);
1429 return getCI(&Ty, uint64_t(LI.getSyncScopeID()));
1430}
1431
1434 auto &LI = cast<LoadInst>(V);
1435 return getCI(&Ty, LI.isVolatile());
1436}
1437
1439 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1440 if (UserConfig)
1441 Config = *UserConfig;
1442 if (Config.has(PassPointer))
1443 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer",
1444 "The base pointer in question.",
1446 if (Config.has(PassPointerKind))
1447 IRTArgs.push_back(IRTArg(
1448 IIRB.Int32Ty, "base_pointer_kind",
1449 "The base pointer kind (argument, global, instruction, unknown).",
1451 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1452 IConf.addChoice(*this, IIRB.Ctx);
1453}
1454
1456 InstrumentationConfig &IConf,
1458 if (isa<Argument>(V))
1459 return getCI(&Ty, 0);
1460 if (isa<GlobalValue>(V))
1461 return getCI(&Ty, 1);
1462 if (isa<Instruction>(V))
1463 return getCI(&Ty, 2);
1464 return getCI(&Ty, 3);
1465}
1466
1468 ConfigTy *UserConfig) {
1469 if (UserConfig)
1470 Config = *UserConfig;
1471
1472 if (Config.has(PassName))
1473 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "module_name",
1474 "The module/translation unit name.",
1476 if (Config.has(PassTargetTriple))
1477 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "target_triple", "The target triple.",
1479
1480 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1481 IConf.addChoice(*this, IIRB.Ctx);
1482}
1485 // V is a constructor or destructor of the module we can place code in.
1486 auto &Fn = cast<Function>(V);
1487 return IConf.getGlobalString(Fn.getParent()->getName(), IIRB);
1488}
1490 InstrumentationConfig &IConf,
1492 // V is a constructor or destructor of the module we can place code in.
1493 auto &Fn = cast<Function>(V);
1494 return IConf.getGlobalString(Fn.getParent()->getTargetTriple().getTriple(),
1495 IIRB);
1496}
1497
1499 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1500 if (UserConfig)
1501 Config = *UserConfig;
1503 if (Config.has(PassAddress))
1504 IRTArgs.push_back(IRTArg(
1505 IIRB.PtrTy, "address",
1506 "The address of the global (replaceable for definitions).",
1509 if (Config.has(PassAS))
1510 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "address_space",
1511 "The address space of the global.", IRTArg::NONE,
1512 getAS));
1513 if (Config.has(PassDeclaredSize))
1514 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "declared_size",
1515 "The size of the declared type of the global.",
1517 if (Config.has(PassAlignment))
1518 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1519 "The allocation alignment.", IRTArg::NONE,
1520 getAlignment));
1521 if (Config.has(PassName))
1522 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The name of the global.",
1524 if (Config.has(PassInitialValue))
1525 IRTArgs.push_back(IRTArg(
1526 IIRB.Int64Ty, "initial_value", "The initial value of the global.",
1529 if (Config.has(PassIsConstant))
1530 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_constant",
1531 "Flag to indicate constant globals.", IRTArg::NONE,
1532 isConstant));
1533 if (Config.has(PassIsDefinition))
1534 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_definition",
1535 "Flag to indicate global definitions.",
1537 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1538 IConf.addChoice(*this, IIRB.Ctx);
1539}
1543 if (GV.getAddressSpace())
1544 return ConstantExpr::getAddrSpaceCast(&GV, IIRB.PtrTy);
1545 return &GV;
1546}
1548 InstrumentationConfig &IConf,
1551
1552 GlobalVariable *ShadowGV = nullptr;
1553 auto ShadowName = IConf.getRTName("shadow.", GV.getName());
1554 auto &DL = GV.getDataLayout();
1555 if (GV.isDeclaration()) {
1556 ShadowGV = new GlobalVariable(*GV.getParent(), GV.getType(), false,
1558 ShadowName, &GV, GV.getThreadLocalMode(),
1559 DL.getDefaultGlobalsAddressSpace());
1560 } else {
1561 ShadowGV = new GlobalVariable(
1562 *GV.getParent(), NewV.getType(), false, GV.getLinkage(),
1563 PoisonValue::get(NewV.getType()), ShadowName, &GV);
1564 IIRB.IRB.CreateStore(&NewV, ShadowGV);
1565 }
1566
1570 DenseMap<Value *, Instruction *> ConstToInstMap;
1572
1573 auto MakeInstForConst = [&](Use &U) {
1574 Instruction *&I = ConstToInstMap[U];
1575 if (I)
1576 return;
1577 if (U == &GV) {
1578 } else if (auto *CE = dyn_cast<ConstantExpr>(U)) {
1579 I = CE->getAsInstruction();
1580 }
1581 };
1582
1583 auto InsertConsts = [&](Instruction *UserI, Use &UserU) {
1585 auto *&Reload = ReloadMap[UserI->getFunction()];
1586 if (!Reload) {
1587 Reload = new LoadInst(
1588 GV.getType(), ShadowGV, GV.getName() + ".shadow_load",
1590 IIRB.NewInsts.insert({Reload, IIRB.Epoch});
1591 }
1592 Worklist.push_back({UserI, &UserU});
1593 while (!Worklist.empty()) {
1594 auto [I, U] = Worklist.pop_back_val();
1595 if (*U == &GV) {
1596 U->set(ReloadMap[I->getFunction()]);
1597 continue;
1598 }
1599 if (auto *CI = ConstToInstMap[*U]) {
1600 auto *CIClone = CI->clone();
1601 IIRB.NewInsts.insert({CIClone, IIRB.Epoch});
1602 if (auto *PHI = dyn_cast<PHINode>(I)) {
1603 auto *BB = PHI->getIncomingBlock(U->getOperandNo());
1604 CIClone->insertBefore(BB->getTerminator()->getIterator());
1605 } else {
1606 CIClone->insertBefore(I->getIterator());
1607 }
1608 U->set(CIClone);
1609 for (auto &CICUse : CIClone->operands()) {
1610 Worklist.push_back({CIClone, &CICUse});
1611 }
1612 }
1613 }
1614 };
1615
1616 SmallPtrSet<Use *, 8> Visited;
1617 while (!Worklist.empty()) {
1618 Use *U = Worklist.pop_back_val();
1619 if (!Done.insert(U).second)
1620 continue;
1621 MakeInstForConst(*U);
1622 auto *I = dyn_cast<Instruction>(U->getUser());
1623 if (!I) {
1624 append_range(Worklist, make_pointer_range(U->getUser()->uses()));
1625 continue;
1626 }
1627 if (IIRB.NewInsts.lookup(I) == IIRB.Epoch)
1628 continue;
1630 continue;
1631 if (auto *II = dyn_cast<IntrinsicInst>(I))
1632 if (II->getIntrinsicID() == Intrinsic::eh_typeid_for)
1633 continue;
1634 if (I->getParent())
1635 InsertConsts(I, *U);
1636 }
1637
1638 for (auto &It : ConstToInstMap)
1639 if (It.second)
1640 It.second->deleteValue();
1641
1642 return &V;
1643}
1647 return getCI(&Ty, GV.getAddressSpace());
1648}
1650 InstrumentationConfig &IConf,
1653 return getCI(&Ty, GV.getAlignment());
1654}
1656 InstrumentationConfig &IConf,
1659 auto &DL = GV.getDataLayout();
1660 return getCI(&Ty, DL.getTypeAllocSize(GV.getValueType()));
1661}
1663 InstrumentationConfig &IConf,
1666 return IConf.getGlobalString(GV.getName(), IIRB);
1667}
1678 return getCI(&Ty, GV.isConstant());
1679}
1681 InstrumentationConfig &IConf,
1684 return getCI(&Ty, !GV.isDeclaration());
1685}
1686
1687/// CastIO
1688/// {
1690 ConfigTy *UserConfig) {
1691 if (UserConfig)
1692 Config = *UserConfig;
1694 if (Config.has(PassInput))
1695 IRTArgs.push_back(
1696 IRTArg(IIRB.Int64Ty, "input", "Input value of the cast.",
1699 : IRTArg::NONE),
1700 getInput));
1701 if (Config.has(PassInputTypeId))
1702 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_type_id",
1703 "The type id of the input value.", IRTArg::TYPEID,
1705 if (Config.has(PassInputSubTypeId))
1706 IRTArgs.push_back(IRTArg(
1707 IIRB.Int32Ty, "input_sub_type_id",
1708 "The sub type id of the input value (for arrays and vectors, or -1).",
1710 if (Config.has(PassInputSize))
1711 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_size",
1712 "The size of the input value.", IRTArg::NONE,
1713 getInputSize));
1714 if (!IsPRE && Config.has(PassResult))
1715 IRTArgs.push_back(
1716 IRTArg(IIRB.Int64Ty, "result", "Result of the cast.",
1719 : IRTArg::NONE),
1720 getValue, Config.has(ReplaceResult) ? replaceValue : nullptr));
1721 if (Config.has(PassResultTypeId))
1722 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_type_id",
1723 "The type id of the result value.", IRTArg::TYPEID,
1725 if (Config.has(PassResultSubTypeId))
1726 IRTArgs.push_back(IRTArg(
1727 IIRB.Int32Ty, "result_sub_type_id",
1728 "The sub type id of the result value (for arrays and vectors, or -1).",
1730 if (Config.has(PassResultSize))
1731 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_size",
1732 "The size of the result value.", IRTArg::NONE,
1733 getResultSize));
1734 if (Config.has(PassOpcode))
1735 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode",
1736 "The opcode of the cast instruction.",
1738
1739 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1740 IConf.addChoice(*this, IIRB.Ctx);
1741}
1742
1745 auto &CI = cast<CastInst>(V);
1746 return CI.getOperand(0);
1747}
1748
1751 auto &CI = cast<CastInst>(V);
1752 return getCI(&Ty, CI.getSrcTy()->getTypeID());
1753}
1754
1756 InstrumentationConfig &IConf,
1758 auto &CI = cast<CastInst>(V);
1759 return getSubTypeID(*CI.getSrcTy(), Ty);
1760}
1761
1764 auto &CI = cast<CastInst>(V);
1765 auto &DL = CI.getDataLayout();
1766 return getCI(&Ty, DL.getTypeStoreSize(CI.getSrcTy()));
1767}
1768
1771 auto &CI = cast<CastInst>(V);
1772 return getCI(&Ty, CI.getDestTy()->getTypeID());
1773}
1774
1776 InstrumentationConfig &IConf,
1778 auto &CI = cast<CastInst>(V);
1779 return getSubTypeID(*CI.getDestTy(), Ty);
1780}
1781
1784 auto &CI = cast<CastInst>(V);
1785 auto &DL = CI.getDataLayout();
1786 return getCI(&Ty, DL.getTypeStoreSize(CI.getDestTy()));
1787}
1788///}
1789
1792 auto &I = cast<Instruction>(V);
1794
1795 switch (I.getOpcode()) {
1796 case Instruction::Add:
1797 case Instruction::Sub:
1798 case Instruction::Mul:
1799 case Instruction::Shl:
1800 if (I.hasNoSignedWrap())
1802 if (I.hasNoUnsignedWrap())
1804 break;
1805 case Instruction::FAdd:
1806 case Instruction::FSub:
1807 case Instruction::FMul:
1808 case Instruction::FDiv:
1809 case Instruction::FNeg:
1810 if (I.hasNoNaNs())
1812 if (I.hasNoInfs())
1814 if (I.hasNoSignedZeros())
1816 break;
1817 case Instruction::AShr:
1818 case Instruction::LShr:
1819 case Instruction::SDiv:
1820 case Instruction::UDiv:
1821 if (I.isExact())
1822 Flag |= NUMERIC_FLAG_IS_EXACT;
1823 break;
1824 }
1825
1826 if (auto *DI = dyn_cast<PossiblyDisjointInst>(&V))
1827 if (DI->isDisjoint())
1829
1830 return getCI(&Ty, Flag);
1831}
1832
1834 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1835 if (UserConfig)
1836 Config = UserConfig;
1838 const auto ValArgOpts =
1841 if (Config.has(PassTypeId))
1842 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "type_id",
1843 "The operation's type id.", IRTArg::TYPEID,
1844 getTypeId));
1845 if (Config.has(PassSubTypeId))
1846 IRTArgs.push_back(
1847 IRTArg(IIRB.Int32Ty, "sub_type_id",
1848 "The operation's sub type id (for arrays and vectors, or -1).",
1850 if (Config.has(PassSize))
1851 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "size", "The operation's type size.",
1853 if (Config.has(PassOpcode))
1854 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
1856 if (Config.has(PassLeft))
1857 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
1858 "The operation's left operand.", ValArgOpts,
1860 if (Config.has(PassRight))
1861 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
1862 "The operation's right operand. This value is "
1863 "poison for unary operations.",
1864 ValArgOpts, getRightOperand));
1865 if (!IsPRE && Config.has(PassResult))
1866 IRTArgs.push_back(
1867 IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
1868 IRTArg::REPLACABLE | ValArgOpts, getValue,
1869 Config.has(ReplaceResult) ? replaceValue : nullptr));
1870 if (Config.has(PassFlags))
1871 IRTArgs.push_back(
1872 IRTArg(IIRB.Int64Ty, "flags",
1873 "A bitmask value signaling which instruction flags are present.",
1875 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1876 IConf.addChoice(*this, IIRB.Ctx);
1877}
1878
1880 InstrumentationConfig &IConf,
1882 auto &I = cast<Instruction>(V);
1883 return getCI(&Ty, I.getOperand(0)->getType()->getTypeID());
1884}
1885
1887 InstrumentationConfig &IConf,
1889 auto &I = cast<Instruction>(V);
1890 auto &DL = I.getDataLayout();
1891 return getCI(&Ty, DL.getTypeStoreSize(I.getOperand(0)->getType()));
1892}
1893
1896 auto *CI = dyn_cast<CmpInst>(&V);
1897 return getCI(&Ty, CI->getPredicate());
1898}
1899
1902 auto &I = cast<Instruction>(V);
1904
1905 switch (I.getOpcode()) {
1906 case Instruction::ICmp:
1907 if (dyn_cast<ICmpInst>(&V)->hasSameSign())
1908 Flag |= COMPARE_FLAG_SAMESIGN;
1909 break;
1910 case Instruction::FCmp:
1911 if (I.hasNoNaNs())
1913 if (I.hasNoInfs())
1915 if (I.hasNoSignedZeros())
1917 break;
1918 }
1919
1920 return getCI(&Ty, Flag);
1921}
1922
1924 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1925 if (UserConfig)
1926 Config = UserConfig;
1928 const auto OperandArgOpts =
1931 if (Config.has(PassOpTypeId))
1932 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "operand_type_id",
1933 "The operand type id.", IRTArg::NONE,
1935 if (Config.has(PassOpSize))
1936 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "operand_size",
1937 "The operand type size.", IRTArg::NONE,
1939 if (Config.has(PassOpcode))
1940 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
1942 if (Config.has(PassPredicate))
1943 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "predicate",
1944 "The comparison predicate ID.", IRTArg::NONE,
1945 getPredicate));
1946 if (Config.has(PassLeft))
1947 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
1948 "The comparison's left operand.", OperandArgOpts,
1950 if (Config.has(PassRight))
1951 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
1952 "The comparison's right operand.", OperandArgOpts,
1954 if (!IsPRE && Config.has(PassResultSize))
1955 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_type_id",
1956 "The result value's type ID.", IRTArg::NONE,
1957 getTypeId));
1958 if (!IsPRE && Config.has(PassResultSize))
1959 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_size",
1960 "Size of the result value.", IRTArg::NONE,
1961 getTypeSize));
1962 if (!IsPRE && Config.has(PassResult))
1963 IRTArgs.push_back(
1964 IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
1967 : IRTArg::NONE),
1968 getValue, Config.has(ReplaceResult) ? replaceValue : nullptr));
1969 if (Config.has(PassFlags))
1970 IRTArgs.push_back(
1971 IRTArg(IIRB.Int64Ty, "flags",
1972 "A bitmask value signaling which instruction flags are present.",
1974 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1975 IConf.addChoice(*this, IIRB.Ctx);
1976}
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
static MaybeAlign getAlign(Value *Ptr)
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
@ COMPARE_FLAG_HAS_NO_NANS
@ COMPARE_FLAG_HAS_NO_INFS
@ COMPARE_FLAG_HAS_NO_SIGNED_ZEROS
@ NUMERIC_FLAG_NO_SIGNED_WRAP
@ NUMERIC_FLAG_NO_UNSIGNED_WRAP
@ NUMERIC_FLAG_HAS_NO_SIGNED_ZEROS
@ NUMERIC_FLAG_HAS_NO_INFS
@ NUMERIC_FLAG_HAS_NO_NANS
@ NUMERIC_FLAG_IS_DISJOINT
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.
#define LLVM_DEBUG(...)
Definition Debug.h:119
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:783
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:357
iterator_range< arg_iterator > args()
Definition Function.h:866
arg_iterator arg_begin()
Definition Function.h:842
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:353
size_t arg_size() const
Definition Function.h:875
Argument * getArg(unsigned i) const
Definition Function.h:860
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:723
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:346
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:143
@ 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.
LLVM_ABI 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:1554
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:477
const std::string & getTriple() const
Definition Triple.h:492
bool isAMDGPU() const
Definition Triple.h:905
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 isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:288
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:319
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
TypeID getTypeID() const
Return the type id for the type.
Definition Type.h:138
Type * getContainedType(unsigned i) const
This method is used to implement the type iterator (defined at the end of the file).
Definition Type.h:397
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:561
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:319
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
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
initializer< Ty > init(const Ty &Val)
LLVM_ABI void writeConfigToJSON(InstrumentationConfig &IConf, StringRef OutputFile, LLVMContext &Ctx)
Write the configuration in /p IConf to the file with path OutputFile.
LLVM_ABI 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.
LLVM_ABI bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile, LLVMContext &Ctx, vfs::FileSystem &FS)
Read the configuration from the file with path InputFile into /p IConf.
LLVM_ABI 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:573
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
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:2554
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:2208
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
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 const Value * getUnderlyingObjectAggressive(const Value *V)
Like getUnderlyingObject(), but will try harder to find a single underlying object.
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)
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
}
BaseConfigTy< ConfigKind > ConfigTy
static LLVM_ABI Value * getSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * setSize(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI 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 LLVM_ABI 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...
static LLVM_ABI Value * getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getRightOperand(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getSubTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getTypeSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getLeftOperand(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getPointerKind(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * setValueNoop(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
This is necessary to produce a return value that can be used by other IOs.
BaseConfigTy< ConfigKind > ConfigTy
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
CastIO {.
static LLVM_ABI Value * getResultTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getInputSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getResultSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getResultSubTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getInput(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getInputSubTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static LLVM_ABI Value * getInputTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getFlags(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getOperandSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getOperandTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static LLVM_ABI Value * getPredicate(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
llvm::instrumentor::FunctionIO::ConfigTy Config
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
LLVM_ABI Value * setArguments(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getFunctionAddress(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * isMainFunction(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
LLVM_ABI Value * getArguments(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
LLVM_ABI Value * getNumArguments(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getFunctionName(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
FunctionIO {.
static LLVM_ABI Value * setAddress(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
static LLVM_ABI Value * getAS(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getInitialValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * isDefinition(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getDeclaredSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getSymbolName(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getAddress(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static LLVM_ABI Value * isConstant(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
bool isReplacable(IRTArg &IRTA) const
Return whether the IRTA argument can be replaced.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI 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)
DenseMap< Value *, Value * > UnderlyingObjsMap
Map to remember underlying objects for pointers.
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...
DenseMap< std::pair< Value *, Function * >, Value * > BasePointerInfoMap
Map to remember base pointer info for values in a specific function.
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.
Value * getBasePointerInfo(Value &V, InstrumentorIRBuilderTy &IIRB)
Return the base pointer info for V.
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 LLVM_ABI Value * getIdPre(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Get the opportunity identifier for the pre and post positions.
static LLVM_ABI 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 LLVM_ABI Value * getIdPost(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI 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 LLVM_ABI Value * getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getAtomicityOrdering(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
virtual Type * getValueType(InstrumentorIRBuilderTy &IIRB) const
}
static LLVM_ABI Value * getValueSubTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI 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 LLVM_ABI Value * isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getBasePointerInfo(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static LLVM_ABI Value * getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
}
static LLVM_ABI Value * getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
Initialize the load opportunity using the instrumentation config IConf and the user config UserConfig...
static LLVM_ABI Value * getModuleName(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getTargetTriple(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
BaseConfigTy< ConfigKind > ConfigTy
static LLVM_ABI Value * getFlags(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
}
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static LLVM_ABI 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 LLVM_ABI Value * getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
virtual Type * getValueType(InstrumentorIRBuilderTy &IIRB) const
}
static LLVM_ABI Value * getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getValueSubTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
Initialize the store opportunity using the instrumentation config IConf and the user config UserConfi...
static LLVM_ABI Value * getBasePointerInfo(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static LLVM_ABI Value * getAtomicityOrdering(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
LLVM_ABI void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
UnreachableIO {.
BaseConfigTy< ConfigKind > ConfigTy