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 unsigned Offset = 0;
992 for (const auto &[Idx, RE] : enumerate(R)) {
993 Value *V = getValue(RE);
994 if (!V->getType()->isSized())
995 continue;
996 Offset += 8;
997 auto VSize = DL.getTypeAllocSize(V->getType());
998 auto Padding = alignTo(VSize, 8) - VSize;
999 Offset += Padding;
1000 auto *Ptr = IIRB.IRB.CreateConstInBoundsGEP1_32(IIRB.Int8Ty, &Pack, Offset);
1001 auto *NewV = IIRB.IRB.CreateLoad(V->getType(), Ptr);
1002 SetterCB(Idx, NewV);
1003 Offset += VSize;
1004 }
1005}
1006
1008 InstrumentationConfig &IConf,
1010 auto &I = cast<Instruction>(V);
1011 return getCI(&Ty, I.getOpcode());
1012}
1013
1015 InstrumentationConfig &IConf,
1017 auto &I = cast<Instruction>(V);
1018 auto &DL = I.getDataLayout();
1019 return getCI(&Ty, DL.getTypeStoreSize(V.getType()));
1020}
1021
1023 InstrumentationConfig &IConf,
1025 auto &I = cast<Instruction>(V);
1026 return I.getOperand(0);
1027}
1028
1030 InstrumentationConfig &IConf,
1032 auto &I = cast<Instruction>(V);
1033 if (I.getNumOperands() > 1)
1034 return I.getOperand(1);
1035 return PoisonValue::get(&Ty);
1036}
1037
1039 InstrumentationConfig &IConf,
1041 return getCI(&Ty, V.getType()->getTypeID());
1042}
1043
1045 InstrumentationConfig &IConf,
1047 return getSubTypeID(*V.getType(), Ty);
1048}
1049
1050/// FunctionIO
1051/// {
1053 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1054 using namespace std::placeholders;
1055 if (UserConfig)
1056 Config = *UserConfig;
1057
1059 if (Config.has(PassAddress))
1060 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "address", "The function address.",
1062 if (Config.has(PassName))
1063 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The function name.",
1065 if (Config.has(PassNumArguments))
1066 IRTArgs.push_back(
1067 IRTArg(IIRB.Int32Ty, "num_arguments",
1068 "Number of function arguments (without varargs).", IRTArg::NONE,
1069 std::bind(&FunctionIO::getNumArguments, this, _1, _2, _3, _4)));
1070 if (Config.has(PassArguments))
1071 IRTArgs.push_back(IRTArg(
1072 IIRB.PtrTy, "arguments", "Description of the arguments.",
1074 : IRTArg::NONE) |
1076 std::bind(&FunctionIO::getArguments, this, _1, _2, _3, _4),
1077 std::bind(&FunctionIO::setArguments, this, _1, _2, _3, _4)));
1078 if (Config.has(PassIsMain))
1079 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_main",
1080 "Flag to indicate it is the main function.",
1082 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1083 IConf.addChoice(*this, IIRB.Ctx);
1084}
1085
1087 InstrumentationConfig &IConf,
1089 auto &Fn = cast<Function>(V);
1090 if (Fn.isIntrinsic())
1091 return Constant::getNullValue(&Ty);
1092 return &V;
1093}
1095 InstrumentationConfig &IConf,
1097 auto &Fn = cast<Function>(V);
1098 return IConf.getGlobalString(IConf.DemangleFunctionNames->getBool()
1099 ? demangle(Fn.getName())
1100 : Fn.getName(),
1101 IIRB);
1102}
1104 InstrumentationConfig &IConf,
1106 auto &Fn = cast<Function>(V);
1107 if (!Config.ArgFilter)
1108 return getCI(&Ty, Fn.arg_size());
1109 auto FRange = make_filter_range(Fn.args(), Config.ArgFilter);
1110 return getCI(&Ty, std::distance(FRange.begin(), FRange.end()));
1111}
1113 InstrumentationConfig &IConf,
1115 auto &Fn = cast<Function>(V);
1116 if (!Config.ArgFilter)
1117 return createValuePack(Fn.args(), IConf, IIRB);
1118 return createValuePack(make_filter_range(Fn.args(), Config.ArgFilter), IConf,
1119 IIRB);
1120}
1122 InstrumentationConfig &IConf,
1124 auto &Fn = cast<Function>(V);
1125 auto *AIt = Fn.arg_begin();
1126 auto CB = [&](int Idx, Value *ReplV) {
1127 while (Config.ArgFilter && !Config.ArgFilter(*AIt))
1128 ++AIt;
1129 Fn.getArg(Idx)->replaceUsesWithIf(ReplV, [&](Use &U) {
1130 return IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) != IIRB.Epoch;
1131 });
1132 ++AIt;
1133 };
1134 if (!Config.ArgFilter)
1135 readValuePack(Fn.args(), NewV, IIRB, CB);
1136 else
1137 readValuePack(make_filter_range(Fn.args(), Config.ArgFilter), NewV, IIRB,
1138 CB);
1139 return &Fn;
1140}
1142 InstrumentationConfig &IConf,
1144 auto &Fn = cast<Function>(V);
1145 return getCI(&Ty, Fn.getName() == "main");
1146}
1147
1148/// UnreachableIO
1149///{
1151 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1152 if (UserConfig)
1153 Config = *UserConfig;
1154 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1155 IConf.addChoice(*this, IIRB.Ctx);
1156}
1157///}
1158
1159/// AllocaIO
1160///{
1162 ConfigTy *UserConfig) {
1163 if (UserConfig)
1164 Config = *UserConfig;
1165
1167 if (!IsPRE && Config.has(PassAddress))
1168 IRTArgs.push_back(
1169 IRTArg(IIRB.PtrTy, "address", "The allocated memory address.",
1173 if (Config.has(PassSize))
1174 IRTArgs.push_back(IRTArg(
1175 IIRB.Int64Ty, "size", "The allocation size.",
1177 getSize, setSize));
1178 if (Config.has(PassAlignment))
1179 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1180 "The allocation alignment.", IRTArg::NONE,
1181 getAlignment));
1182
1183 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1184 IConf.addChoice(*this, IIRB.Ctx);
1185}
1186
1189 auto &AI = cast<AllocaInst>(V);
1190 return IIRB.IRB.CreateAllocationSize(&Ty, &AI);
1191}
1192
1195 auto &AI = cast<AllocaInst>(V);
1196 const DataLayout &DL = AI.getDataLayout();
1197 auto *NewAI = IIRB.IRB.CreateAlloca(IIRB.IRB.getInt8Ty(),
1198 DL.getAllocaAddrSpace(), &NewV);
1199 NewAI->setAlignment(AI.getAlign());
1200 AI.replaceAllUsesWith(NewAI);
1201 IIRB.eraseLater(&AI);
1202 return NewAI;
1203}
1204
1207 return getCI(&Ty, cast<AllocaInst>(V).getAlign().value());
1208}
1209///}
1210
1212 ConfigTy *UserConfig) {
1213 if (UserConfig)
1214 Config = *UserConfig;
1215
1217 if (Config.has(PassPointer)) {
1218 IRTArgs.push_back(
1219 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1220 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1221 : IRTArg::NONE),
1223 }
1224 if (Config.has(PassPointerAS)) {
1225 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1226 "The address space of the accessed pointer.",
1228 }
1229 if (Config.has(PassBasePointerInfo)) {
1230 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1231 "The runtime provided base pointer info.",
1233 }
1234 if (Config.has(PassStoredValue)) {
1235 IRTArgs.push_back(
1236 IRTArg(getValueType(IIRB), "value", "The stored value.",
1239 : IRTArg::NONE),
1240 getValue));
1241 }
1242 if (Config.has(PassStoredValueSize)) {
1243 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1244 "The size of the stored value.", IRTArg::NONE,
1245 getValueSize));
1246 }
1247 if (Config.has(PassAlignment)) {
1248 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1249 "The known access alignment.", IRTArg::NONE,
1250 getAlignment));
1251 }
1252 if (Config.has(PassValueTypeId)) {
1253 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1254 "The type id of the stored value.", IRTArg::TYPEID,
1256 }
1257 if (Config.has(PassValueSubTypeId)) {
1258 IRTArgs.push_back(IRTArg(
1259 IIRB.Int32Ty, "value_sub_type_id",
1260 "The type id of the stored value (for arrays and vectors, or -1).",
1262 }
1263 if (Config.has(PassAtomicityOrdering)) {
1264 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1265 "The atomicity ordering of the store.",
1267 }
1268 if (Config.has(PassSyncScopeId)) {
1269 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1270 "The sync scope id of the store.", IRTArg::NONE,
1272 }
1273 if (Config.has(PassIsVolatile)) {
1274 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1275 "Flag indicating a volatile store.", IRTArg::NONE,
1276 isVolatile));
1277 }
1278
1279 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1280 IConf.addChoice(*this, IIRB.Ctx);
1281}
1282
1285 auto &SI = cast<StoreInst>(V);
1286 return SI.getPointerOperand();
1287}
1288
1291 auto &SI = cast<StoreInst>(V);
1292 SI.setOperand(SI.getPointerOperandIndex(), &NewV);
1293 return &SI;
1294}
1295
1298 auto &SI = cast<StoreInst>(V);
1299 return getCI(&Ty, SI.getPointerAddressSpace());
1300}
1301
1303 InstrumentationConfig &IConf,
1305 auto &SI = cast<StoreInst>(V);
1306 return IConf.getBasePointerInfo(*SI.getPointerOperand(), IIRB);
1307}
1308
1311 auto &SI = cast<StoreInst>(V);
1312 return SI.getValueOperand();
1313}
1314
1317 auto &SI = cast<StoreInst>(V);
1318 auto &DL = SI.getDataLayout();
1319 return getCI(&Ty, DL.getTypeStoreSize(SI.getValueOperand()->getType()));
1320}
1321
1324 auto &SI = cast<StoreInst>(V);
1325 return getCI(&Ty, SI.getAlign().value());
1326}
1327
1330 auto &SI = cast<StoreInst>(V);
1331 return getCI(&Ty, SI.getValueOperand()->getType()->getTypeID());
1332}
1333
1335 InstrumentationConfig &IConf,
1337 auto &SI = cast<StoreInst>(V);
1338 return getSubTypeID(*SI.getValueOperand()->getType(), Ty);
1339}
1340
1342 InstrumentationConfig &IConf,
1344 auto &SI = cast<StoreInst>(V);
1345 return getCI(&Ty, uint64_t(SI.getOrdering()));
1346}
1347
1350 auto &SI = cast<StoreInst>(V);
1351 return getCI(&Ty, uint64_t(SI.getSyncScopeID()));
1352}
1353
1356 auto &SI = cast<StoreInst>(V);
1357 return getCI(&Ty, SI.isVolatile());
1358}
1359
1361 ConfigTy *UserConfig) {
1363 if (UserConfig)
1364 Config = *UserConfig;
1365 if (Config.has(PassPointer)) {
1366 IRTArgs.push_back(
1367 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1368 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1369 : IRTArg::NONE),
1371 }
1372 if (Config.has(PassPointerAS)) {
1373 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1374 "The address space of the accessed pointer.",
1376 }
1377 if (Config.has(PassBasePointerInfo)) {
1378 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1379 "The runtime provided base pointer info.",
1381 }
1382 if (!IsPRE && Config.has(PassValue)) {
1383 IRTArgs.push_back(
1384 IRTArg(getValueType(IIRB), "value", "The loaded value.",
1385 Config.has(ReplaceValue)
1388 : IRTArg::NONE)
1389 : IRTArg::NONE,
1390 getValue, Config.has(ReplaceValue) ? replaceValue : nullptr));
1391 }
1392 if (Config.has(PassValueSize)) {
1393 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1394 "The size of the loaded value.", IRTArg::NONE,
1395 getValueSize));
1396 }
1397 if (Config.has(PassAlignment)) {
1398 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1399 "The known access alignment.", IRTArg::NONE,
1400 getAlignment));
1401 }
1402 if (Config.has(PassValueTypeId)) {
1403 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1404 "The type id of the loaded value.", IRTArg::TYPEID,
1406 }
1407 if (Config.has(PassValueSubTypeId)) {
1408 IRTArgs.push_back(IRTArg(
1409 IIRB.Int32Ty, "value_sub_type_id",
1410 "The sub type id of the loaded value (for arrays and vectors, or -1).",
1412 }
1413 if (Config.has(PassAtomicityOrdering)) {
1414 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1415 "The atomicity ordering of the load.",
1417 }
1418 if (Config.has(PassSyncScopeId)) {
1419 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1420 "The sync scope id of the load.", IRTArg::NONE,
1422 }
1423 if (Config.has(PassIsVolatile)) {
1424 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1425 "Flag indicating a volatile load.", IRTArg::NONE,
1426 isVolatile));
1427 }
1428
1429 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1430 IConf.addChoice(*this, IIRB.Ctx);
1431}
1432
1435 auto &LI = cast<LoadInst>(V);
1436 return LI.getPointerOperand();
1437}
1438
1441 auto &LI = cast<LoadInst>(V);
1442 LI.setOperand(LI.getPointerOperandIndex(), &NewV);
1443 return &LI;
1444}
1445
1448 auto &LI = cast<LoadInst>(V);
1449 return getCI(&Ty, LI.getPointerAddressSpace());
1450}
1451
1453 InstrumentationConfig &IConf,
1455 auto &LI = cast<LoadInst>(V);
1456 return IConf.getBasePointerInfo(*LI.getPointerOperand(), IIRB);
1457}
1458
1461 return &V;
1462}
1463
1466 auto &LI = cast<LoadInst>(V);
1467 auto &DL = LI.getDataLayout();
1468 return getCI(&Ty, DL.getTypeStoreSize(LI.getType()));
1469}
1470
1473 auto &LI = cast<LoadInst>(V);
1474 return getCI(&Ty, LI.getAlign().value());
1475}
1476
1479 auto &LI = cast<LoadInst>(V);
1480 return getCI(&Ty, LI.getType()->getTypeID());
1481}
1482
1484 InstrumentationConfig &IConf,
1486 auto &LI = cast<LoadInst>(V);
1487 return getSubTypeID(*LI.getType(), Ty);
1488}
1489
1491 InstrumentationConfig &IConf,
1493 auto &LI = cast<LoadInst>(V);
1494 return getCI(&Ty, uint64_t(LI.getOrdering()));
1495}
1496
1499 auto &LI = cast<LoadInst>(V);
1500 return getCI(&Ty, uint64_t(LI.getSyncScopeID()));
1501}
1502
1505 auto &LI = cast<LoadInst>(V);
1506 return getCI(&Ty, LI.isVolatile());
1507}
1508
1510 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1511 if (UserConfig)
1512 Config = *UserConfig;
1513 if (Config.has(PassPointer))
1514 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer",
1515 "The base pointer in question.",
1517 if (Config.has(PassPointerKind))
1518 IRTArgs.push_back(IRTArg(
1519 IIRB.Int32Ty, "base_pointer_kind",
1520 "The base pointer kind (argument, global, instruction, unknown).",
1522 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1523 IConf.addChoice(*this, IIRB.Ctx);
1524}
1525
1527 InstrumentationConfig &IConf,
1529 if (isa<Argument>(V))
1530 return getCI(&Ty, 0);
1531 if (isa<GlobalValue>(V))
1532 return getCI(&Ty, 1);
1533 if (isa<Instruction>(V))
1534 return getCI(&Ty, 2);
1535 return getCI(&Ty, 3);
1536}
1537
1539 ConfigTy *UserConfig) {
1540 if (UserConfig)
1541 Config = *UserConfig;
1542
1543 if (Config.has(PassName))
1544 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "module_name",
1545 "The module/translation unit name.",
1547 if (Config.has(PassTargetTriple))
1548 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "target_triple", "The target triple.",
1550
1551 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1552 IConf.addChoice(*this, IIRB.Ctx);
1553}
1556 // V is a constructor or destructor of the module we can place code in.
1557 auto &Fn = cast<Function>(V);
1558 return IConf.getGlobalString(Fn.getParent()->getName(), IIRB);
1559}
1561 InstrumentationConfig &IConf,
1563 // V is a constructor or destructor of the module we can place code in.
1564 auto &Fn = cast<Function>(V);
1565 return IConf.getGlobalString(Fn.getParent()->getTargetTriple().getTriple(),
1566 IIRB);
1567}
1568
1570 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1571 if (UserConfig)
1572 Config = *UserConfig;
1574 if (Config.has(PassAddress))
1575 IRTArgs.push_back(IRTArg(
1576 IIRB.PtrTy, "address",
1577 "The address of the global (replaceable for definitions).",
1580 if (Config.has(PassAS))
1581 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "address_space",
1582 "The address space of the global.", IRTArg::NONE,
1583 getAS));
1584 if (Config.has(PassDeclaredSize))
1585 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "declared_size",
1586 "The size of the declared type of the global.",
1588 if (Config.has(PassAlignment))
1589 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1590 "The allocation alignment.", IRTArg::NONE,
1591 getAlignment));
1592 if (Config.has(PassName))
1593 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The name of the global.",
1595 if (Config.has(PassInitialValue))
1596 IRTArgs.push_back(IRTArg(
1597 IIRB.Int64Ty, "initial_value", "The initial value of the global.",
1600 if (Config.has(PassIsConstant))
1601 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_constant",
1602 "Flag to indicate constant globals.", IRTArg::NONE,
1603 isConstant));
1604 if (Config.has(PassIsDefinition))
1605 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_definition",
1606 "Flag to indicate global definitions.",
1608 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1609 IConf.addChoice(*this, IIRB.Ctx);
1610}
1614 if (GV.getAddressSpace())
1615 return ConstantExpr::getAddrSpaceCast(&GV, IIRB.PtrTy);
1616 return &GV;
1617}
1619 InstrumentationConfig &IConf,
1622
1623 GlobalVariable *ShadowGV = nullptr;
1624 auto ShadowName = IConf.getRTName("shadow.", GV.getName());
1625 auto &DL = GV.getDataLayout();
1626 if (GV.isDeclaration()) {
1627 ShadowGV = new GlobalVariable(*GV.getParent(), GV.getType(), false,
1629 ShadowName, &GV, GV.getThreadLocalMode(),
1630 DL.getDefaultGlobalsAddressSpace());
1631 } else {
1632 ShadowGV = new GlobalVariable(
1633 *GV.getParent(), NewV.getType(), false, GV.getLinkage(),
1634 PoisonValue::get(NewV.getType()), ShadowName, &GV);
1635 IIRB.IRB.CreateStore(&NewV, ShadowGV);
1636 }
1637
1640 DenseMap<Value *, Instruction *> ConstToInstMap;
1642
1643 auto MakeInstForConst = [&](Use &U) {
1644 Instruction *&I = ConstToInstMap[U];
1645 if (I)
1646 return;
1647 if (U == &GV) {
1648 } else if (auto *CE = dyn_cast<ConstantExpr>(U)) {
1649 I = CE->getAsInstruction();
1650 }
1651 };
1652
1653 auto InsertConsts = [&](Instruction *UserI, Use &UserU) {
1655 auto *&Reload = ReloadMap[UserI->getFunction()];
1656 if (!Reload) {
1657 Reload = new LoadInst(
1658 GV.getType(), ShadowGV, GV.getName() + ".shadow_load",
1660 IIRB.NewInsts.insert({Reload, IIRB.Epoch});
1661 }
1662 Worklist.push_back({UserI, &UserU});
1663 while (!Worklist.empty()) {
1664 auto [I, U] = Worklist.pop_back_val();
1665 if (*U == &GV) {
1666 U->set(ReloadMap[I->getFunction()]);
1667 continue;
1668 }
1669 if (auto *CI = ConstToInstMap[*U]) {
1670 auto *CIClone = CI->clone();
1671 IIRB.NewInsts.insert({CIClone, IIRB.Epoch});
1672 if (auto *PHI = dyn_cast<PHINode>(I)) {
1673 auto *BB = PHI->getIncomingBlock(U->getOperandNo());
1674 CIClone->insertBefore(BB->getTerminator()->getIterator());
1675 } else {
1676 CIClone->insertBefore(I->getIterator());
1677 }
1678 U->set(CIClone);
1679 for (auto &CICUse : CIClone->operands()) {
1680 Worklist.push_back({CIClone, &CICUse});
1681 }
1682 }
1683 }
1684 };
1685
1686 while (!Worklist.empty()) {
1687 Use *U = Worklist.pop_back_val();
1688 if (!Done.insert(U).second)
1689 continue;
1690 MakeInstForConst(*U);
1691 auto *I = dyn_cast<Instruction>(U->getUser());
1692 if (!I) {
1693 append_range(Worklist, make_pointer_range(U->getUser()->uses()));
1694 continue;
1695 }
1696 if (IIRB.NewInsts.lookup(I) == IIRB.Epoch)
1697 continue;
1699 continue;
1700 if (auto *II = dyn_cast<IntrinsicInst>(I))
1701 if (II->getIntrinsicID() == Intrinsic::eh_typeid_for)
1702 continue;
1703 if (I->getParent())
1704 InsertConsts(I, *U);
1705 }
1706
1707 for (auto &It : ConstToInstMap)
1708 if (It.second)
1709 It.second->deleteValue();
1710
1711 return &V;
1712}
1716 return getCI(&Ty, GV.getAddressSpace());
1717}
1719 InstrumentationConfig &IConf,
1722 MaybeAlign Alignment = GV.getAlign();
1723 return getCI(&Ty, Alignment ? Alignment->value() : 0);
1724}
1726 InstrumentationConfig &IConf,
1729 auto &DL = GV.getDataLayout();
1730 return getCI(&Ty, DL.getTypeAllocSize(GV.getValueType()));
1731}
1733 InstrumentationConfig &IConf,
1736 return IConf.getGlobalString(GV.getName(), IIRB);
1737}
1748 return getCI(&Ty, GV.isConstant());
1749}
1751 InstrumentationConfig &IConf,
1754 return getCI(&Ty, !GV.isDeclaration());
1755}
1756
1757/// CastIO
1758/// {
1760 ConfigTy *UserConfig) {
1761 if (UserConfig)
1762 Config = *UserConfig;
1764 if (Config.has(PassInput))
1765 IRTArgs.push_back(
1766 IRTArg(IIRB.Int64Ty, "input", "Input value of the cast.",
1769 : IRTArg::NONE),
1770 getInput));
1771 if (Config.has(PassInputTypeId))
1772 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_type_id",
1773 "The type id of the input value.", IRTArg::TYPEID,
1775 if (Config.has(PassInputSubTypeId))
1776 IRTArgs.push_back(IRTArg(
1777 IIRB.Int32Ty, "input_sub_type_id",
1778 "The sub type id of the input value (for arrays and vectors, or -1).",
1780 if (Config.has(PassInputSize))
1781 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_size",
1782 "The size of the input value.", IRTArg::NONE,
1783 getInputSize));
1784 if (!IsPRE && Config.has(PassResult))
1785 IRTArgs.push_back(
1786 IRTArg(IIRB.Int64Ty, "result", "Result of the cast.",
1789 : IRTArg::NONE),
1790 getValue, Config.has(ReplaceResult) ? replaceValue : nullptr));
1791 if (Config.has(PassResultTypeId))
1792 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_type_id",
1793 "The type id of the result value.", IRTArg::TYPEID,
1795 if (Config.has(PassResultSubTypeId))
1796 IRTArgs.push_back(IRTArg(
1797 IIRB.Int32Ty, "result_sub_type_id",
1798 "The sub type id of the result value (for arrays and vectors, or -1).",
1800 if (Config.has(PassResultSize))
1801 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_size",
1802 "The size of the result value.", IRTArg::NONE,
1803 getResultSize));
1804 if (Config.has(PassOpcode))
1805 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode",
1806 "The opcode of the cast instruction.",
1808
1809 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1810 IConf.addChoice(*this, IIRB.Ctx);
1811}
1812
1815 auto &CI = cast<CastInst>(V);
1816 return CI.getOperand(0);
1817}
1818
1821 auto &CI = cast<CastInst>(V);
1822 return getCI(&Ty, CI.getSrcTy()->getTypeID());
1823}
1824
1826 InstrumentationConfig &IConf,
1828 auto &CI = cast<CastInst>(V);
1829 return getSubTypeID(*CI.getSrcTy(), Ty);
1830}
1831
1834 auto &CI = cast<CastInst>(V);
1835 auto &DL = CI.getDataLayout();
1836 return getCI(&Ty, DL.getTypeStoreSize(CI.getSrcTy()));
1837}
1838
1841 auto &CI = cast<CastInst>(V);
1842 return getCI(&Ty, CI.getDestTy()->getTypeID());
1843}
1844
1846 InstrumentationConfig &IConf,
1848 auto &CI = cast<CastInst>(V);
1849 return getSubTypeID(*CI.getDestTy(), Ty);
1850}
1851
1854 auto &CI = cast<CastInst>(V);
1855 auto &DL = CI.getDataLayout();
1856 return getCI(&Ty, DL.getTypeStoreSize(CI.getDestTy()));
1857}
1858///}
1859
1862 auto &I = cast<Instruction>(V);
1863 uint64_t Flag = NUMERIC_FLAG_NONE;
1864
1865 switch (I.getOpcode()) {
1866 case Instruction::Add:
1867 case Instruction::Sub:
1868 case Instruction::Mul:
1869 case Instruction::Shl:
1870 if (I.hasNoSignedWrap())
1872 if (I.hasNoUnsignedWrap())
1874 break;
1875 case Instruction::FAdd:
1876 case Instruction::FSub:
1877 case Instruction::FMul:
1878 case Instruction::FDiv:
1879 case Instruction::FNeg:
1880 if (I.hasNoNaNs())
1882 if (I.hasNoInfs())
1884 if (I.hasNoSignedZeros())
1886 break;
1887 case Instruction::AShr:
1888 case Instruction::LShr:
1889 case Instruction::SDiv:
1890 case Instruction::UDiv:
1891 if (I.isExact())
1892 Flag |= NUMERIC_FLAG_IS_EXACT;
1893 break;
1894 }
1895
1896 if (auto *DI = dyn_cast<PossiblyDisjointInst>(&V))
1897 if (DI->isDisjoint())
1899
1900 return getCI(&Ty, Flag);
1901}
1902
1911
1913 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1914 if (UserConfig)
1915 Config = UserConfig;
1917 const auto ValArgOpts =
1920 if (Config.has(PassTypeId))
1921 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "type_id",
1922 "The operation's type id.", IRTArg::TYPEID,
1923 getTypeId));
1924 if (Config.has(PassSubTypeId))
1925 IRTArgs.push_back(
1926 IRTArg(IIRB.Int32Ty, "sub_type_id",
1927 "The operation's sub type id (for arrays and vectors, or -1).",
1929 if (Config.has(PassSize))
1930 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "size", "The operation's type size.",
1932 if (Config.has(PassOpcode))
1933 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
1935 if (Config.has(PassLeft))
1936 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
1937 "The operation's left operand.", ValArgOpts,
1939 if (Config.has(PassRight))
1940 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
1941 "The operation's right operand. This value is "
1942 "poison for unary operations.",
1943 ValArgOpts, getRightOperand));
1944 if (!IsPRE && Config.has(PassResult))
1945 IRTArgs.push_back(
1946 IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
1947 IRTArg::REPLACABLE | ValArgOpts, getValue,
1948 Config.has(ReplaceResult) ? replaceValue : nullptr));
1949 if (Config.has(PassFlags))
1950 IRTArgs.push_back(
1951 IRTArg(IIRB.Int64Ty, "flags",
1952 "A bitmask value signaling which instruction flags are present.",
1954 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1955 addFlagNames();
1956 IConf.addChoice(*this, IIRB.Ctx);
1957}
1958
1960 InstrumentationConfig &IConf,
1962 auto &I = cast<Instruction>(V);
1963 return getCI(&Ty, I.getOperand(0)->getType()->getTypeID());
1964}
1965
1967 InstrumentationConfig &IConf,
1969 auto &I = cast<Instruction>(V);
1970 auto &DL = I.getDataLayout();
1971 return getCI(&Ty, DL.getTypeStoreSize(I.getOperand(0)->getType()));
1972}
1973
1976 auto *CI = dyn_cast<CmpInst>(&V);
1977 return getCI(&Ty, CI->getPredicate());
1978}
1979
1986
1989 auto &I = cast<Instruction>(V);
1990 uint64_t Flag = NUMERIC_FLAG_NONE;
1991
1992 switch (I.getOpcode()) {
1993 case Instruction::ICmp:
1994 if (dyn_cast<ICmpInst>(&V)->hasSameSign())
1995 Flag |= COMPARE_FLAG_SAMESIGN;
1996 break;
1997 case Instruction::FCmp:
1998 if (I.hasNoNaNs())
2000 if (I.hasNoInfs())
2002 if (I.hasNoSignedZeros())
2004 break;
2005 }
2006
2007 return getCI(&Ty, Flag);
2008}
2009
2011 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
2012 if (UserConfig)
2013 Config = UserConfig;
2015 const auto OperandArgOpts =
2018 if (Config.has(PassOpTypeId))
2019 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "operand_type_id",
2020 "The operand type id.", IRTArg::NONE,
2022 if (Config.has(PassOpSize))
2023 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "operand_size",
2024 "The operand type size.", IRTArg::NONE,
2026 if (Config.has(PassOpcode))
2027 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
2029 if (Config.has(PassPredicate))
2030 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "predicate",
2031 "The comparison predicate ID.", IRTArg::NONE,
2032 getPredicate));
2033 if (Config.has(PassLeft))
2034 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
2035 "The comparison's left operand.", OperandArgOpts,
2037 if (Config.has(PassRight))
2038 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
2039 "The comparison's right operand.", OperandArgOpts,
2041 if (!IsPRE && Config.has(PassResultSize))
2042 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_type_id",
2043 "The result value's type ID.", IRTArg::NONE,
2044 getTypeId));
2045 if (!IsPRE && Config.has(PassResultSize))
2046 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_size",
2047 "Size of the result value.", IRTArg::NONE,
2048 getTypeSize));
2049 if (!IsPRE && Config.has(PassResult))
2050 IRTArgs.push_back(
2051 IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
2054 : IRTArg::NONE),
2055 getValue, Config.has(ReplaceResult) ? replaceValue : nullptr));
2056 if (Config.has(PassFlags))
2057 IRTArgs.push_back(
2058 IRTArg(IIRB.Int64Ty, "flags",
2059 "A bitmask value signaling which instruction flags are present.",
2061 addFlagNames();
2062 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
2063 IConf.addChoice(*this, IIRB.Ctx);
2064}
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:44
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.
#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