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 bool RegexMatches = true;
335 if (ParsedFunctionRegex.isValid())
336 RegexMatches = ParsedFunctionRegex.match(Fn.getName());
337 return (RegexMatches && !Fn.getName().starts_with(IConf.getRTName())) ||
338 Fn.hasFnAttribute("instrument");
339}
340
341bool InstrumentorImpl::shouldInstrumentGlobalVariable(GlobalVariable &GV) {
342 return !GV.getName().starts_with("llvm.") &&
343 !GV.getName().starts_with(IConf.getRTName());
344}
345
346bool InstrumentorImpl::instrumentInstruction(Instruction &I,
347 InstrumentationCaches &ICaches) {
348 bool Changed = false;
349
350 // Skip instrumentation instructions.
351 if (IIRB.NewInsts.contains(&I))
352 return Changed;
353
354 // Count epochs eagerly.
355 ++IIRB.Epoch;
356
357 Value *IPtr = &I;
358 if (auto *IO = InstChoicesPRE.lookup(I.getOpcode())) {
359 IIRB.IRB.SetInsertPoint(&I);
360 ensureDbgLoc(IIRB.IRB);
361 IO->instrument(IPtr, Changed, IConf, IIRB, ICaches);
362 }
363
364 if (auto *IO = InstChoicesPOST.lookup(I.getOpcode())) {
365 IIRB.IRB.SetInsertPoint(I.getNextNode());
366 ensureDbgLoc(IIRB.IRB);
367 IO->instrument(IPtr, Changed, IConf, IIRB, ICaches);
368 }
369 IIRB.returnAllocas();
370
371 return Changed;
372}
373
374bool InstrumentorImpl::instrumentFunction(Function &Fn) {
375 bool Changed = false;
376 if (!shouldInstrumentFunction(Fn))
377 return Changed;
378
379 InstrumentationCaches ICaches;
380 SmallVector<Instruction *> FinalTIs;
381 ReversePostOrderTraversal<Function *> RPOT(&Fn);
382 for (auto &It : RPOT) {
383 for (auto &I : *It)
384 Changed |= instrumentInstruction(I, ICaches);
385
386 auto *TI = It->getTerminator();
387 if (!TI->getNumSuccessors())
388 FinalTIs.push_back(TI);
389 }
390
391 Value *FPtr = &Fn;
392 for (auto &[Name, IO] :
394 if (!IO->Enabled)
395 continue;
396 // Count epochs eagerly.
397 ++IIRB.Epoch;
398
399 IIRB.IRB.SetInsertPoint(
400 cast<Function>(FPtr)->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
401 ensureDbgLoc(IIRB.IRB);
402 IO->instrument(FPtr, Changed, IConf, IIRB, ICaches);
403 IIRB.returnAllocas();
404 }
405
406 for (auto &[Name, IO] :
408 if (!IO->Enabled)
409 continue;
410 // Count epochs eagerly.
411 ++IIRB.Epoch;
412
413 for (Instruction *FinalTI : FinalTIs) {
414 IIRB.IRB.SetInsertPoint(FinalTI);
415 ensureDbgLoc(IIRB.IRB);
416 IO->instrument(FPtr, Changed, IConf, IIRB, ICaches);
417 IIRB.returnAllocas();
418 }
419 }
420 return Changed;
421}
422
423bool InstrumentorImpl::instrumentModule() {
425 Globals.reserve(M.global_size());
426 for (GlobalVariable &GV : M.globals()) {
427 // llvm.metadata contains globals such as llvm.used.
428 if (GV.getSection() == "llvm.metadata" ||
429 GV.getName() == "llvm.global_dtors" ||
430 GV.getName() == "llvm.global_ctors")
431 continue;
432 Globals.push_back(&GV);
433 }
434
435 auto CreateYtor = [&](bool Ctor) {
436 Function *YtorFn = Function::Create(
437 FunctionType::get(IIRB.VoidTy, false), GlobalValue::PrivateLinkage,
438 IConf.getRTName(Ctor ? "ctor" : "dtor", ""), M);
439
440 auto *EntryBB = BasicBlock::Create(IIRB.Ctx, "entry", YtorFn);
441 IIRB.IRB.SetInsertPoint(EntryBB->begin());
442 ensureDbgLoc(IIRB.IRB);
443 IIRB.IRB.CreateRetVoid();
444
445 if (Ctor)
446 appendToGlobalCtors(M, YtorFn, 1000);
447 else
448 appendToGlobalDtors(M, YtorFn, 1000);
449 return YtorFn;
450 };
451
452 InstrumentationCaches ICaches;
453
454 Function *CtorFn = nullptr, *DtorFn = nullptr;
455 bool Changed = false;
458 bool IsPRE = InstrumentationLocation::isPRE(Loc);
459 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
460 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
461 auto *IO = ChoiceIt.second;
462 if (!IO->Enabled)
463 continue;
464 if (!YtorFn) {
465 YtorFn = CreateYtor(IsPRE);
466 Changed = true;
467 }
468 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
469 ensureDbgLoc(IIRB.IRB);
470 Value *YtorPtr = YtorFn;
471
472 // Count epochs eagerly.
473 ++IIRB.Epoch;
474
475 IO->instrument(YtorPtr, Changed, IConf, IIRB, ICaches);
476 IIRB.returnAllocas();
477 }
478 }
479
482 bool IsPRE = InstrumentationLocation::isPRE(Loc);
483 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
484 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
485 auto *IO = ChoiceIt.second;
486 if (!IO->Enabled)
487 continue;
488 if (!YtorFn) {
489 YtorFn = CreateYtor(IsPRE);
490 Changed = true;
491 }
492 for (GlobalVariable *GV : Globals) {
493 if (!shouldInstrumentGlobalVariable(*GV))
494 continue;
495 if (IsPRE)
496 IIRB.IRB.SetInsertPoint(YtorFn->getEntryBlock().getTerminator());
497 else
498 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
499 ensureDbgLoc(IIRB.IRB);
500 Value *GVPtr = GV;
501
502 // Count epochs eagerly.
503 ++IIRB.Epoch;
504
505 IO->instrument(GVPtr, Changed, IConf, IIRB, ICaches);
506 IIRB.returnAllocas();
507 }
508 }
509 }
510
511 return Changed;
512}
513
514bool InstrumentorImpl::instrument() {
515 bool Changed = false;
516 if (!shouldInstrumentTarget())
517 return Changed;
518
519 StringRef FunctionRegexStr = IConf.FunctionRegex->getString();
520 ParsedFunctionRegex = createRegex(FunctionRegexStr, "function", IIRB.Ctx);
521
522 // Helper to register an IO for all its opcodes.
523 auto RegisterForAllOpcodes = [](auto &InstChoices,
524 InstrumentationOpportunity *IO) {
525 ArrayRef<unsigned> Opcodes = IO->getAllOpcodes();
526 // Register for all opcodes.
527 for (unsigned Opcode : Opcodes)
528 InstChoices[Opcode] = IO;
529 };
530
531 for (auto &[Name, IO] :
533 if (IO->Enabled)
534 RegisterForAllOpcodes(InstChoicesPRE, IO);
535 for (auto &[Name, IO] :
537 if (IO->Enabled)
538 RegisterForAllOpcodes(InstChoicesPOST, IO);
539 Changed |= instrumentModule();
540
541 for (Function &Fn : M)
542 Changed |= instrumentFunction(Fn);
543
544 Changed |= linkRuntime();
545
546 return Changed;
547}
548
550 InstrumentationConfig *IC,
551 InstrumentorIRBuilderTy *IIRB)
552 : FS(FS), UserIConf(IC), UserIIRB(IIRB) {
553 if (!FS)
554 this->FS = vfs::getRealFileSystem();
555}
556
557PreservedAnalyses InstrumentorPass::run(Module &M, InstrumentationConfig &IConf,
559 bool ReadConfig) {
560 bool Changed = false;
561 InstrumentorImpl Impl(IConf, IIRB, M);
562
563 // If this is a configuration driven run, iterate over all configurations
564 // provided by the user, if not, use the config as is and run the instrumentor
565 // once.
566 if (ReadConfig)
567 readConfigPathsFile(ConfigPathsFile, ConfigFiles, IIRB.Ctx, *FS);
568
569 bool MultipleConfigs = ConfigFiles.size() > 1;
570 unsigned Idx = 0;
571 do {
572 std::string ConfigFile =
573 ReadConfig && !ConfigFiles.empty() ? ConfigFiles[Idx] : "";
574
575 // Initialize the config to the base state but keep the caches around.
576 Impl.clear();
577 IConf.init(IIRB);
578
579 if (!readConfigFromJSON(IConf, ConfigFile, IIRB.Ctx, *FS))
580 continue;
581
582 writeConfigToJSON(IConf,
583 MultipleConfigs
584 ? OutputConfigFile + "." + std::to_string(Idx)
585 : OutputConfigFile,
586 IIRB.Ctx);
587
588 printRuntimeStub(IConf, IConf.RuntimeStubsFile->getString(), IIRB.Ctx);
589
590 Changed |= Impl.instrument();
591 } while (++Idx < ConfigFiles.size());
592
593 if (!Changed)
594 return PreservedAnalyses::all();
596}
597
599 // Only create them if the user did not provide them.
600 std::unique_ptr<InstrumentationConfig> IConfInt(
601 !UserIConf ? new InstrumentationConfig() : nullptr);
602 std::unique_ptr<InstrumentorIRBuilderTy> IIRBInt(
603 !UserIIRB ? new InstrumentorIRBuilderTy(M) : nullptr);
604
605 auto *IConf = IConfInt ? IConfInt.get() : UserIConf;
606 auto *IIRB = IIRBInt ? IIRBInt.get() : UserIIRB;
607
608 auto PA = run(M, *IConf, *IIRB, !UserIConf);
609
610 assert(!verifyModule(M, &errs()));
611 return PA;
612}
613
614std::unique_ptr<BaseConfigurationOption>
617 bool DefaultValue) {
618 auto BCO =
619 std::make_unique<BaseConfigurationOption>(Name, Description, BOOLEAN);
620 BCO->setBool(DefaultValue);
621 IConf.addBaseChoice(BCO.get());
622 return BCO;
623}
624
625std::unique_ptr<BaseConfigurationOption>
629 StringRef DefaultValue) {
630 auto BCO =
631 std::make_unique<BaseConfigurationOption>(Name, Description, STRING);
632 BCO->setString(DefaultValue);
633 IConf.addBaseChoice(BCO.get());
634 return BCO;
635}
636
637std::unique_ptr<BaseConfigurationOption>
640 ArrayRef<StringRef> DefaultValue) {
641 auto BCO =
642 std::make_unique<BaseConfigurationOption>(Name, Description, STRING_LIST);
643 BCO->setStringList(DefaultValue);
644 IConf.addBaseChoice(BCO.get());
645 return BCO;
646}
647
649 /// List of all instrumentation opportunities.
650 BasePointerIO::populate(*this, IIRB);
651 ModuleIO::populate(*this, IIRB);
652 GlobalVarIO::populate(*this, IIRB);
653 FunctionIO::populate(*this, IIRB);
654 AllocaIO::populate(*this, IIRB);
655 UnreachableIO::populate(*this, IIRB);
656 LoadIO::populate(*this, IIRB);
657 StoreIO::populate(*this, IIRB);
658 CastIO::populate(*this, IIRB);
659 NumericIO::populate(*this, IIRB);
660 CompareIO::populate(*this, IIRB);
661}
662
664 LLVMContext &Ctx) {
665 auto *&ICPtr = IChoices[IO.getLocationKind()][IO.getName()];
666 if (ICPtr) {
668 Twine("registered two instrumentation opportunities for the same "
669 "location (") +
670 ICPtr->getName() + Twine(" vs ") + IO.getName() + Twine(")"),
671 DS_Warning));
672 }
673 ICPtr = &IO;
674}
675
676Value *
679 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
680
681 Value *Obj;
682 {
683 Value *&UnderlyingObj = UnderlyingObjsMap[&V];
684 if (!UnderlyingObj)
685 UnderlyingObj = const_cast<Value *>(getUnderlyingObjectAggressive(&V));
686 Obj = UnderlyingObj;
687 }
688
689 Value *&BPI = BasePointerInfoMap[{Obj, Fn}];
690 if (BPI)
691 return BPI;
692
693 auto *BPIO =
695 if (!BPIO || !BPIO->Enabled) {
697 "Base pointer info disabled but required, passing nullptr.",
698 DS_Warning));
699 return BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
700 }
701
703 if (auto *BasePtrI = dyn_cast<Instruction>(Obj)) {
704 std::optional<BasicBlock::iterator> IP =
705 BasePtrI->getInsertionPointAfterDef();
706 if (IP) {
707 IIRB.IRB.SetInsertPoint(*IP);
708 } else {
710 "Base pointer info could not be placed, passing nullptr.",
711 DS_Warning));
712 return BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
713 }
714 } else if (isa<Constant>(Obj) || isa<Argument>(Obj)) {
715 IIRB.IRB.SetInsertPointPastAllocas(IIRB.IRB.GetInsertBlock()->getParent());
716 } else {
717 LLVM_DEBUG(Obj->dump());
718 llvm_unreachable("Unexpected base pointer!");
719 }
720 ensureDbgLoc(IIRB.IRB);
721
722 // Use fresh caches for safety, as this function may be called from
723 // another instrumentation opportunity.
724 bool Changed;
725 InstrumentationCaches ICaches;
726 BPI = BPIO->instrument(Obj, Changed, *this, IIRB, ICaches);
727 IIRB.returnAllocas();
728 if (!BPI)
729 BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
730 return BPI;
731}
732
736 return getCI(&Ty, getIdFromEpoch(IIRB.Epoch));
737}
738
742 return getCI(&Ty, -getIdFromEpoch(IIRB.Epoch), /*IsSigned=*/true);
743}
744
747 if (V.getType()->isVoidTy())
748 return Ty.isVoidTy() ? &V : Constant::getNullValue(&Ty);
749 return tryToCast(IIRB.IRB, &V, &Ty, IIRB.IRB.getDataLayout());
750}
751
755 if (V.getType()->isVoidTy())
756 return &V;
757
758 auto *NewVCasted = &NewV;
759 if (auto *I = dyn_cast<Instruction>(&NewV)) {
761 IIRB.IRB.SetInsertPoint(I->getNextNode());
762 ensureDbgLoc(IIRB.IRB);
763 NewVCasted = tryToCast(IIRB.IRB, &NewV, V.getType(), IIRB.DL,
764 /*AllowTruncate=*/true);
765 }
766 V.replaceUsesWithIf(NewVCasted, [&](Use &U) {
767 if (IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) == IIRB.Epoch)
768 return false;
769 return !isa<LifetimeIntrinsic>(U.getUser()) && !U.getUser()->isDroppable();
770 });
771
772 return &V;
773}
774
776 Type *RetTy)
777 : IO(IO), RetTy(RetTy) {
778 for (auto &It : IO.IRTArgs) {
779 if (!It.Enabled)
780 continue;
781 NumReplaceableArgs += bool(It.Flags & IRTArg::REPLACABLE);
782 MightRequireIndirection |= It.Flags & IRTArg::POTENTIALLY_INDIRECT;
783 }
786}
787
790 const DataLayout &DL, bool ForceIndirection) {
791 assert(((ForceIndirection && MightRequireIndirection) ||
792 (!ForceIndirection && !RequiresIndirection)) &&
793 "Wrong indirection setting!");
794
795 SmallVector<Type *> ParamTypes;
796 for (auto &It : IO.IRTArgs) {
797 if (!It.Enabled)
798 continue;
799 if (!ForceIndirection || !isPotentiallyIndirect(It)) {
800 ParamTypes.push_back(It.Ty);
801 if (!RetTy && NumReplaceableArgs == 1 && (It.Flags & IRTArg::REPLACABLE))
802 RetTy = It.Ty;
803 continue;
804 }
805
806 // The indirection pointer and the size of the value.
807 ParamTypes.push_back(IIRB.PtrTy);
808 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE))
809 ParamTypes.push_back(IIRB.Int32Ty);
810 }
811 if (!RetTy)
812 RetTy = IIRB.VoidTy;
813
814 return FunctionType::get(RetTy, ParamTypes, /*isVarArg=*/false);
815}
816
820 const DataLayout &DL,
821 InstrumentationCaches &ICaches) {
822 SmallVector<Value *> CallParams;
823
825 auto IP = IIRB.IRB.GetInsertPoint();
826
827 bool ForceIndirection = RequiresIndirection;
828 for (auto &It : IO.IRTArgs) {
829 if (!It.Enabled)
830 continue;
831 auto *&Param = ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
832 if (!Param || It.NoCache)
833 // Avoid passing the caches to the getter.
834 Param = It.GetterCB(*V, *It.Ty, IConf, IIRB);
835 assert(Param);
836
837 if (Param->getType()->isVoidTy()) {
838 Param = Constant::getNullValue(It.Ty);
839 } else if (Param->getType()->isAggregateType() ||
840 Param->getType()->isVectorTy() ||
841 DL.getTypeSizeInBits(Param->getType()) >
842 DL.getTypeSizeInBits(It.Ty)) {
843 if (!isPotentiallyIndirect(It)) {
845 Twine("indirection needed for ") + It.Name + Twine(" in ") +
846 IO.getName() +
847 Twine(", but not indicated. Instrumentation is skipped"),
848 DS_Warning));
849 return nullptr;
850 }
851 ForceIndirection = true;
852 } else {
853 Param = tryToCast(IIRB.IRB, Param, It.Ty, DL);
854 }
855 CallParams.push_back(Param);
856 }
857
858 if (ForceIndirection) {
859 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
860
861 unsigned Offset = 0;
862 for (auto &It : IO.IRTArgs) {
863 if (!It.Enabled)
864 continue;
865
866 if (!isPotentiallyIndirect(It)) {
867 ++Offset;
868 continue;
869 }
870 auto *&CallParam = CallParams[Offset++];
871 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE)) {
872 CallParams.insert(&CallParam + 1, IIRB.IRB.getInt32(DL.getTypeStoreSize(
873 CallParam->getType())));
874 Offset += 1;
875 }
876
877 auto *&CachedParam =
878 ICaches.IndirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
879 if (CachedParam) {
880 CallParam = CachedParam;
881 continue;
882 }
883
884 auto *AI = IIRB.getAlloca(Fn, CallParam->getType());
885 IIRB.IRB.CreateStore(CallParam, AI);
886 CallParam = CachedParam = tryToCast(IIRB.IRB, AI, IIRB.PtrTy, DL);
887 }
888 }
889
890 if (!ForceIndirection)
891 IIRB.IRB.SetInsertPoint(IP);
892 ensureDbgLoc(IIRB.IRB);
893
894 auto *FnTy = createLLVMSignature(IConf, IIRB, DL, ForceIndirection);
895 auto CompleteName =
896 IConf.getRTName(IO.IP.isPRE() ? "pre_" : "post_", IO.getName(),
897 ForceIndirection ? "_ind" : "");
898 auto FC = IIRB.IRB.getModule()->getOrInsertFunction(CompleteName, FnTy);
899 auto *CI = IIRB.IRB.CreateCall(FC, CallParams);
900 CI->addFnAttr(Attribute::get(IIRB.Ctx, Attribute::WillReturn));
901
902 for (unsigned I = 0, E = IO.IRTArgs.size(); I < E; ++I) {
903 if (!IO.IRTArgs[I].Enabled)
904 continue;
905 if (!isReplacable(IO.IRTArgs[I]))
906 continue;
907 bool IsCustomReplaceable = IO.IRTArgs[I].Flags & IRTArg::REPLACABLE_CUSTOM;
908 Value *NewValue = FnTy->isVoidTy() || IsCustomReplaceable
909 ? ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(),
910 IO.IRTArgs[I].Name}]
911 : CI;
912 assert(NewValue);
913 if (ForceIndirection && !IsCustomReplaceable &&
914 isPotentiallyIndirect(IO.IRTArgs[I])) {
915 auto *Q =
916 ICaches
917 .IndirectArgCache[{IIRB.Epoch, IO.getName(), IO.IRTArgs[I].Name}];
918 NewValue = IIRB.IRB.CreateLoad(V->getType(), Q);
919 }
920 V = IO.IRTArgs[I].SetterCB(*V, *NewValue, IConf, IIRB);
921 }
922 return CI;
923}
924
925template <typename Ty> constexpr static Value *getValue(Ty &ValueOrUse) {
926 if constexpr (std::is_same<Ty, Use>::value)
927 return ValueOrUse.get();
928 else
929 return static_cast<Value *>(&ValueOrUse);
930}
931
932template <typename Range>
935 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
936 auto *I32Ty = IIRB.IRB.getInt32Ty();
937 SmallVector<Constant *> ConstantValues;
940 for (auto &RE : R) {
941 Value *V = getValue(RE);
942 if (!V->getType()->isSized())
943 continue;
944 auto VSize = IIRB.DL.getTypeAllocSize(V->getType());
945 ConstantValues.push_back(getCI(I32Ty, VSize));
946 Types.push_back(I32Ty);
947 ConstantValues.push_back(getCI(I32Ty, V->getType()->getTypeID()));
948 Types.push_back(I32Ty);
949 if (uint32_t MisAlign = VSize % 8) {
950 Types.push_back(ArrayType::get(IIRB.Int8Ty, 8 - MisAlign));
951 ConstantValues.push_back(ConstantArray::getNullValue(Types.back()));
952 }
953 Types.push_back(V->getType());
954 if (auto *C = dyn_cast<Constant>(V)) {
955 ConstantValues.push_back(C);
956 continue;
957 }
958 Values.push_back({V, ConstantValues.size()});
959 ConstantValues.push_back(Constant::getNullValue(V->getType()));
960 }
961 if (Types.empty())
962 return ConstantPointerNull::get(IIRB.PtrTy);
963
964 StructType *STy = StructType::get(Fn->getContext(), Types, /*isPacked=*/true);
965 Constant *Initializer = ConstantStruct::get(STy, ConstantValues);
966
967 GlobalVariable *&GV = IConf.ConstantGlobalsCache[Initializer];
968 if (!GV)
969 GV = new GlobalVariable(*Fn->getParent(), STy, false,
970 GlobalValue::InternalLinkage, Initializer,
971 IConf.getRTName("", "value_pack"));
972
973 auto *AI = IIRB.getAlloca(Fn, STy);
974 IIRB.IRB.CreateMemCpy(AI, AI->getAlign(), GV, GV->getAlign(),
975 IIRB.DL.getTypeAllocSize(STy));
976 for (auto [Param, Idx] : Values) {
977 auto *Ptr = IIRB.IRB.CreateStructGEP(STy, AI, Idx);
978 IIRB.IRB.CreateStore(Param, Ptr);
979 }
980 return AI;
981}
982
983template <typename Range>
984static void readValuePack(const Range &R, Value &Pack,
986 function_ref<void(int, Value *)> SetterCB) {
987 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
988 auto &DL = Fn->getDataLayout();
989 SmallVector<Value *> ParameterValues;
990 unsigned Offset = 0;
991 for (const auto &[Idx, RE] : enumerate(R)) {
992 Value *V = getValue(RE);
993 if (!V->getType()->isSized())
994 continue;
995 Offset += 8;
996 auto VSize = DL.getTypeAllocSize(V->getType());
997 auto Padding = alignTo(VSize, 8) - VSize;
998 Offset += Padding;
999 auto *Ptr = IIRB.IRB.CreateConstInBoundsGEP1_32(IIRB.Int8Ty, &Pack, Offset);
1000 auto *NewV = IIRB.IRB.CreateLoad(V->getType(), Ptr);
1001 SetterCB(Idx, NewV);
1002 Offset += VSize;
1003 }
1004}
1005
1007 InstrumentationConfig &IConf,
1009 auto &I = cast<Instruction>(V);
1010 return getCI(&Ty, I.getOpcode());
1011}
1012
1014 InstrumentationConfig &IConf,
1016 auto &I = cast<Instruction>(V);
1017 auto &DL = I.getDataLayout();
1018 return getCI(&Ty, DL.getTypeStoreSize(V.getType()));
1019}
1020
1022 InstrumentationConfig &IConf,
1024 auto &I = cast<Instruction>(V);
1025 return I.getOperand(0);
1026}
1027
1029 InstrumentationConfig &IConf,
1031 auto &I = cast<Instruction>(V);
1032 if (I.getNumOperands() > 1)
1033 return I.getOperand(1);
1034 return PoisonValue::get(&Ty);
1035}
1036
1038 InstrumentationConfig &IConf,
1040 return getCI(&Ty, V.getType()->getTypeID());
1041}
1042
1044 InstrumentationConfig &IConf,
1046 return getSubTypeID(*V.getType(), Ty);
1047}
1048
1049/// FunctionIO
1050/// {
1052 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1053 using namespace std::placeholders;
1054 if (UserConfig)
1055 Config = *UserConfig;
1056
1058 if (Config.has(PassAddress))
1059 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "address", "The function address.",
1061 if (Config.has(PassName))
1062 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The function name.",
1064 if (Config.has(PassNumArguments))
1065 IRTArgs.push_back(
1066 IRTArg(IIRB.Int32Ty, "num_arguments",
1067 "Number of function arguments (without varargs).", IRTArg::NONE,
1068 std::bind(&FunctionIO::getNumArguments, this, _1, _2, _3, _4)));
1069 if (Config.has(PassArguments))
1070 IRTArgs.push_back(IRTArg(
1071 IIRB.PtrTy, "arguments", "Description of the arguments.",
1073 : IRTArg::NONE) |
1075 std::bind(&FunctionIO::getArguments, this, _1, _2, _3, _4),
1076 std::bind(&FunctionIO::setArguments, this, _1, _2, _3, _4)));
1077 if (Config.has(PassIsMain))
1078 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_main",
1079 "Flag to indicate it is the main function.",
1081 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1082 IConf.addChoice(*this, IIRB.Ctx);
1083}
1084
1086 InstrumentationConfig &IConf,
1088 auto &Fn = cast<Function>(V);
1089 if (Fn.isIntrinsic())
1090 return Constant::getNullValue(&Ty);
1091 return &V;
1092}
1094 InstrumentationConfig &IConf,
1096 auto &Fn = cast<Function>(V);
1097 return IConf.getGlobalString(IConf.DemangleFunctionNames->getBool()
1098 ? demangle(Fn.getName())
1099 : Fn.getName(),
1100 IIRB);
1101}
1103 InstrumentationConfig &IConf,
1105 auto &Fn = cast<Function>(V);
1106 if (!Config.ArgFilter)
1107 return getCI(&Ty, Fn.arg_size());
1108 auto FRange = make_filter_range(Fn.args(), Config.ArgFilter);
1109 return getCI(&Ty, std::distance(FRange.begin(), FRange.end()));
1110}
1112 InstrumentationConfig &IConf,
1114 auto &Fn = cast<Function>(V);
1115 if (!Config.ArgFilter)
1116 return createValuePack(Fn.args(), IConf, IIRB);
1117 return createValuePack(make_filter_range(Fn.args(), Config.ArgFilter), IConf,
1118 IIRB);
1119}
1121 InstrumentationConfig &IConf,
1123 auto &Fn = cast<Function>(V);
1124 auto *AIt = Fn.arg_begin();
1125 auto CB = [&](int Idx, Value *ReplV) {
1126 while (Config.ArgFilter && !Config.ArgFilter(*AIt))
1127 ++AIt;
1128 Fn.getArg(Idx)->replaceUsesWithIf(ReplV, [&](Use &U) {
1129 return IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) != IIRB.Epoch;
1130 });
1131 ++AIt;
1132 };
1133 if (!Config.ArgFilter)
1134 readValuePack(Fn.args(), NewV, IIRB, CB);
1135 else
1136 readValuePack(make_filter_range(Fn.args(), Config.ArgFilter), NewV, IIRB,
1137 CB);
1138 return &Fn;
1139}
1141 InstrumentationConfig &IConf,
1143 auto &Fn = cast<Function>(V);
1144 return getCI(&Ty, Fn.getName() == "main");
1145}
1146
1147/// UnreachableIO
1148///{
1150 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1151 if (UserConfig)
1152 Config = *UserConfig;
1153 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1154 IConf.addChoice(*this, IIRB.Ctx);
1155}
1156///}
1157
1158/// AllocaIO
1159///{
1161 ConfigTy *UserConfig) {
1162 if (UserConfig)
1163 Config = *UserConfig;
1164
1166 if (!IsPRE && Config.has(PassAddress))
1167 IRTArgs.push_back(
1168 IRTArg(IIRB.PtrTy, "address", "The allocated memory address.",
1172 if (Config.has(PassSize))
1173 IRTArgs.push_back(IRTArg(
1174 IIRB.Int64Ty, "size", "The allocation size.",
1176 getSize, setSize));
1177 if (Config.has(PassAlignment))
1178 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1179 "The allocation alignment.", IRTArg::NONE,
1180 getAlignment));
1181
1182 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1183 IConf.addChoice(*this, IIRB.Ctx);
1184}
1185
1188 auto &AI = cast<AllocaInst>(V);
1189 return IIRB.IRB.CreateAllocationSize(&Ty, &AI);
1190}
1191
1194 auto &AI = cast<AllocaInst>(V);
1195 const DataLayout &DL = AI.getDataLayout();
1196 auto *NewAI = IIRB.IRB.CreateAlloca(IIRB.IRB.getInt8Ty(),
1197 DL.getAllocaAddrSpace(), &NewV);
1198 NewAI->setAlignment(AI.getAlign());
1199 AI.replaceAllUsesWith(NewAI);
1200 IIRB.eraseLater(&AI);
1201 return NewAI;
1202}
1203
1206 return getCI(&Ty, cast<AllocaInst>(V).getAlign().value());
1207}
1208///}
1209
1211 ConfigTy *UserConfig) {
1212 if (UserConfig)
1213 Config = *UserConfig;
1214
1216 if (Config.has(PassPointer)) {
1217 IRTArgs.push_back(
1218 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1219 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1220 : IRTArg::NONE),
1222 }
1223 if (Config.has(PassPointerAS)) {
1224 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1225 "The address space of the accessed pointer.",
1227 }
1228 if (Config.has(PassBasePointerInfo)) {
1229 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1230 "The runtime provided base pointer info.",
1232 }
1233 if (Config.has(PassStoredValue)) {
1234 IRTArgs.push_back(
1235 IRTArg(getValueType(IIRB), "value", "The stored value.",
1238 : IRTArg::NONE),
1239 getValue));
1240 }
1241 if (Config.has(PassStoredValueSize)) {
1242 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1243 "The size of the stored value.", IRTArg::NONE,
1244 getValueSize));
1245 }
1246 if (Config.has(PassAlignment)) {
1247 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1248 "The known access alignment.", IRTArg::NONE,
1249 getAlignment));
1250 }
1251 if (Config.has(PassValueTypeId)) {
1252 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1253 "The type id of the stored value.", IRTArg::TYPEID,
1255 }
1256 if (Config.has(PassValueSubTypeId)) {
1257 IRTArgs.push_back(IRTArg(
1258 IIRB.Int32Ty, "value_sub_type_id",
1259 "The type id of the stored value (for arrays and vectors, or -1).",
1261 }
1262 if (Config.has(PassAtomicityOrdering)) {
1263 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1264 "The atomicity ordering of the store.",
1266 }
1267 if (Config.has(PassSyncScopeId)) {
1268 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1269 "The sync scope id of the store.", IRTArg::NONE,
1271 }
1272 if (Config.has(PassIsVolatile)) {
1273 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1274 "Flag indicating a volatile store.", IRTArg::NONE,
1275 isVolatile));
1276 }
1277
1278 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1279 IConf.addChoice(*this, IIRB.Ctx);
1280}
1281
1284 auto &SI = cast<StoreInst>(V);
1285 return SI.getPointerOperand();
1286}
1287
1290 auto &SI = cast<StoreInst>(V);
1291 SI.setOperand(SI.getPointerOperandIndex(), &NewV);
1292 return &SI;
1293}
1294
1297 auto &SI = cast<StoreInst>(V);
1298 return getCI(&Ty, SI.getPointerAddressSpace());
1299}
1300
1302 InstrumentationConfig &IConf,
1304 auto &SI = cast<StoreInst>(V);
1305 return IConf.getBasePointerInfo(*SI.getPointerOperand(), IIRB);
1306}
1307
1310 auto &SI = cast<StoreInst>(V);
1311 return SI.getValueOperand();
1312}
1313
1316 auto &SI = cast<StoreInst>(V);
1317 auto &DL = SI.getDataLayout();
1318 return getCI(&Ty, DL.getTypeStoreSize(SI.getValueOperand()->getType()));
1319}
1320
1323 auto &SI = cast<StoreInst>(V);
1324 return getCI(&Ty, SI.getAlign().value());
1325}
1326
1329 auto &SI = cast<StoreInst>(V);
1330 return getCI(&Ty, SI.getValueOperand()->getType()->getTypeID());
1331}
1332
1334 InstrumentationConfig &IConf,
1336 auto &SI = cast<StoreInst>(V);
1337 return getSubTypeID(*SI.getValueOperand()->getType(), Ty);
1338}
1339
1341 InstrumentationConfig &IConf,
1343 auto &SI = cast<StoreInst>(V);
1344 return getCI(&Ty, uint64_t(SI.getOrdering()));
1345}
1346
1349 auto &SI = cast<StoreInst>(V);
1350 return getCI(&Ty, uint64_t(SI.getSyncScopeID()));
1351}
1352
1355 auto &SI = cast<StoreInst>(V);
1356 return getCI(&Ty, SI.isVolatile());
1357}
1358
1360 ConfigTy *UserConfig) {
1362 if (UserConfig)
1363 Config = *UserConfig;
1364 if (Config.has(PassPointer)) {
1365 IRTArgs.push_back(
1366 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1367 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1368 : IRTArg::NONE),
1370 }
1371 if (Config.has(PassPointerAS)) {
1372 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1373 "The address space of the accessed pointer.",
1375 }
1376 if (Config.has(PassBasePointerInfo)) {
1377 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1378 "The runtime provided base pointer info.",
1380 }
1381 if (!IsPRE && Config.has(PassValue)) {
1382 IRTArgs.push_back(
1383 IRTArg(getValueType(IIRB), "value", "The loaded value.",
1384 Config.has(ReplaceValue)
1387 : IRTArg::NONE)
1388 : IRTArg::NONE,
1389 getValue, Config.has(ReplaceValue) ? replaceValue : nullptr));
1390 }
1391 if (Config.has(PassValueSize)) {
1392 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1393 "The size of the loaded value.", IRTArg::NONE,
1394 getValueSize));
1395 }
1396 if (Config.has(PassAlignment)) {
1397 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1398 "The known access alignment.", IRTArg::NONE,
1399 getAlignment));
1400 }
1401 if (Config.has(PassValueTypeId)) {
1402 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1403 "The type id of the loaded value.", IRTArg::TYPEID,
1405 }
1406 if (Config.has(PassValueSubTypeId)) {
1407 IRTArgs.push_back(IRTArg(
1408 IIRB.Int32Ty, "value_sub_type_id",
1409 "The sub type id of the loaded value (for arrays and vectors, or -1).",
1411 }
1412 if (Config.has(PassAtomicityOrdering)) {
1413 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1414 "The atomicity ordering of the load.",
1416 }
1417 if (Config.has(PassSyncScopeId)) {
1418 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1419 "The sync scope id of the load.", IRTArg::NONE,
1421 }
1422 if (Config.has(PassIsVolatile)) {
1423 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1424 "Flag indicating a volatile load.", IRTArg::NONE,
1425 isVolatile));
1426 }
1427
1428 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1429 IConf.addChoice(*this, IIRB.Ctx);
1430}
1431
1434 auto &LI = cast<LoadInst>(V);
1435 return LI.getPointerOperand();
1436}
1437
1440 auto &LI = cast<LoadInst>(V);
1441 LI.setOperand(LI.getPointerOperandIndex(), &NewV);
1442 return &LI;
1443}
1444
1447 auto &LI = cast<LoadInst>(V);
1448 return getCI(&Ty, LI.getPointerAddressSpace());
1449}
1450
1452 InstrumentationConfig &IConf,
1454 auto &LI = cast<LoadInst>(V);
1455 return IConf.getBasePointerInfo(*LI.getPointerOperand(), IIRB);
1456}
1457
1460 return &V;
1461}
1462
1465 auto &LI = cast<LoadInst>(V);
1466 auto &DL = LI.getDataLayout();
1467 return getCI(&Ty, DL.getTypeStoreSize(LI.getType()));
1468}
1469
1472 auto &LI = cast<LoadInst>(V);
1473 return getCI(&Ty, LI.getAlign().value());
1474}
1475
1478 auto &LI = cast<LoadInst>(V);
1479 return getCI(&Ty, LI.getType()->getTypeID());
1480}
1481
1483 InstrumentationConfig &IConf,
1485 auto &LI = cast<LoadInst>(V);
1486 return getSubTypeID(*LI.getType(), Ty);
1487}
1488
1490 InstrumentationConfig &IConf,
1492 auto &LI = cast<LoadInst>(V);
1493 return getCI(&Ty, uint64_t(LI.getOrdering()));
1494}
1495
1498 auto &LI = cast<LoadInst>(V);
1499 return getCI(&Ty, uint64_t(LI.getSyncScopeID()));
1500}
1501
1504 auto &LI = cast<LoadInst>(V);
1505 return getCI(&Ty, LI.isVolatile());
1506}
1507
1509 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1510 if (UserConfig)
1511 Config = *UserConfig;
1512 if (Config.has(PassPointer))
1513 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer",
1514 "The base pointer in question.",
1516 if (Config.has(PassPointerKind))
1517 IRTArgs.push_back(IRTArg(
1518 IIRB.Int32Ty, "base_pointer_kind",
1519 "The base pointer kind (argument, global, instruction, unknown).",
1521 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1522 IConf.addChoice(*this, IIRB.Ctx);
1523}
1524
1526 InstrumentationConfig &IConf,
1528 if (isa<Argument>(V))
1529 return getCI(&Ty, 0);
1530 if (isa<GlobalValue>(V))
1531 return getCI(&Ty, 1);
1532 if (isa<Instruction>(V))
1533 return getCI(&Ty, 2);
1534 return getCI(&Ty, 3);
1535}
1536
1538 ConfigTy *UserConfig) {
1539 if (UserConfig)
1540 Config = *UserConfig;
1541
1542 if (Config.has(PassName))
1543 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "module_name",
1544 "The module/translation unit name.",
1546 if (Config.has(PassTargetTriple))
1547 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "target_triple", "The target triple.",
1549
1550 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1551 IConf.addChoice(*this, IIRB.Ctx);
1552}
1555 // V is a constructor or destructor of the module we can place code in.
1556 auto &Fn = cast<Function>(V);
1557 return IConf.getGlobalString(Fn.getParent()->getName(), IIRB);
1558}
1560 InstrumentationConfig &IConf,
1562 // V is a constructor or destructor of the module we can place code in.
1563 auto &Fn = cast<Function>(V);
1564 return IConf.getGlobalString(Fn.getParent()->getTargetTriple().getTriple(),
1565 IIRB);
1566}
1567
1569 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1570 if (UserConfig)
1571 Config = *UserConfig;
1573 if (Config.has(PassAddress))
1574 IRTArgs.push_back(IRTArg(
1575 IIRB.PtrTy, "address",
1576 "The address of the global (replaceable for definitions).",
1579 if (Config.has(PassAS))
1580 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "address_space",
1581 "The address space of the global.", IRTArg::NONE,
1582 getAS));
1583 if (Config.has(PassDeclaredSize))
1584 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "declared_size",
1585 "The size of the declared type of the global.",
1587 if (Config.has(PassAlignment))
1588 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1589 "The allocation alignment.", IRTArg::NONE,
1590 getAlignment));
1591 if (Config.has(PassName))
1592 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The name of the global.",
1594 if (Config.has(PassInitialValue))
1595 IRTArgs.push_back(IRTArg(
1596 IIRB.Int64Ty, "initial_value", "The initial value of the global.",
1599 if (Config.has(PassIsConstant))
1600 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_constant",
1601 "Flag to indicate constant globals.", IRTArg::NONE,
1602 isConstant));
1603 if (Config.has(PassIsDefinition))
1604 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_definition",
1605 "Flag to indicate global definitions.",
1607 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1608 IConf.addChoice(*this, IIRB.Ctx);
1609}
1613 if (GV.getAddressSpace())
1614 return ConstantExpr::getAddrSpaceCast(&GV, IIRB.PtrTy);
1615 return &GV;
1616}
1618 InstrumentationConfig &IConf,
1621
1622 GlobalVariable *ShadowGV = nullptr;
1623 auto ShadowName = IConf.getRTName("shadow.", GV.getName());
1624 auto &DL = GV.getDataLayout();
1625 if (GV.isDeclaration()) {
1626 ShadowGV = new GlobalVariable(*GV.getParent(), GV.getType(), false,
1628 ShadowName, &GV, GV.getThreadLocalMode(),
1629 DL.getDefaultGlobalsAddressSpace());
1630 } else {
1631 ShadowGV = new GlobalVariable(
1632 *GV.getParent(), NewV.getType(), false, GV.getLinkage(),
1633 PoisonValue::get(NewV.getType()), ShadowName, &GV);
1634 IIRB.IRB.CreateStore(&NewV, ShadowGV);
1635 }
1636
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 SmallPtrSet<Use *, 8> Visited;
1687 while (!Worklist.empty()) {
1688 Use *U = Worklist.pop_back_val();
1689 if (!Done.insert(U).second)
1690 continue;
1691 MakeInstForConst(*U);
1692 auto *I = dyn_cast<Instruction>(U->getUser());
1693 if (!I) {
1694 append_range(Worklist, make_pointer_range(U->getUser()->uses()));
1695 continue;
1696 }
1697 if (IIRB.NewInsts.lookup(I) == IIRB.Epoch)
1698 continue;
1700 continue;
1701 if (auto *II = dyn_cast<IntrinsicInst>(I))
1702 if (II->getIntrinsicID() == Intrinsic::eh_typeid_for)
1703 continue;
1704 if (I->getParent())
1705 InsertConsts(I, *U);
1706 }
1707
1708 for (auto &It : ConstToInstMap)
1709 if (It.second)
1710 It.second->deleteValue();
1711
1712 return &V;
1713}
1717 return getCI(&Ty, GV.getAddressSpace());
1718}
1720 InstrumentationConfig &IConf,
1723 MaybeAlign Alignment = GV.getAlign();
1724 return getCI(&Ty, Alignment ? Alignment->value() : 0);
1725}
1727 InstrumentationConfig &IConf,
1730 auto &DL = GV.getDataLayout();
1731 return getCI(&Ty, DL.getTypeAllocSize(GV.getValueType()));
1732}
1734 InstrumentationConfig &IConf,
1737 return IConf.getGlobalString(GV.getName(), IIRB);
1738}
1749 return getCI(&Ty, GV.isConstant());
1750}
1752 InstrumentationConfig &IConf,
1755 return getCI(&Ty, !GV.isDeclaration());
1756}
1757
1758/// CastIO
1759/// {
1761 ConfigTy *UserConfig) {
1762 if (UserConfig)
1763 Config = *UserConfig;
1765 if (Config.has(PassInput))
1766 IRTArgs.push_back(
1767 IRTArg(IIRB.Int64Ty, "input", "Input value of the cast.",
1770 : IRTArg::NONE),
1771 getInput));
1772 if (Config.has(PassInputTypeId))
1773 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_type_id",
1774 "The type id of the input value.", IRTArg::TYPEID,
1776 if (Config.has(PassInputSubTypeId))
1777 IRTArgs.push_back(IRTArg(
1778 IIRB.Int32Ty, "input_sub_type_id",
1779 "The sub type id of the input value (for arrays and vectors, or -1).",
1781 if (Config.has(PassInputSize))
1782 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_size",
1783 "The size of the input value.", IRTArg::NONE,
1784 getInputSize));
1785 if (!IsPRE && Config.has(PassResult))
1786 IRTArgs.push_back(
1787 IRTArg(IIRB.Int64Ty, "result", "Result of the cast.",
1790 : IRTArg::NONE),
1791 getValue, Config.has(ReplaceResult) ? replaceValue : nullptr));
1792 if (Config.has(PassResultTypeId))
1793 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_type_id",
1794 "The type id of the result value.", IRTArg::TYPEID,
1796 if (Config.has(PassResultSubTypeId))
1797 IRTArgs.push_back(IRTArg(
1798 IIRB.Int32Ty, "result_sub_type_id",
1799 "The sub type id of the result value (for arrays and vectors, or -1).",
1801 if (Config.has(PassResultSize))
1802 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_size",
1803 "The size of the result value.", IRTArg::NONE,
1804 getResultSize));
1805 if (Config.has(PassOpcode))
1806 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode",
1807 "The opcode of the cast instruction.",
1809
1810 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1811 IConf.addChoice(*this, IIRB.Ctx);
1812}
1813
1816 auto &CI = cast<CastInst>(V);
1817 return CI.getOperand(0);
1818}
1819
1822 auto &CI = cast<CastInst>(V);
1823 return getCI(&Ty, CI.getSrcTy()->getTypeID());
1824}
1825
1827 InstrumentationConfig &IConf,
1829 auto &CI = cast<CastInst>(V);
1830 return getSubTypeID(*CI.getSrcTy(), Ty);
1831}
1832
1835 auto &CI = cast<CastInst>(V);
1836 auto &DL = CI.getDataLayout();
1837 return getCI(&Ty, DL.getTypeStoreSize(CI.getSrcTy()));
1838}
1839
1842 auto &CI = cast<CastInst>(V);
1843 return getCI(&Ty, CI.getDestTy()->getTypeID());
1844}
1845
1847 InstrumentationConfig &IConf,
1849 auto &CI = cast<CastInst>(V);
1850 return getSubTypeID(*CI.getDestTy(), Ty);
1851}
1852
1855 auto &CI = cast<CastInst>(V);
1856 auto &DL = CI.getDataLayout();
1857 return getCI(&Ty, DL.getTypeStoreSize(CI.getDestTy()));
1858}
1859///}
1860
1863 auto &I = cast<Instruction>(V);
1864 uint64_t Flag = NUMERIC_FLAG_NONE;
1865
1866 switch (I.getOpcode()) {
1867 case Instruction::Add:
1868 case Instruction::Sub:
1869 case Instruction::Mul:
1870 case Instruction::Shl:
1871 if (I.hasNoSignedWrap())
1873 if (I.hasNoUnsignedWrap())
1875 break;
1876 case Instruction::FAdd:
1877 case Instruction::FSub:
1878 case Instruction::FMul:
1879 case Instruction::FDiv:
1880 case Instruction::FNeg:
1881 if (I.hasNoNaNs())
1883 if (I.hasNoInfs())
1885 if (I.hasNoSignedZeros())
1887 break;
1888 case Instruction::AShr:
1889 case Instruction::LShr:
1890 case Instruction::SDiv:
1891 case Instruction::UDiv:
1892 if (I.isExact())
1893 Flag |= NUMERIC_FLAG_IS_EXACT;
1894 break;
1895 }
1896
1897 if (auto *DI = dyn_cast<PossiblyDisjointInst>(&V))
1898 if (DI->isDisjoint())
1900
1901 return getCI(&Ty, Flag);
1902}
1903
1912
1914 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1915 if (UserConfig)
1916 Config = UserConfig;
1918 const auto ValArgOpts =
1921 if (Config.has(PassTypeId))
1922 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "type_id",
1923 "The operation's type id.", IRTArg::TYPEID,
1924 getTypeId));
1925 if (Config.has(PassSubTypeId))
1926 IRTArgs.push_back(
1927 IRTArg(IIRB.Int32Ty, "sub_type_id",
1928 "The operation's sub type id (for arrays and vectors, or -1).",
1930 if (Config.has(PassSize))
1931 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "size", "The operation's type size.",
1933 if (Config.has(PassOpcode))
1934 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
1936 if (Config.has(PassLeft))
1937 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
1938 "The operation's left operand.", ValArgOpts,
1940 if (Config.has(PassRight))
1941 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
1942 "The operation's right operand. This value is "
1943 "poison for unary operations.",
1944 ValArgOpts, getRightOperand));
1945 if (!IsPRE && Config.has(PassResult))
1946 IRTArgs.push_back(
1947 IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
1948 IRTArg::REPLACABLE | ValArgOpts, getValue,
1949 Config.has(ReplaceResult) ? replaceValue : nullptr));
1950 if (Config.has(PassFlags))
1951 IRTArgs.push_back(
1952 IRTArg(IIRB.Int64Ty, "flags",
1953 "A bitmask value signaling which instruction flags are present.",
1955 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1956 addFlagNames();
1957 IConf.addChoice(*this, IIRB.Ctx);
1958}
1959
1961 InstrumentationConfig &IConf,
1963 auto &I = cast<Instruction>(V);
1964 return getCI(&Ty, I.getOperand(0)->getType()->getTypeID());
1965}
1966
1968 InstrumentationConfig &IConf,
1970 auto &I = cast<Instruction>(V);
1971 auto &DL = I.getDataLayout();
1972 return getCI(&Ty, DL.getTypeStoreSize(I.getOperand(0)->getType()));
1973}
1974
1977 auto *CI = dyn_cast<CmpInst>(&V);
1978 return getCI(&Ty, CI->getPredicate());
1979}
1980
1987
1990 auto &I = cast<Instruction>(V);
1991 uint64_t Flag = NUMERIC_FLAG_NONE;
1992
1993 switch (I.getOpcode()) {
1994 case Instruction::ICmp:
1995 if (dyn_cast<ICmpInst>(&V)->hasSameSign())
1996 Flag |= COMPARE_FLAG_SAMESIGN;
1997 break;
1998 case Instruction::FCmp:
1999 if (I.hasNoNaNs())
2001 if (I.hasNoInfs())
2003 if (I.hasNoSignedZeros())
2005 break;
2006 }
2007
2008 return getCI(&Ty, Flag);
2009}
2010
2012 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
2013 if (UserConfig)
2014 Config = UserConfig;
2016 const auto OperandArgOpts =
2019 if (Config.has(PassOpTypeId))
2020 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "operand_type_id",
2021 "The operand type id.", IRTArg::NONE,
2023 if (Config.has(PassOpSize))
2024 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "operand_size",
2025 "The operand type size.", IRTArg::NONE,
2027 if (Config.has(PassOpcode))
2028 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
2030 if (Config.has(PassPredicate))
2031 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "predicate",
2032 "The comparison predicate ID.", IRTArg::NONE,
2033 getPredicate));
2034 if (Config.has(PassLeft))
2035 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
2036 "The comparison's left operand.", OperandArgOpts,
2038 if (Config.has(PassRight))
2039 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
2040 "The comparison's right operand.", OperandArgOpts,
2042 if (!IsPRE && Config.has(PassResultSize))
2043 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_type_id",
2044 "The result value's type ID.", IRTArg::NONE,
2045 getTypeId));
2046 if (!IsPRE && Config.has(PassResultSize))
2047 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_size",
2048 "Size of the result value.", IRTArg::NONE,
2049 getTypeSize));
2050 if (!IsPRE && Config.has(PassResult))
2051 IRTArgs.push_back(
2052 IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
2055 : IRTArg::NONE),
2056 getValue, Config.has(ReplaceResult) ? replaceValue : nullptr));
2057 if (Config.has(PassFlags))
2058 IRTArgs.push_back(
2059 IRTArg(IIRB.Int64Ty, "flags",
2060 "A bitmask value signaling which instruction flags are present.",
2062 addFlagNames();
2063 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
2064 IConf.addChoice(*this, IIRB.Ctx);
2065}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
unsigned 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 getFirstNonPHIOrDbgOrAlloca() const
Returns an iterator to the first instruction in this block that is not a PHINode, a debug intrinsic,...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Diagnostic information for IR instrumentation reporting.
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h: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:360
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:356
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:734
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:71
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:336
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:561
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:319
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