LLVM 24.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/Dominators.h"
34#include "llvm/IR/Function.h"
35#include "llvm/IR/IRBuilder.h"
36#include "llvm/IR/InstrTypes.h"
37#include "llvm/IR/Instruction.h"
40#include "llvm/IR/Intrinsics.h"
41#include "llvm/IR/LLVMContext.h"
42#include "llvm/IR/Metadata.h"
43#include "llvm/IR/Module.h"
44#include "llvm/IR/PassManager.h"
45#include "llvm/IR/Verifier.h"
47#include "llvm/Linker/Linker.h"
50#include "llvm/Support/Regex.h"
56
57#include <cassert>
58#include <cstdint>
59#include <functional>
60#include <iterator>
61#include <memory>
62#include <string>
63#include <type_traits>
64
65using namespace llvm;
66using namespace llvm::instrumentor;
67
68#define DEBUG_TYPE "instrumentor"
69
70namespace {
71
72/// The user option to specify an output JSON file to write the configuration.
73static cl::opt<std::string> OutputConfigFile(
74 "instrumentor-write-config-file",
76 "Write the instrumentor configuration into the specified JSON file"),
77 cl::init(""));
78
79/// The user option to specify input JSON files to read the configuration from.
81 ConfigFiles("instrumentor-read-config-files",
82 cl::desc("Read the instrumentor configuration from the "
83 "specified JSON files (comma separated)"),
85
86/// The user option to specify an input file to read the configuration file
87/// paths from.
88static cl::opt<std::string> ConfigPathsFile(
89 "instrumentor-read-config-paths-file",
90 cl::desc("Read the instrumentor configuration file "
91 "paths from the specified file (newline separated)"),
92 cl::init(""));
93
94/// Set the debug location, if not set, after changing the insertion point of
95/// the IR builder \p IRB.
96template <typename IRBuilderTy> void ensureDbgLoc(IRBuilderTy &IRB) {
97 if (IRB.getCurrentDebugLocation())
98 return;
99 auto *BB = IRB.GetInsertBlock();
100 if (auto *SP = BB->getParent()->getSubprogram())
101 IRB.SetCurrentDebugLocation(DILocation::get(BB->getContext(), 0, 0, SP));
102}
103
104/// Attempt to cast \p V to type \p Ty using only bit-preserving casts.
105/// This ensures that floating-point values are converted via bitcast (not
106/// fptosi/fptoui) to preserve their exact bit representation.
107template <typename IRBTy>
108Value *tryToCast(IRBTy &IRB, Value *V, Type *Ty, const DataLayout &DL,
109 bool AllowTruncate = false) {
110 if (!V)
111 return Constant::getAllOnesValue(Ty);
112 Type *VTy = V->getType();
113 if (VTy == Ty)
114 return V;
115 if (VTy->isAggregateType() || VTy->isVectorTy())
116 return V;
117 if (VTy->isPointerTy() && Ty->isPointerTy())
118 return IRB.CreatePointerBitCastOrAddrSpaceCast(V, Ty);
119 TypeSize RequestedSize = DL.getTypeSizeInBits(Ty);
120 TypeSize ValueSize = DL.getTypeSizeInBits(VTy);
121 bool ShouldTruncate = RequestedSize < ValueSize;
122 if (ShouldTruncate && !AllowTruncate)
123 return V;
124 if (ShouldTruncate && AllowTruncate) {
125 // First convert to integer of the same size if needed.
126 Value *IntV = V;
127 if (VTy->isFloatingPointTy())
128 IntV = IRB.CreateBitCast(V, IRB.getIntNTy(ValueSize));
129 return tryToCast(IRB,
130 IRB.CreateIntCast(IntV, IRB.getIntNTy(RequestedSize),
131 /*IsSigned=*/false),
132 Ty, DL, AllowTruncate);
133 }
134 if (VTy->isIntegerTy() && Ty->isIntegerTy())
135 return IRB.CreateIntCast(V, Ty, /*IsSigned=*/false);
136 // Use bit-preserving casts for floating-point values: convert float to int
137 // of the same size via bitcast, then extend/truncate the integer if needed.
138 if (VTy->isFloatingPointTy() && Ty->isIntOrPtrTy()) {
139 return tryToCast(IRB, IRB.CreateBitCast(V, IRB.getIntNTy(ValueSize)), Ty,
140 DL, AllowTruncate);
141 }
142 // When converting int to float, never use sitofp/uitofp as they perform value
143 // conversion, not bit-preserving cast.
144 if (VTy->isIntegerTy() && Ty->isFloatingPointTy()) {
145 if (ValueSize == RequestedSize)
146 return IRB.CreateBitCast(V, Ty);
147 return tryToCast(
148 IRB,
149 IRB.CreateIntCast(V, IRB.getIntNTy(RequestedSize), /*IsSigned=*/false),
150 Ty, DL, AllowTruncate);
151 }
152 return IRB.CreateBitOrPointerCast(V, Ty);
153}
154
155/// Get a constant integer/boolean of type \p IT and value \p Val.
156template <typename Ty>
157Constant *getCI(Type *IT, Ty Val, bool IsSigned = false) {
158 return ConstantInt::get(IT, Val, IsSigned);
159}
160
161Constant *getSubTypeID(Type &OpTy, Type &ReqTy) {
162 switch (OpTy.getTypeID()) {
163 case Type::TypeID::ArrayTyID:
164 case Type::TypeID::FixedVectorTyID:
165 case Type::TypeID::ScalableVectorTyID:
166 return getCI(&ReqTy, OpTy.getContainedType(0)->getTypeID());
167 default:
168 break;
169 }
170
171 return getCI(&ReqTy, -1, /*IsSigned=*/true);
172}
173
174/// The core of the instrumentor pass, which instruments the module as the
175/// instrumentation configuration mandates.
176class InstrumentorImpl final {
177public:
178 /// Construct an instrumentor implementation using the configuration \p IConf.
179 InstrumentorImpl(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
180 Module &M)
181 : IConf(IConf), M(M), IIRB(IIRB) {}
182
183 /// Instrument the module, public entry point.
184 bool instrument();
185
186 // Reset the state to allow reuse of the instrumentor with a different
187 // configuration.
188 void clear() {
189 InstChoicesPRE.clear();
190 InstChoicesPOST.clear();
191 ParsedFunctionRegex = Regex();
192 }
193
194private:
195 /// Link the runtime bitcodes into the module. Returns true if the module
196 /// was changed.
197 bool linkRuntime();
198
199 /// Indicate if the module should be instrumented based on the target.
200 bool shouldInstrumentTarget();
201
202 /// Indicate if the function \p Fn should be instrumented.
203 bool shouldInstrumentFunction(Function &Fn);
204 bool shouldInstrumentGlobalVariable(GlobalVariable &GV);
205
206 /// Instrument instruction \p I if needed, and use the argument caches in \p
207 /// ICaches.
208 bool instrumentInstruction(Instruction &I, InstrumentationCaches &ICaches);
209
210 /// Instrument function \p Fn.
211 bool instrumentFunction(Function &Fn);
212 bool instrumentModule();
213
214 /// The instrumentation opportunities for instructions indexed by
215 /// their opcode.
217 InstChoicesPOST;
218
219 /// The instrumentor configuration.
221
222 /// The function regex filter, if any.
223 Regex ParsedFunctionRegex;
224
225 /// The underlying module.
226 Module &M;
227
228protected:
229 /// A special IR builder that keeps track of the inserted instructions.
231};
232
233} // end anonymous namespace
234
236 if (!Str.empty()) {
237 Regex RX(Str);
238 std::string ErrMsg;
239 if (!RX.isValid(ErrMsg)) {
241 Twine("failed to parse ") + Name + " regex: " + ErrMsg, DS_Error));
242 return Regex();
243 }
244 return RX;
245 }
246 return Regex();
247}
248
249bool InstrumentorImpl::linkRuntime() {
250 ArrayRef<StringRef> RuntimeBitcodes = IConf.RuntimeBitcodes->getStringList();
251 if (RuntimeBitcodes.empty())
252 return false;
253
254 bool Changed = false;
255
256 for (StringRef RuntimeBitcode : RuntimeBitcodes) {
257 if (RuntimeBitcode.empty())
258 continue;
259
260 SMDiagnostic Err;
261 auto RTM = parseIRFile(RuntimeBitcode, Err, M.getContext());
262 if (!RTM) {
263 IIRB.Ctx.diagnose(DiagnosticInfoInstrumentation(
264 Twine("Failed to parse runtime bitcode file '") + RuntimeBitcode +
265 Twine("': ") + Err.getMessage(),
266 DS_Error));
267 return Changed;
268 }
269
270 if (Linker::linkModules(M, std::move(RTM))) {
271 IIRB.Ctx.diagnose(DiagnosticInfoInstrumentation(
272 Twine("Failed to link in runtime bitcode file '") + RuntimeBitcode +
273 "'",
274 DS_Error));
275 return Changed;
276 }
277 Changed = true;
278 }
279
280 if (!IConf.InlineRuntimeEagerly->getBool())
281 return Changed;
282
283 for (auto [I, _] : IIRB.NewInsts) {
284 auto *CI = dyn_cast<CallInst>(I);
285 if (!CI || isa<IntrinsicInst>(CI))
286 continue;
287
288 InlineFunctionInfo IFI;
289 auto InlineResult = InlineFunction(*CI, IFI);
290 if (!InlineResult.isSuccess()) {
291 std::string WarnMsg;
292 raw_string_ostream SS(WarnMsg);
293 SS << "Inlining of runtime call failed: "
294 << CI->getCalledFunction()->getName() << "\n";
295 SS << "Reason: " << InlineResult.getFailureReason() << "\n";
296 SS << "Signatures: " << *CI->getFunctionType() << " vs "
297 << *CI->getCalledFunction()->getFunctionType() << "\n";
298 IIRB.Ctx.diagnose(DiagnosticInfoInstrumentation(WarnMsg, DS_Warning));
299 }
300 }
301
302 // Promote any eligible instrumentor-associated allocas to registers.
303 for (auto It : IIRB.AllocaMap) {
304 auto *Fn = It.first.first;
305 DominatorTree DT(*Fn);
306 auto &Allocas = *It.second;
307 erase_if(Allocas,
308 [](const AllocaInst *AI) { return !isAllocaPromotable(AI); });
309 PromoteMemToReg(Allocas, DT);
310 delete It.second;
311 }
312 IIRB.AllocaMap.clear();
313 return Changed;
314}
315
316bool InstrumentorImpl::shouldInstrumentTarget() {
317 const Triple &T = M.getTargetTriple();
318 const bool IsGPU = T.isAMDGPU() || T.isNVPTX();
319
320 bool RegexMatches = true;
321 Regex RX = createRegex(IConf.TargetRegex->getString(), "target", IIRB.Ctx);
322 if (RX.isValid())
323 RegexMatches = RX.match(T.str());
324
325 // Only instrument the module if the target has to be instrumented.
326 return ((IsGPU && IConf.GPUEnabled->getBool()) ||
327 (!IsGPU && IConf.HostEnabled->getBool())) &&
328 RegexMatches;
329}
330
331bool InstrumentorImpl::shouldInstrumentFunction(Function &Fn) {
332 if (Fn.isDeclaration())
333 return false;
334 if (Fn.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
335 return false;
336 bool RegexMatches = true;
337 if (ParsedFunctionRegex.isValid())
338 RegexMatches = ParsedFunctionRegex.match(Fn.getName());
339 return (RegexMatches && !Fn.getName().starts_with(IConf.getRTName())) ||
340 Fn.hasFnAttribute("instrument");
341}
342
343bool InstrumentorImpl::shouldInstrumentGlobalVariable(GlobalVariable &GV) {
344 return !GV.getName().starts_with("llvm.") &&
345 !GV.getName().starts_with(IConf.getRTName());
346}
347
348bool InstrumentorImpl::instrumentInstruction(Instruction &I,
349 InstrumentationCaches &ICaches) {
350 bool Changed = false;
351
352 // Skip instrumentation instructions.
353 if (IIRB.NewInsts.contains(&I))
354 return Changed;
355
356 // Count epochs eagerly.
357 ++IIRB.Epoch;
358
359 Value *IPtr = &I;
360 if (auto *IO = InstChoicesPRE.lookup(I.getOpcode())) {
361 IIRB.IRB.SetInsertPoint(&I);
362 ensureDbgLoc(IIRB.IRB);
363 IO->instrument(IPtr, Changed, IConf, IIRB, ICaches);
364 }
365
366 if (auto *IO = InstChoicesPOST.lookup(I.getOpcode())) {
367 IIRB.IRB.SetInsertPoint(I.getNextNode());
368 ensureDbgLoc(IIRB.IRB);
369 IO->instrument(IPtr, Changed, IConf, IIRB, ICaches);
370 }
371 IIRB.returnAllocas();
372
373 return Changed;
374}
375
376bool InstrumentorImpl::instrumentFunction(Function &Fn) {
377 bool Changed = false;
378 if (!shouldInstrumentFunction(Fn))
379 return Changed;
380
381 InstrumentationCaches ICaches;
382 SmallVector<Instruction *> FinalTIs;
383 ReversePostOrderTraversal<Function *> RPOT(&Fn);
384 for (auto &It : RPOT) {
385 for (auto &I : *It)
386 Changed |= instrumentInstruction(I, ICaches);
387
388 auto *TI = It->getTerminator();
389 if (!TI->getNumSuccessors())
390 FinalTIs.push_back(TI);
391 }
392
393 Value *FPtr = &Fn;
394 for (auto &[Name, IO] :
396 if (!IO->Enabled)
397 continue;
398 // Count epochs eagerly.
399 ++IIRB.Epoch;
400
401 IIRB.IRB.SetInsertPoint(
402 cast<Function>(FPtr)->getEntryBlock().getFirstNonPHIOrAlloca());
403 ensureDbgLoc(IIRB.IRB);
404 IO->instrument(FPtr, Changed, IConf, IIRB, ICaches);
405 IIRB.returnAllocas();
406 }
407
408 for (auto &[Name, IO] :
410 if (!IO->Enabled)
411 continue;
412 // Count epochs eagerly.
413 ++IIRB.Epoch;
414
415 for (Instruction *FinalTI : FinalTIs) {
416 IIRB.IRB.SetInsertPoint(FinalTI);
417 ensureDbgLoc(IIRB.IRB);
418 IO->instrument(FPtr, Changed, IConf, IIRB, ICaches);
419 IIRB.returnAllocas();
420 }
421 }
422 return Changed;
423}
424
425bool InstrumentorImpl::instrumentModule() {
427 Globals.reserve(M.global_size());
428 for (GlobalVariable &GV : M.globals()) {
429 // llvm.metadata contains globals such as llvm.used.
430 if (GV.getSection() == "llvm.metadata" ||
431 GV.getName() == "llvm.global_dtors" ||
432 GV.getName() == "llvm.global_ctors")
433 continue;
434 Globals.push_back(&GV);
435 }
436
437 auto CreateYtor = [&](bool Ctor) {
438 Function *YtorFn = Function::Create(
439 FunctionType::get(IIRB.VoidTy, false), GlobalValue::PrivateLinkage,
440 IConf.getRTName(Ctor ? "ctor" : "dtor", ""), M);
441
442 auto *EntryBB = BasicBlock::Create(IIRB.Ctx, "entry", YtorFn);
443 IIRB.IRB.SetInsertPoint(EntryBB->begin());
444 ensureDbgLoc(IIRB.IRB);
445 IIRB.IRB.CreateRetVoid();
446
447 if (Ctor)
448 appendToGlobalCtors(M, YtorFn, 1000);
449 else
450 appendToGlobalDtors(M, YtorFn, 1000);
451 return YtorFn;
452 };
453
454 InstrumentationCaches ICaches;
455
456 Function *CtorFn = nullptr, *DtorFn = nullptr;
457 bool Changed = false;
460 bool IsPRE = InstrumentationLocation::isPRE(Loc);
461 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
462 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
463 auto *IO = ChoiceIt.second;
464 if (!IO->Enabled)
465 continue;
466 if (!YtorFn) {
467 YtorFn = CreateYtor(IsPRE);
468 Changed = true;
469 }
470 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
471 ensureDbgLoc(IIRB.IRB);
472 Value *YtorPtr = YtorFn;
473
474 // Count epochs eagerly.
475 ++IIRB.Epoch;
476
477 IO->instrument(YtorPtr, Changed, IConf, IIRB, ICaches);
478 IIRB.returnAllocas();
479 }
480 }
481
484 bool IsPRE = InstrumentationLocation::isPRE(Loc);
485 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
486 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
487 auto *IO = ChoiceIt.second;
488 if (!IO->Enabled)
489 continue;
490 if (!YtorFn) {
491 YtorFn = CreateYtor(IsPRE);
492 Changed = true;
493 }
494 for (GlobalVariable *GV : Globals) {
495 if (!shouldInstrumentGlobalVariable(*GV))
496 continue;
497 if (IsPRE)
498 IIRB.IRB.SetInsertPoint(YtorFn->getEntryBlock().getTerminator());
499 else
500 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
501 ensureDbgLoc(IIRB.IRB);
502 Value *GVPtr = GV;
503
504 // Count epochs eagerly.
505 ++IIRB.Epoch;
506
507 IO->instrument(GVPtr, Changed, IConf, IIRB, ICaches);
508 IIRB.returnAllocas();
509 }
510 }
511 }
512
513 return Changed;
514}
515
516bool InstrumentorImpl::instrument() {
517 bool Changed = false;
518 if (!shouldInstrumentTarget())
519 return Changed;
520
521 StringRef FunctionRegexStr = IConf.FunctionRegex->getString();
522 ParsedFunctionRegex = createRegex(FunctionRegexStr, "function", IIRB.Ctx);
523
524 // Helper to register an IO for all its opcodes.
525 auto RegisterForAllOpcodes = [](auto &InstChoices,
526 InstrumentationOpportunity *IO) {
527 ArrayRef<unsigned> Opcodes = IO->getAllOpcodes();
528 // Register for all opcodes.
529 for (unsigned Opcode : Opcodes)
530 InstChoices[Opcode] = IO;
531 };
532
533 for (auto &[Name, IO] :
535 if (IO->Enabled)
536 RegisterForAllOpcodes(InstChoicesPRE, IO);
537 for (auto &[Name, IO] :
539 if (IO->Enabled)
540 RegisterForAllOpcodes(InstChoicesPOST, IO);
541 Changed |= instrumentModule();
542
543 for (Function &Fn : M)
544 Changed |= instrumentFunction(Fn);
545
546 Changed |= linkRuntime();
547
548 return Changed;
549}
550
552 InstrumentationConfig *IC,
553 InstrumentorIRBuilderTy *IIRB)
554 : FS(FS), UserIConf(IC), UserIIRB(IIRB) {
555 if (!FS)
556 this->FS = vfs::getRealFileSystem();
557}
558
559PreservedAnalyses InstrumentorPass::run(Module &M, InstrumentationConfig &IConf,
561 bool ReadConfig) {
562 bool Changed = false;
563 InstrumentorImpl Impl(IConf, IIRB, M);
564
565 // If this is a configuration driven run, iterate over all configurations
566 // provided by the user, if not, use the config as is and run the instrumentor
567 // once.
568 if (ReadConfig)
569 readConfigPathsFile(ConfigPathsFile, ConfigFiles, IIRB.Ctx, *FS);
570
571 bool MultipleConfigs = ConfigFiles.size() > 1;
572 unsigned Idx = 0;
573 do {
574 std::string ConfigFile =
575 ReadConfig && !ConfigFiles.empty() ? ConfigFiles[Idx] : "";
576
577 // Initialize the config to the base state but keep the caches around.
578 Impl.clear();
579 IConf.init(IIRB);
580
581 if (!readConfigFromJSON(IConf, ConfigFile, IIRB.Ctx, *FS))
582 continue;
583
584 writeConfigToJSON(IConf,
585 MultipleConfigs
586 ? OutputConfigFile + "." + std::to_string(Idx)
587 : OutputConfigFile,
588 IIRB.Ctx);
589
590 printRuntimeStub(IConf, IConf.RuntimeStubsFile->getString(), IIRB.Ctx);
591
592 Changed |= Impl.instrument();
593 } while (++Idx < ConfigFiles.size());
594
595 if (!Changed)
596 return PreservedAnalyses::all();
598}
599
601 // Only create them if the user did not provide them.
602 std::unique_ptr<InstrumentationConfig> IConfInt(
603 !UserIConf ? new InstrumentationConfig() : nullptr);
604 std::unique_ptr<InstrumentorIRBuilderTy> IIRBInt(
605 !UserIIRB ? new InstrumentorIRBuilderTy(M) : nullptr);
606
607 auto *IConf = IConfInt ? IConfInt.get() : UserIConf;
608 auto *IIRB = IIRBInt ? IIRBInt.get() : UserIIRB;
609
610 auto PA = run(M, *IConf, *IIRB, !UserIConf);
611
612 assert(!verifyModule(M, &errs()));
613 return PA;
614}
615
616std::unique_ptr<BaseConfigurationOption>
619 bool DefaultValue) {
620 auto BCO =
621 std::make_unique<BaseConfigurationOption>(Name, Description, BOOLEAN);
622 BCO->setBool(DefaultValue);
623 IConf.addBaseChoice(BCO.get());
624 return BCO;
625}
626
627std::unique_ptr<BaseConfigurationOption>
631 StringRef DefaultValue) {
632 auto BCO =
633 std::make_unique<BaseConfigurationOption>(Name, Description, STRING);
634 BCO->setString(DefaultValue);
635 IConf.addBaseChoice(BCO.get());
636 return BCO;
637}
638
639std::unique_ptr<BaseConfigurationOption>
642 ArrayRef<StringRef> DefaultValue) {
643 auto BCO =
644 std::make_unique<BaseConfigurationOption>(Name, Description, STRING_LIST);
645 BCO->setStringList(DefaultValue);
646 IConf.addBaseChoice(BCO.get());
647 return BCO;
648}
649
651 /// List of all instrumentation opportunities.
652 BasePointerIO::populate(*this, IIRB);
653 ModuleIO::populate(*this, IIRB);
654 GlobalVarIO::populate(*this, IIRB);
655 FunctionIO::populate(*this, IIRB);
656 AllocaIO::populate(*this, IIRB);
657 UnreachableIO::populate(*this, IIRB);
658 LoadIO::populate(*this, IIRB);
659 StoreIO::populate(*this, IIRB);
660 CastIO::populate(*this, IIRB);
661 NumericIO::populate(*this, IIRB);
662 CompareIO::populate(*this, IIRB);
663}
664
666 LLVMContext &Ctx) {
667 auto *&ICPtr = IChoices[IO.getLocationKind()][IO.getName()];
668 if (ICPtr) {
670 Twine("registered two instrumentation opportunities for the same "
671 "location (") +
672 ICPtr->getName() + Twine(" vs ") + IO.getName() + Twine(")"),
673 DS_Warning));
674 }
675 ICPtr = &IO;
676}
677
678Value *
681 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
682
683 Value *Obj;
684 {
685 Value *&UnderlyingObj = UnderlyingObjsMap[&V];
686 if (!UnderlyingObj)
687 UnderlyingObj = const_cast<Value *>(getUnderlyingObjectAggressive(&V));
688 Obj = UnderlyingObj;
689 }
690
691 Value *&BPI = BasePointerInfoMap[{Obj, Fn}];
692 if (BPI)
693 return BPI;
694
695 auto *BPIO =
697 if (!BPIO || !BPIO->Enabled) {
699 "Base pointer info disabled but required, passing nullptr.",
700 DS_Warning));
701 return BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
702 }
703
705 if (auto *BasePtrI = dyn_cast<Instruction>(Obj)) {
706 std::optional<BasicBlock::iterator> IP =
707 BasePtrI->getInsertionPointAfterDef();
708 if (IP) {
709 IIRB.IRB.SetInsertPoint(*IP);
710 } else {
712 "Base pointer info could not be placed, passing nullptr.",
713 DS_Warning));
714 return BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
715 }
716 } else if (isa<Constant>(Obj) || isa<Argument>(Obj)) {
717 IIRB.IRB.SetInsertPointPastAllocas(IIRB.IRB.GetInsertBlock()->getParent());
718 } else {
719 LLVM_DEBUG(Obj->dump());
720 llvm_unreachable("Unexpected base pointer!");
721 }
722 ensureDbgLoc(IIRB.IRB);
723
724 // Use fresh caches for safety, as this function may be called from
725 // another instrumentation opportunity.
726 bool Changed;
727 InstrumentationCaches ICaches;
728 BPI = BPIO->instrument(Obj, Changed, *this, IIRB, ICaches);
729 IIRB.returnAllocas();
730 if (!BPI)
731 BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
732 return BPI;
733}
734
738 return getCI(&Ty, getIdFromEpoch(IIRB.Epoch));
739}
740
744 return getCI(&Ty, -getIdFromEpoch(IIRB.Epoch), /*IsSigned=*/true);
745}
746
749 if (V.getType()->isVoidTy())
750 return Ty.isVoidTy() ? &V : Constant::getNullValue(&Ty);
751 return tryToCast(IIRB.IRB, &V, &Ty, IIRB.IRB.getDataLayout());
752}
753
757 if (V.getType()->isVoidTy())
758 return &V;
759
760 auto *NewVCasted = &NewV;
761 if (auto *I = dyn_cast<Instruction>(&NewV)) {
763 IIRB.IRB.SetInsertPoint(I->getNextNode());
764 ensureDbgLoc(IIRB.IRB);
765 NewVCasted = tryToCast(IIRB.IRB, &NewV, V.getType(), IIRB.DL,
766 /*AllowTruncate=*/true);
767 }
768 V.replaceUsesWithIf(NewVCasted, [&](Use &U) {
769 if (IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) == IIRB.Epoch)
770 return false;
771 return !isa<LifetimeIntrinsic>(U.getUser()) && !U.getUser()->isDroppable();
772 });
773
774 return &V;
775}
776
778 Type *RetTy)
779 : IO(IO), RetTy(RetTy) {
780 for (auto &It : IO.IRTArgs) {
781 if (!It.Enabled)
782 continue;
783 NumReplaceableArgs += bool(It.Flags & IRTArg::REPLACABLE);
784 MightRequireIndirection |= It.Flags & IRTArg::POTENTIALLY_INDIRECT;
785 }
788}
789
792 const DataLayout &DL, bool ForceIndirection) {
793 assert(((ForceIndirection && MightRequireIndirection) ||
794 (!ForceIndirection && !RequiresIndirection)) &&
795 "Wrong indirection setting!");
796
797 SmallVector<Type *> ParamTypes;
798 for (auto &It : IO.IRTArgs) {
799 if (!It.Enabled)
800 continue;
801 if (!ForceIndirection || !isPotentiallyIndirect(It)) {
802 ParamTypes.push_back(It.Ty);
803 if (!RetTy && NumReplaceableArgs == 1 && (It.Flags & IRTArg::REPLACABLE))
804 RetTy = It.Ty;
805 continue;
806 }
807
808 // The indirection pointer and the size of the value.
809 ParamTypes.push_back(IIRB.PtrTy);
810 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE))
811 ParamTypes.push_back(IIRB.Int32Ty);
812 }
813 if (!RetTy)
814 RetTy = IIRB.VoidTy;
815
816 return FunctionType::get(RetTy, ParamTypes, /*isVarArg=*/false);
817}
818
822 const DataLayout &DL,
823 InstrumentationCaches &ICaches) {
824 SmallVector<Value *> CallParams;
825
827 auto IP = IIRB.IRB.GetInsertPoint();
828
829 bool ForceIndirection = RequiresIndirection;
830 for (auto &It : IO.IRTArgs) {
831 if (!It.Enabled)
832 continue;
833 auto *&Param = ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
834 if (!Param || It.NoCache)
835 // Avoid passing the caches to the getter.
836 Param = It.GetterCB(*V, *It.Ty, IConf, IIRB);
837 assert(Param);
838
839 if (Param->getType()->isVoidTy()) {
840 Param = Constant::getNullValue(It.Ty);
841 } else if (Param->getType()->isAggregateType() ||
842 Param->getType()->isVectorTy() ||
843 DL.getTypeSizeInBits(Param->getType()) >
844 DL.getTypeSizeInBits(It.Ty)) {
845 if (!isPotentiallyIndirect(It)) {
847 Twine("indirection needed for ") + It.Name + Twine(" in ") +
848 IO.getName() +
849 Twine(", but not indicated. Instrumentation is skipped"),
850 DS_Warning));
851 return nullptr;
852 }
853 ForceIndirection = true;
854 } else {
855 Param = tryToCast(IIRB.IRB, Param, It.Ty, DL);
856 }
857 CallParams.push_back(Param);
858 }
859
860 if (ForceIndirection) {
861 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
862
863 unsigned Offset = 0;
864 for (auto &It : IO.IRTArgs) {
865 if (!It.Enabled)
866 continue;
867
868 if (!isPotentiallyIndirect(It)) {
869 ++Offset;
870 continue;
871 }
872 auto *&CallParam = CallParams[Offset++];
873 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE)) {
874 CallParams.insert(&CallParam + 1, IIRB.IRB.getInt32(DL.getTypeStoreSize(
875 CallParam->getType())));
876 Offset += 1;
877 }
878
879 auto *&CachedParam =
880 ICaches.IndirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
881 if (CachedParam) {
882 CallParam = CachedParam;
883 continue;
884 }
885
886 auto *AI = IIRB.getAlloca(Fn, CallParam->getType());
887 IIRB.IRB.CreateStore(CallParam, AI);
888 CallParam = CachedParam = tryToCast(IIRB.IRB, AI, IIRB.PtrTy, DL);
889 }
890 }
891
892 if (!ForceIndirection)
893 IIRB.IRB.SetInsertPoint(IP);
894 ensureDbgLoc(IIRB.IRB);
895
896 auto *FnTy = createLLVMSignature(IConf, IIRB, DL, ForceIndirection);
897 auto CompleteName =
898 IConf.getRTName(IO.IP.isPRE() ? "pre_" : "post_", IO.getName(),
899 ForceIndirection ? "_ind" : "");
900 auto FC = IIRB.IRB.getModule()->getOrInsertFunction(CompleteName, FnTy);
901 auto *CI = IIRB.IRB.CreateCall(FC, CallParams);
902 CI->addFnAttr(Attribute::get(IIRB.Ctx, Attribute::WillReturn));
903
904 for (unsigned I = 0, E = IO.IRTArgs.size(); I < E; ++I) {
905 if (!IO.IRTArgs[I].Enabled)
906 continue;
907 if (!isReplacable(IO.IRTArgs[I]))
908 continue;
909 bool IsCustomReplaceable = IO.IRTArgs[I].Flags & IRTArg::REPLACABLE_CUSTOM;
910 Value *NewValue = FnTy->isVoidTy() || IsCustomReplaceable
911 ? ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(),
912 IO.IRTArgs[I].Name}]
913 : CI;
914 assert(NewValue);
915 if (ForceIndirection && !IsCustomReplaceable &&
916 isPotentiallyIndirect(IO.IRTArgs[I])) {
917 auto *Q =
918 ICaches
919 .IndirectArgCache[{IIRB.Epoch, IO.getName(), IO.IRTArgs[I].Name}];
920 NewValue = IIRB.IRB.CreateLoad(V->getType(), Q);
921 }
922 V = IO.IRTArgs[I].SetterCB(*V, *NewValue, IConf, IIRB);
923 }
924 return CI;
925}
926
927template <typename Ty> constexpr static Value *getValue(Ty &ValueOrUse) {
928 if constexpr (std::is_same<Ty, Use>::value)
929 return ValueOrUse.get();
930 else
931 return static_cast<Value *>(&ValueOrUse);
932}
933
934template <typename Range>
937 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
938 auto *I32Ty = IIRB.IRB.getInt32Ty();
939 SmallVector<Constant *> ConstantValues;
942 for (auto &RE : R) {
943 Value *V = getValue(RE);
944 if (!V->getType()->isSized())
945 continue;
946 auto VSize = IIRB.DL.getTypeAllocSize(V->getType());
947 ConstantValues.push_back(getCI(I32Ty, VSize));
948 Types.push_back(I32Ty);
949 ConstantValues.push_back(getCI(I32Ty, V->getType()->getTypeID()));
950 Types.push_back(I32Ty);
951 if (uint32_t MisAlign = VSize % 8) {
952 Types.push_back(ArrayType::get(IIRB.Int8Ty, 8 - MisAlign));
953 ConstantValues.push_back(ConstantArray::getNullValue(Types.back()));
954 }
955 Types.push_back(V->getType());
956 if (auto *C = dyn_cast<Constant>(V)) {
957 ConstantValues.push_back(C);
958 continue;
959 }
960 Values.push_back({V, ConstantValues.size()});
961 ConstantValues.push_back(Constant::getNullValue(V->getType()));
962 }
963 if (Types.empty())
964 return ConstantPointerNull::get(IIRB.PtrTy);
965
966 StructType *STy = StructType::get(Fn->getContext(), Types, /*isPacked=*/true);
967 Constant *Initializer = ConstantStruct::get(STy, ConstantValues);
968
969 GlobalVariable *&GV = IConf.ConstantGlobalsCache[Initializer];
970 if (!GV)
971 GV = new GlobalVariable(*Fn->getParent(), STy, false,
972 GlobalValue::InternalLinkage, Initializer,
973 IConf.getRTName("", "value_pack"));
974
975 auto *AI = IIRB.getAlloca(Fn, STy);
976 IIRB.IRB.CreateMemCpy(AI, AI->getAlign(), GV, GV->getAlign(),
977 IIRB.DL.getTypeAllocSize(STy));
978 for (auto [Param, Idx] : Values) {
979 auto *Ptr = IIRB.IRB.CreateStructGEP(STy, AI, Idx);
980 IIRB.IRB.CreateStore(Param, Ptr);
981 }
982 return AI;
983}
984
985template <typename Range>
986static void readValuePack(const Range &R, Value &Pack,
988 function_ref<void(int, Value *)> SetterCB) {
989 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
990 auto &DL = Fn->getDataLayout();
991 SmallVector<Value *> ParameterValues;
992 unsigned Offset = 0;
993 for (const auto &[Idx, RE] : enumerate(R)) {
994 Value *V = getValue(RE);
995 if (!V->getType()->isSized())
996 continue;
997 Offset += 8;
998 auto VSize = DL.getTypeAllocSize(V->getType());
999 auto Padding = alignTo(VSize, 8) - VSize;
1000 Offset += Padding;
1001 auto *Ptr = IIRB.IRB.CreateConstInBoundsGEP1_32(IIRB.Int8Ty, &Pack, Offset);
1002 auto *NewV = IIRB.IRB.CreateLoad(V->getType(), Ptr);
1003 SetterCB(Idx, NewV);
1004 Offset += VSize;
1005 }
1006}
1007
1009 InstrumentationConfig &IConf,
1011 auto &I = cast<Instruction>(V);
1012 return getCI(&Ty, I.getOpcode());
1013}
1014
1016 InstrumentationConfig &IConf,
1018 auto &I = cast<Instruction>(V);
1019 auto &DL = I.getDataLayout();
1020 return getCI(&Ty, DL.getTypeStoreSize(V.getType()));
1021}
1022
1024 InstrumentationConfig &IConf,
1026 auto &I = cast<Instruction>(V);
1027 return I.getOperand(0);
1028}
1029
1031 InstrumentationConfig &IConf,
1033 auto &I = cast<Instruction>(V);
1034 if (I.getNumOperands() > 1)
1035 return I.getOperand(1);
1036 return PoisonValue::get(&Ty);
1037}
1038
1040 InstrumentationConfig &IConf,
1042 return getCI(&Ty, V.getType()->getTypeID());
1043}
1044
1046 InstrumentationConfig &IConf,
1048 return getSubTypeID(*V.getType(), Ty);
1049}
1050
1051/// FunctionIO
1052/// {
1054 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1055 using namespace std::placeholders;
1056 if (UserConfig)
1057 Config = *UserConfig;
1058
1060 if (Config.has(PassAddress))
1061 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "address", "The function address.",
1063 if (Config.has(PassName))
1064 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The function name.",
1066 if (Config.has(PassNumArguments))
1067 IRTArgs.push_back(
1068 IRTArg(IIRB.Int32Ty, "num_arguments",
1069 "Number of function arguments (without varargs).", IRTArg::NONE,
1070 std::bind(&FunctionIO::getNumArguments, this, _1, _2, _3, _4)));
1071 if (Config.has(PassArguments))
1072 IRTArgs.push_back(IRTArg(
1073 IIRB.PtrTy, "arguments", "Description of the arguments.",
1075 : IRTArg::NONE) |
1077 std::bind(&FunctionIO::getArguments, this, _1, _2, _3, _4),
1078 std::bind(&FunctionIO::setArguments, this, _1, _2, _3, _4)));
1079 if (Config.has(PassIsMain))
1080 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_main",
1081 "Flag to indicate it is the main function.",
1083 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1084 IConf.addChoice(*this, IIRB.Ctx);
1085}
1086
1088 InstrumentationConfig &IConf,
1090 auto &Fn = cast<Function>(V);
1091 if (Fn.isIntrinsic())
1092 return Constant::getNullValue(&Ty);
1093 return &V;
1094}
1096 InstrumentationConfig &IConf,
1098 auto &Fn = cast<Function>(V);
1099 return IConf.getGlobalString(IConf.DemangleFunctionNames->getBool()
1100 ? demangle(Fn.getName())
1101 : Fn.getName(),
1102 IIRB);
1103}
1105 InstrumentationConfig &IConf,
1107 auto &Fn = cast<Function>(V);
1108 if (!Config.ArgFilter)
1109 return getCI(&Ty, Fn.arg_size());
1110 auto FRange = make_filter_range(Fn.args(), Config.ArgFilter);
1111 return getCI(&Ty, std::distance(FRange.begin(), FRange.end()));
1112}
1114 InstrumentationConfig &IConf,
1116 auto &Fn = cast<Function>(V);
1117 if (!Config.ArgFilter)
1118 return createValuePack(Fn.args(), IConf, IIRB);
1119 return createValuePack(make_filter_range(Fn.args(), Config.ArgFilter), IConf,
1120 IIRB);
1121}
1123 InstrumentationConfig &IConf,
1125 auto &Fn = cast<Function>(V);
1126 auto *AIt = Fn.arg_begin();
1127 auto CB = [&](int Idx, Value *ReplV) {
1128 while (Config.ArgFilter && !Config.ArgFilter(*AIt))
1129 ++AIt;
1130 Fn.getArg(Idx)->replaceUsesWithIf(ReplV, [&](Use &U) {
1131 return IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) != IIRB.Epoch;
1132 });
1133 ++AIt;
1134 };
1135 if (!Config.ArgFilter)
1136 readValuePack(Fn.args(), NewV, IIRB, CB);
1137 else
1138 readValuePack(make_filter_range(Fn.args(), Config.ArgFilter), NewV, IIRB,
1139 CB);
1140 return &Fn;
1141}
1143 InstrumentationConfig &IConf,
1145 auto &Fn = cast<Function>(V);
1146 return getCI(&Ty, Fn.getName() == "main");
1147}
1148
1149/// UnreachableIO
1150///{
1152 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1153 if (UserConfig)
1154 Config = *UserConfig;
1155 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1156 IConf.addChoice(*this, IIRB.Ctx);
1157}
1158///}
1159
1160/// AllocaIO
1161///{
1163 ConfigTy *UserConfig) {
1164 if (UserConfig)
1165 Config = *UserConfig;
1166
1168 if (!IsPRE && Config.has(PassAddress))
1169 IRTArgs.push_back(
1170 IRTArg(IIRB.PtrTy, "address", "The allocated memory address.",
1174 if (Config.has(PassSize))
1175 IRTArgs.push_back(IRTArg(
1176 IIRB.Int64Ty, "size", "The allocation size.",
1178 getSize, setSize));
1179 if (Config.has(PassAlignment))
1180 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1181 "The allocation alignment.", IRTArg::NONE,
1182 getAlignment));
1183
1184 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1185 IConf.addChoice(*this, IIRB.Ctx);
1186}
1187
1190 auto &AI = cast<AllocaInst>(V);
1191 return IIRB.IRB.CreateAllocationSize(&Ty, &AI);
1192}
1193
1196 auto &AI = cast<AllocaInst>(V);
1197 const DataLayout &DL = AI.getDataLayout();
1198 auto *NewAI = IIRB.IRB.CreateAlloca(IIRB.IRB.getInt8Ty(),
1199 DL.getAllocaAddrSpace(), &NewV);
1200 NewAI->setAlignment(AI.getAlign());
1201 AI.replaceAllUsesWith(NewAI);
1202 IIRB.eraseLater(&AI);
1203 return NewAI;
1204}
1205
1208 return getCI(&Ty, cast<AllocaInst>(V).getAlign().value());
1209}
1210///}
1211
1213 ConfigTy *UserConfig) {
1214 if (UserConfig)
1215 Config = *UserConfig;
1216
1218 if (Config.has(PassPointer)) {
1219 IRTArgs.push_back(
1220 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1221 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1222 : IRTArg::NONE),
1224 }
1225 if (Config.has(PassPointerAS)) {
1226 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1227 "The address space of the accessed pointer.",
1229 }
1230 if (Config.has(PassBasePointerInfo)) {
1231 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1232 "The runtime provided base pointer info.",
1234 }
1235 if (Config.has(PassStoredValue)) {
1236 IRTArgs.push_back(
1237 IRTArg(getValueType(IIRB), "value", "The stored value.",
1240 : IRTArg::NONE),
1241 getValue));
1242 }
1243 if (Config.has(PassStoredValueSize)) {
1244 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1245 "The size of the stored value.", IRTArg::NONE,
1246 getValueSize));
1247 }
1248 if (Config.has(PassAlignment)) {
1249 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1250 "The known access alignment.", IRTArg::NONE,
1251 getAlignment));
1252 }
1253 if (Config.has(PassValueTypeId)) {
1254 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1255 "The type id of the stored value.", IRTArg::TYPEID,
1257 }
1258 if (Config.has(PassValueSubTypeId)) {
1259 IRTArgs.push_back(IRTArg(
1260 IIRB.Int32Ty, "value_sub_type_id",
1261 "The type id of the stored value (for arrays and vectors, or -1).",
1263 }
1264 if (Config.has(PassAtomicityOrdering)) {
1265 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1266 "The atomicity ordering of the store.",
1268 }
1269 if (Config.has(PassSyncScopeId)) {
1270 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1271 "The sync scope id of the store.", IRTArg::NONE,
1273 }
1274 if (Config.has(PassIsVolatile)) {
1275 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1276 "Flag indicating a volatile store.", IRTArg::NONE,
1277 isVolatile));
1278 }
1279
1280 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1281 IConf.addChoice(*this, IIRB.Ctx);
1282}
1283
1286 auto &SI = cast<StoreInst>(V);
1287 return SI.getPointerOperand();
1288}
1289
1292 auto &SI = cast<StoreInst>(V);
1293 SI.setOperand(SI.getPointerOperandIndex(), &NewV);
1294 return &SI;
1295}
1296
1299 auto &SI = cast<StoreInst>(V);
1300 return getCI(&Ty, SI.getPointerAddressSpace());
1301}
1302
1304 InstrumentationConfig &IConf,
1306 auto &SI = cast<StoreInst>(V);
1307 return IConf.getBasePointerInfo(*SI.getPointerOperand(), IIRB);
1308}
1309
1312 auto &SI = cast<StoreInst>(V);
1313 return SI.getValueOperand();
1314}
1315
1318 auto &SI = cast<StoreInst>(V);
1319 auto &DL = SI.getDataLayout();
1320 return getCI(&Ty, DL.getTypeStoreSize(SI.getValueOperand()->getType()));
1321}
1322
1325 auto &SI = cast<StoreInst>(V);
1326 return getCI(&Ty, SI.getAlign().value());
1327}
1328
1331 auto &SI = cast<StoreInst>(V);
1332 return getCI(&Ty, SI.getValueOperand()->getType()->getTypeID());
1333}
1334
1336 InstrumentationConfig &IConf,
1338 auto &SI = cast<StoreInst>(V);
1339 return getSubTypeID(*SI.getValueOperand()->getType(), Ty);
1340}
1341
1343 InstrumentationConfig &IConf,
1345 auto &SI = cast<StoreInst>(V);
1346 return getCI(&Ty, uint64_t(SI.getOrdering()));
1347}
1348
1351 auto &SI = cast<StoreInst>(V);
1352 return getCI(&Ty, uint64_t(SI.getSyncScopeID()));
1353}
1354
1357 auto &SI = cast<StoreInst>(V);
1358 return getCI(&Ty, SI.isVolatile());
1359}
1360
1362 ConfigTy *UserConfig) {
1364 if (UserConfig)
1365 Config = *UserConfig;
1366 if (Config.has(PassPointer)) {
1367 IRTArgs.push_back(
1368 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1369 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1370 : IRTArg::NONE),
1372 }
1373 if (Config.has(PassPointerAS)) {
1374 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1375 "The address space of the accessed pointer.",
1377 }
1378 if (Config.has(PassBasePointerInfo)) {
1379 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1380 "The runtime provided base pointer info.",
1382 }
1383 if (!IsPRE && Config.has(PassValue)) {
1384 IRTArgs.push_back(
1385 IRTArg(getValueType(IIRB), "value", "The loaded value.",
1386 Config.has(ReplaceValue)
1389 : IRTArg::NONE)
1390 : IRTArg::NONE,
1391 getValue, Config.has(ReplaceValue) ? replaceValue : nullptr));
1392 }
1393 if (Config.has(PassValueSize)) {
1394 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1395 "The size of the loaded value.", IRTArg::NONE,
1396 getValueSize));
1397 }
1398 if (Config.has(PassAlignment)) {
1399 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1400 "The known access alignment.", IRTArg::NONE,
1401 getAlignment));
1402 }
1403 if (Config.has(PassValueTypeId)) {
1404 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1405 "The type id of the loaded value.", IRTArg::TYPEID,
1407 }
1408 if (Config.has(PassValueSubTypeId)) {
1409 IRTArgs.push_back(IRTArg(
1410 IIRB.Int32Ty, "value_sub_type_id",
1411 "The sub type id of the loaded value (for arrays and vectors, or -1).",
1413 }
1414 if (Config.has(PassAtomicityOrdering)) {
1415 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1416 "The atomicity ordering of the load.",
1418 }
1419 if (Config.has(PassSyncScopeId)) {
1420 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1421 "The sync scope id of the load.", IRTArg::NONE,
1423 }
1424 if (Config.has(PassIsVolatile)) {
1425 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1426 "Flag indicating a volatile load.", IRTArg::NONE,
1427 isVolatile));
1428 }
1429
1430 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1431 IConf.addChoice(*this, IIRB.Ctx);
1432}
1433
1436 auto &LI = cast<LoadInst>(V);
1437 return LI.getPointerOperand();
1438}
1439
1442 auto &LI = cast<LoadInst>(V);
1443 LI.setOperand(LI.getPointerOperandIndex(), &NewV);
1444 return &LI;
1445}
1446
1449 auto &LI = cast<LoadInst>(V);
1450 return getCI(&Ty, LI.getPointerAddressSpace());
1451}
1452
1454 InstrumentationConfig &IConf,
1456 auto &LI = cast<LoadInst>(V);
1457 return IConf.getBasePointerInfo(*LI.getPointerOperand(), IIRB);
1458}
1459
1462 return &V;
1463}
1464
1467 auto &LI = cast<LoadInst>(V);
1468 auto &DL = LI.getDataLayout();
1469 return getCI(&Ty, DL.getTypeStoreSize(LI.getType()));
1470}
1471
1474 auto &LI = cast<LoadInst>(V);
1475 return getCI(&Ty, LI.getAlign().value());
1476}
1477
1480 auto &LI = cast<LoadInst>(V);
1481 return getCI(&Ty, LI.getType()->getTypeID());
1482}
1483
1485 InstrumentationConfig &IConf,
1487 auto &LI = cast<LoadInst>(V);
1488 return getSubTypeID(*LI.getType(), Ty);
1489}
1490
1492 InstrumentationConfig &IConf,
1494 auto &LI = cast<LoadInst>(V);
1495 return getCI(&Ty, uint64_t(LI.getOrdering()));
1496}
1497
1500 auto &LI = cast<LoadInst>(V);
1501 return getCI(&Ty, uint64_t(LI.getSyncScopeID()));
1502}
1503
1506 auto &LI = cast<LoadInst>(V);
1507 return getCI(&Ty, LI.isVolatile());
1508}
1509
1511 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1512 if (UserConfig)
1513 Config = *UserConfig;
1514 if (Config.has(PassPointer))
1515 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer",
1516 "The base pointer in question.",
1518 if (Config.has(PassPointerKind))
1519 IRTArgs.push_back(IRTArg(
1520 IIRB.Int32Ty, "base_pointer_kind",
1521 "The base pointer kind (argument, global, instruction, unknown).",
1523 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1524 IConf.addChoice(*this, IIRB.Ctx);
1525}
1526
1528 InstrumentationConfig &IConf,
1530 if (isa<Argument>(V))
1531 return getCI(&Ty, 0);
1532 if (isa<GlobalValue>(V))
1533 return getCI(&Ty, 1);
1534 if (isa<Instruction>(V))
1535 return getCI(&Ty, 2);
1536 return getCI(&Ty, 3);
1537}
1538
1540 ConfigTy *UserConfig) {
1541 if (UserConfig)
1542 Config = *UserConfig;
1543
1544 if (Config.has(PassName))
1545 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "module_name",
1546 "The module/translation unit name.",
1548 if (Config.has(PassTargetTriple))
1549 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "target_triple", "The target triple.",
1551
1552 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1553 IConf.addChoice(*this, IIRB.Ctx);
1554}
1557 // V is a constructor or destructor of the module we can place code in.
1558 auto &Fn = cast<Function>(V);
1559 return IConf.getGlobalString(Fn.getParent()->getName(), IIRB);
1560}
1562 InstrumentationConfig &IConf,
1564 // V is a constructor or destructor of the module we can place code in.
1565 auto &Fn = cast<Function>(V);
1566 return IConf.getGlobalString(Fn.getParent()->getTargetTriple().getTriple(),
1567 IIRB);
1568}
1569
1571 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1572 if (UserConfig)
1573 Config = *UserConfig;
1575 if (Config.has(PassAddress))
1576 IRTArgs.push_back(IRTArg(
1577 IIRB.PtrTy, "address",
1578 "The address of the global (replaceable for definitions).",
1581 if (Config.has(PassAS))
1582 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "address_space",
1583 "The address space of the global.", IRTArg::NONE,
1584 getAS));
1585 if (Config.has(PassDeclaredSize))
1586 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "declared_size",
1587 "The size of the declared type of the global.",
1589 if (Config.has(PassAlignment))
1590 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1591 "The allocation alignment.", IRTArg::NONE,
1592 getAlignment));
1593 if (Config.has(PassName))
1594 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The name of the global.",
1596 if (Config.has(PassInitialValue))
1597 IRTArgs.push_back(IRTArg(
1598 IIRB.Int64Ty, "initial_value", "The initial value of the global.",
1601 if (Config.has(PassIsConstant))
1602 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_constant",
1603 "Flag to indicate constant globals.", IRTArg::NONE,
1604 isConstant));
1605 if (Config.has(PassIsDefinition))
1606 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_definition",
1607 "Flag to indicate global definitions.",
1609 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1610 IConf.addChoice(*this, IIRB.Ctx);
1611}
1615 if (GV.getAddressSpace())
1616 return ConstantExpr::getAddrSpaceCast(&GV, IIRB.PtrTy);
1617 return &GV;
1618}
1620 InstrumentationConfig &IConf,
1623
1624 GlobalVariable *ShadowGV = nullptr;
1625 auto ShadowName = IConf.getRTName("shadow.", GV.getName());
1626 auto &DL = GV.getDataLayout();
1627 if (GV.isDeclaration()) {
1628 ShadowGV = new GlobalVariable(*GV.getParent(), GV.getType(), false,
1630 ShadowName, &GV, GV.getThreadLocalMode(),
1631 DL.getDefaultGlobalsAddressSpace());
1632 } else {
1633 ShadowGV = new GlobalVariable(
1634 *GV.getParent(), NewV.getType(), false, GV.getLinkage(),
1635 PoisonValue::get(NewV.getType()), ShadowName, &GV);
1636 IIRB.IRB.CreateStore(&NewV, ShadowGV);
1637 }
1638
1642 DenseMap<Value *, Instruction *> ConstToInstMap;
1644
1645 auto MakeInstForConst = [&](Use &U) {
1646 Instruction *&I = ConstToInstMap[U];
1647 if (I)
1648 return;
1649 if (U == &GV) {
1650 } else if (auto *CE = dyn_cast<ConstantExpr>(U)) {
1651 I = CE->getAsInstruction();
1652 }
1653 };
1654
1655 auto InsertConsts = [&](Instruction *UserI, Use &UserU) {
1657 auto *&Reload = ReloadMap[UserI->getFunction()];
1658 if (!Reload) {
1659 Reload = new LoadInst(
1660 GV.getType(), ShadowGV, GV.getName() + ".shadow_load",
1662 IIRB.NewInsts.insert({Reload, IIRB.Epoch});
1663 }
1664 Worklist.push_back({UserI, &UserU});
1665 while (!Worklist.empty()) {
1666 auto [I, U] = Worklist.pop_back_val();
1667 if (*U == &GV) {
1668 U->set(ReloadMap[I->getFunction()]);
1669 continue;
1670 }
1671 if (auto *CI = ConstToInstMap[*U]) {
1672 auto *CIClone = CI->clone();
1673 IIRB.NewInsts.insert({CIClone, IIRB.Epoch});
1674 if (auto *PHI = dyn_cast<PHINode>(I)) {
1675 auto *BB = PHI->getIncomingBlock(U->getOperandNo());
1676 CIClone->insertBefore(BB->getTerminator()->getIterator());
1677 } else {
1678 CIClone->insertBefore(I->getIterator());
1679 }
1680 U->set(CIClone);
1681 for (auto &CICUse : CIClone->operands()) {
1682 Worklist.push_back({CIClone, &CICUse});
1683 }
1684 }
1685 }
1686 };
1687
1688 SmallPtrSet<Use *, 8> Visited;
1689 while (!Worklist.empty()) {
1690 Use *U = Worklist.pop_back_val();
1691 if (!Done.insert(U).second)
1692 continue;
1693 MakeInstForConst(*U);
1694 auto *I = dyn_cast<Instruction>(U->getUser());
1695 if (!I) {
1696 append_range(Worklist, make_pointer_range(U->getUser()->uses()));
1697 continue;
1698 }
1699 if (IIRB.NewInsts.lookup(I) == IIRB.Epoch)
1700 continue;
1702 continue;
1703 if (auto *II = dyn_cast<IntrinsicInst>(I))
1704 if (II->getIntrinsicID() == Intrinsic::eh_typeid_for)
1705 continue;
1706 if (I->getParent())
1707 InsertConsts(I, *U);
1708 }
1709
1710 for (auto &It : ConstToInstMap)
1711 if (It.second)
1712 It.second->deleteValue();
1713
1714 return &V;
1715}
1719 return getCI(&Ty, GV.getAddressSpace());
1720}
1722 InstrumentationConfig &IConf,
1725 MaybeAlign Alignment = GV.getAlign();
1726 return getCI(&Ty, Alignment ? Alignment->value() : 0);
1727}
1729 InstrumentationConfig &IConf,
1732 auto &DL = GV.getDataLayout();
1733 return getCI(&Ty, DL.getTypeAllocSize(GV.getValueType()));
1734}
1736 InstrumentationConfig &IConf,
1739 return IConf.getGlobalString(GV.getName(), IIRB);
1740}
1751 return getCI(&Ty, GV.isConstant());
1752}
1754 InstrumentationConfig &IConf,
1757 return getCI(&Ty, !GV.isDeclaration());
1758}
1759
1760/// CastIO
1761/// {
1763 ConfigTy *UserConfig) {
1764 if (UserConfig)
1765 Config = *UserConfig;
1767 if (Config.has(PassInput))
1768 IRTArgs.push_back(
1769 IRTArg(IIRB.Int64Ty, "input", "Input value of the cast.",
1772 : IRTArg::NONE),
1773 getInput));
1774 if (Config.has(PassInputTypeId))
1775 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_type_id",
1776 "The type id of the input value.", IRTArg::TYPEID,
1778 if (Config.has(PassInputSubTypeId))
1779 IRTArgs.push_back(IRTArg(
1780 IIRB.Int32Ty, "input_sub_type_id",
1781 "The sub type id of the input value (for arrays and vectors, or -1).",
1783 if (Config.has(PassInputSize))
1784 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_size",
1785 "The size of the input value.", IRTArg::NONE,
1786 getInputSize));
1787 if (!IsPRE && Config.has(PassResult))
1788 IRTArgs.push_back(
1789 IRTArg(IIRB.Int64Ty, "result", "Result of the cast.",
1792 : IRTArg::NONE),
1793 getValue, Config.has(ReplaceResult) ? replaceValue : nullptr));
1794 if (Config.has(PassResultTypeId))
1795 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_type_id",
1796 "The type id of the result value.", IRTArg::TYPEID,
1798 if (Config.has(PassResultSubTypeId))
1799 IRTArgs.push_back(IRTArg(
1800 IIRB.Int32Ty, "result_sub_type_id",
1801 "The sub type id of the result value (for arrays and vectors, or -1).",
1803 if (Config.has(PassResultSize))
1804 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_size",
1805 "The size of the result value.", IRTArg::NONE,
1806 getResultSize));
1807 if (Config.has(PassOpcode))
1808 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode",
1809 "The opcode of the cast instruction.",
1811
1812 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1813 IConf.addChoice(*this, IIRB.Ctx);
1814}
1815
1818 auto &CI = cast<CastInst>(V);
1819 return CI.getOperand(0);
1820}
1821
1824 auto &CI = cast<CastInst>(V);
1825 return getCI(&Ty, CI.getSrcTy()->getTypeID());
1826}
1827
1829 InstrumentationConfig &IConf,
1831 auto &CI = cast<CastInst>(V);
1832 return getSubTypeID(*CI.getSrcTy(), Ty);
1833}
1834
1837 auto &CI = cast<CastInst>(V);
1838 auto &DL = CI.getDataLayout();
1839 return getCI(&Ty, DL.getTypeStoreSize(CI.getSrcTy()));
1840}
1841
1844 auto &CI = cast<CastInst>(V);
1845 return getCI(&Ty, CI.getDestTy()->getTypeID());
1846}
1847
1849 InstrumentationConfig &IConf,
1851 auto &CI = cast<CastInst>(V);
1852 return getSubTypeID(*CI.getDestTy(), Ty);
1853}
1854
1857 auto &CI = cast<CastInst>(V);
1858 auto &DL = CI.getDataLayout();
1859 return getCI(&Ty, DL.getTypeStoreSize(CI.getDestTy()));
1860}
1861///}
1862
1865 auto &I = cast<Instruction>(V);
1866 uint64_t Flag = NUMERIC_FLAG_NONE;
1867
1868 switch (I.getOpcode()) {
1869 case Instruction::Add:
1870 case Instruction::Sub:
1871 case Instruction::Mul:
1872 case Instruction::Shl:
1873 if (I.hasNoSignedWrap())
1875 if (I.hasNoUnsignedWrap())
1877 break;
1878 case Instruction::FAdd:
1879 case Instruction::FSub:
1880 case Instruction::FMul:
1881 case Instruction::FDiv:
1882 case Instruction::FNeg:
1883 if (I.hasNoNaNs())
1885 if (I.hasNoInfs())
1887 if (I.hasNoSignedZeros())
1889 break;
1890 case Instruction::AShr:
1891 case Instruction::LShr:
1892 case Instruction::SDiv:
1893 case Instruction::UDiv:
1894 if (I.isExact())
1895 Flag |= NUMERIC_FLAG_IS_EXACT;
1896 break;
1897 }
1898
1899 if (auto *DI = dyn_cast<PossiblyDisjointInst>(&V))
1900 if (DI->isDisjoint())
1902
1903 return getCI(&Ty, Flag);
1904}
1905
1914
1916 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1917 if (UserConfig)
1918 Config = UserConfig;
1920 const auto ValArgOpts =
1923 if (Config.has(PassTypeId))
1924 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "type_id",
1925 "The operation's type id.", IRTArg::TYPEID,
1926 getTypeId));
1927 if (Config.has(PassSubTypeId))
1928 IRTArgs.push_back(
1929 IRTArg(IIRB.Int32Ty, "sub_type_id",
1930 "The operation's sub type id (for arrays and vectors, or -1).",
1932 if (Config.has(PassSize))
1933 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "size", "The operation's type size.",
1935 if (Config.has(PassOpcode))
1936 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
1938 if (Config.has(PassLeft))
1939 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
1940 "The operation's left operand.", ValArgOpts,
1942 if (Config.has(PassRight))
1943 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
1944 "The operation's right operand. This value is "
1945 "poison for unary operations.",
1946 ValArgOpts, getRightOperand));
1947 if (!IsPRE && Config.has(PassResult))
1948 IRTArgs.push_back(
1949 IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
1950 IRTArg::REPLACABLE | ValArgOpts, getValue,
1951 Config.has(ReplaceResult) ? replaceValue : nullptr));
1952 if (Config.has(PassFlags))
1953 IRTArgs.push_back(
1954 IRTArg(IIRB.Int64Ty, "flags",
1955 "A bitmask value signaling which instruction flags are present.",
1957 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1958 addFlagNames();
1959 IConf.addChoice(*this, IIRB.Ctx);
1960}
1961
1963 InstrumentationConfig &IConf,
1965 auto &I = cast<Instruction>(V);
1966 return getCI(&Ty, I.getOperand(0)->getType()->getTypeID());
1967}
1968
1970 InstrumentationConfig &IConf,
1972 auto &I = cast<Instruction>(V);
1973 auto &DL = I.getDataLayout();
1974 return getCI(&Ty, DL.getTypeStoreSize(I.getOperand(0)->getType()));
1975}
1976
1979 auto *CI = dyn_cast<CmpInst>(&V);
1980 return getCI(&Ty, CI->getPredicate());
1981}
1982
1989
1992 auto &I = cast<Instruction>(V);
1993 uint64_t Flag = NUMERIC_FLAG_NONE;
1994
1995 switch (I.getOpcode()) {
1996 case Instruction::ICmp:
1997 if (dyn_cast<ICmpInst>(&V)->hasSameSign())
1998 Flag |= COMPARE_FLAG_SAMESIGN;
1999 break;
2000 case Instruction::FCmp:
2001 if (I.hasNoNaNs())
2003 if (I.hasNoInfs())
2005 if (I.hasNoSignedZeros())
2007 break;
2008 }
2009
2010 return getCI(&Ty, Flag);
2011}
2012
2014 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
2015 if (UserConfig)
2016 Config = UserConfig;
2018 const auto OperandArgOpts =
2021 if (Config.has(PassOpTypeId))
2022 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "operand_type_id",
2023 "The operand type id.", IRTArg::NONE,
2025 if (Config.has(PassOpSize))
2026 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "operand_size",
2027 "The operand type size.", IRTArg::NONE,
2029 if (Config.has(PassOpcode))
2030 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
2032 if (Config.has(PassPredicate))
2033 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "predicate",
2034 "The comparison predicate ID.", IRTArg::NONE,
2035 getPredicate));
2036 if (Config.has(PassLeft))
2037 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
2038 "The comparison's left operand.", OperandArgOpts,
2040 if (Config.has(PassRight))
2041 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
2042 "The comparison's right operand.", OperandArgOpts,
2044 if (!IsPRE && Config.has(PassResultSize))
2045 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_type_id",
2046 "The result value's type ID.", IRTArg::NONE,
2047 getTypeId));
2048 if (!IsPRE && Config.has(PassResultSize))
2049 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_size",
2050 "Size of the result value.", IRTArg::NONE,
2051 getTypeSize));
2052 if (!IsPRE && Config.has(PassResult))
2053 IRTArgs.push_back(
2054 IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
2057 : IRTArg::NONE),
2058 getValue, Config.has(ReplaceResult) ? replaceValue : nullptr));
2059 if (Config.has(PassFlags))
2060 IRTArgs.push_back(
2061 IRTArg(IIRB.Int64Ty, "flags",
2062 "A bitmask value signaling which instruction flags are present.",
2064 addFlagNames();
2065 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
2066 IConf.addChoice(*this, IIRB.Ctx);
2067}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
uint64_t uint64_t
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")))
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
post inline ee instrument
#define _
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
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 getFirstNonPHIOrAlloca() const
Returns an iterator to the first instruction in this block that is not a PHINode, a static alloca,...
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:169
const BasicBlock & getEntryBlock() const
Definition Function.h:794
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:356
iterator_range< arg_iterator > args()
Definition Function.h:877
arg_iterator arg_begin()
Definition Function.h:853
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition Function.h:252
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
size_t arg_size() const
Definition Function.h:886
Argument * getArg(unsigned i) const
Definition Function.h:871
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:731
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:408
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:205
@ 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.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
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:76
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
static LLVM_ABI bool linkModules(Module &Dest, std::unique_ptr< Module > Src, unsigned Flags=Flags::None, std::function< void(Module &, const StringSet<> &)> InternalizeCallback={})
This function links two modules together, with the resulting Dest module modified to be the composite...
An instruction for reading from memory.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition Module.h:328
LLVMContext & getContext() const
Get the global data context.
Definition Module.h:332
size_t global_size() const
Definition Module.h:799
StringRef getName() const
Get a short "name" for the module.
Definition Module.h:316
iterator_range< global_iterator > globals()
Definition Module.h:802
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:70
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:84
StringRef getMessage() const
Definition SourceMgr.h:338
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:467
const std::string & getTriple() const
Definition Triple.h:582
bool isAMDGPU() const
Definition Triple.h:998
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:283
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:277
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:314
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:252
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:257
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:382
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
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.
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:577
LLVM_ABI void PromoteMemToReg(ArrayRef< AllocaInst * > Allocas, DominatorTree &DT, AssumptionCache *AC=nullptr)
Promote the specified list of alloca instructions into scalar registers, inserting PHI nodes as appro...
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:2570
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:2224
LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, bool TrackInlineHistory=false, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
This function inlines the called function into the basic block of the caller.
LLVM_ABI bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
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:149
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:552
LLVM_ABI const Value * getUnderlyingObjectAggressive(const Value *V, bool MustPreserveProvenance=false)
Like getUnderlyingObject(), but will try harder to find a single underlying object.
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.
ArrayRef(const T &OneElt) -> ArrayRef< T >
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
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2208
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
LLVM_ABI std::unique_ptr< Module > parseIRFile(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, ParserCallbacks Callbacks={}, AsmParserContext *ParserContext=nullptr)
If the given file holds a bitcode image, return a Module for it.
Definition IRReader.cpp:94
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:111
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 > createStringListOption(InstrumentationConfig &IC, StringRef Name, StringRef Description, ArrayRef< StringRef > DefaultValue)
Create a string-list option with Name name, Description description and DefaultValue as string-list d...
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.
std::unique_ptr< BaseConfigurationOption > InlineRuntimeEagerly
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
std::unique_ptr< BaseConfigurationOption > RuntimeBitcodes
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)
StringMap< int32_t > FlagNames
Flag names and their integer bitmask values.
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)
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.
DenseMap< std::pair< Function *, unsigned >, AllocaListTy * > AllocaMap
Map that holds a list of currently available allocas for a function and alloca size.
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