LLVM 23.0.0git
Instrumentor.cpp
Go to the documentation of this file.
1//===-- Instrumentor.cpp - Highly configurable instrumentation pass -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// The implementation of the Instrumentor, a highly configurable instrumentation
10// pass.
11//
12//===----------------------------------------------------------------------===//
13
17
19#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/StringMap.h"
24#include "llvm/ADT/iterator.h"
27#include "llvm/IR/Constant.h"
28#include "llvm/IR/Constants.h"
29#include "llvm/IR/DataLayout.h"
32#include "llvm/IR/Function.h"
33#include "llvm/IR/IRBuilder.h"
34#include "llvm/IR/InstrTypes.h"
35#include "llvm/IR/Instruction.h"
38#include "llvm/IR/Intrinsics.h"
39#include "llvm/IR/LLVMContext.h"
40#include "llvm/IR/Metadata.h"
41#include "llvm/IR/Module.h"
42#include "llvm/IR/PassManager.h"
43#include "llvm/IR/Verifier.h"
47#include "llvm/Support/Regex.h"
51
52#include <cassert>
53#include <cstdint>
54#include <functional>
55#include <iterator>
56#include <memory>
57#include <string>
58#include <system_error>
59#include <type_traits>
60
61using namespace llvm;
62using namespace llvm::instrumentor;
63
64#define DEBUG_TYPE "instrumentor"
65
66namespace {
67
68/// The user option to specify an output JSON file to write the configuration.
69static cl::opt<std::string> OutputConfigFile(
70 "instrumentor-write-config-file",
72 "Write the instrumentor configuration into the specified JSON file"),
73 cl::init(""));
74
75/// The user option to specify input JSON files to read the configuration from.
77 ConfigFiles("instrumentor-read-config-files",
78 cl::desc("Read the instrumentor configuration from the "
79 "specified JSON files (comma separated)"),
81
82/// The user option to specify an input file to read the configuration file
83/// paths from.
84static cl::opt<std::string> ConfigPathsFile(
85 "instrumentor-read-config-paths-file",
86 cl::desc("Read the instrumentor configuration file "
87 "paths from the specified file (newline separated)"),
88 cl::init(""));
89
90/// Set the debug location, if not set, after changing the insertion point of
91/// the IR builder \p IRB.
92template <typename IRBuilderTy> void ensureDbgLoc(IRBuilderTy &IRB) {
93 if (IRB.getCurrentDebugLocation())
94 return;
95 auto *BB = IRB.GetInsertBlock();
96 if (auto *SP = BB->getParent()->getSubprogram())
97 IRB.SetCurrentDebugLocation(DILocation::get(BB->getContext(), 0, 0, SP));
98}
99
100/// Attempt to cast \p V to type \p Ty using only bit-preserving casts.
101/// This ensures that floating-point values are converted via bitcast (not
102/// fptosi/fptoui) to preserve their exact bit representation.
103template <typename IRBTy>
104Value *tryToCast(IRBTy &IRB, Value *V, Type *Ty, const DataLayout &DL,
105 bool AllowTruncate = false) {
106 if (!V)
107 return Constant::getAllOnesValue(Ty);
108 Type *VTy = V->getType();
109 if (VTy == Ty)
110 return V;
111 if (VTy->isAggregateType())
112 return V;
113 TypeSize RequestedSize = DL.getTypeSizeInBits(Ty);
114 TypeSize ValueSize = DL.getTypeSizeInBits(VTy);
115 bool ShouldTruncate = RequestedSize < ValueSize;
116 if (ShouldTruncate && !AllowTruncate)
117 return V;
118 if (ShouldTruncate && AllowTruncate) {
119 // First convert to integer of the same size if needed.
120 Value *IntV = V;
121 if (VTy->isFloatingPointTy())
122 IntV = IRB.CreateBitCast(V, IRB.getIntNTy(ValueSize));
123 return tryToCast(IRB,
124 IRB.CreateIntCast(IntV, IRB.getIntNTy(RequestedSize),
125 /*IsSigned=*/false),
126 Ty, DL, AllowTruncate);
127 }
128 if (VTy->isPointerTy() && Ty->isPointerTy())
129 return IRB.CreatePointerBitCastOrAddrSpaceCast(V, Ty);
130 if (VTy->isIntegerTy() && Ty->isIntegerTy())
131 return IRB.CreateIntCast(V, Ty, /*IsSigned=*/false);
132 // Use bit-preserving casts for floating-point values: convert float to int
133 // of the same size via bitcast, then extend/truncate the integer if needed.
134 if (VTy->isFloatingPointTy() && Ty->isIntOrPtrTy()) {
135 return tryToCast(IRB, IRB.CreateBitCast(V, IRB.getIntNTy(ValueSize)), Ty,
136 DL, AllowTruncate);
137 }
138 // When converting int to float, never use sitofp/uitofp as they perform value
139 // conversion, not bit-preserving cast.
140 if (VTy->isIntegerTy() && Ty->isFloatingPointTy()) {
141 if (ValueSize == RequestedSize)
142 return IRB.CreateBitCast(V, Ty);
143 return tryToCast(
144 IRB,
145 IRB.CreateIntCast(V, IRB.getIntNTy(RequestedSize), /*IsSigned=*/false),
146 Ty, DL, AllowTruncate);
147 }
148 return IRB.CreateBitOrPointerCast(V, Ty);
149}
150
151/// Get a constant integer/boolean of type \p IT and value \p Val.
152template <typename Ty>
153Constant *getCI(Type *IT, Ty Val, bool IsSigned = false) {
154 return ConstantInt::get(IT, Val, IsSigned);
155}
156
157/// The core of the instrumentor pass, which instruments the module as the
158/// instrumentation configuration mandates.
159class InstrumentorImpl final {
160public:
161 /// Construct an instrumentor implementation using the configuration \p IConf.
162 InstrumentorImpl(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
163 Module &M)
164 : IConf(IConf), M(M), IIRB(IIRB) {}
165
166 /// Instrument the module, public entry point.
167 bool instrument();
168
169 // Reset the state to allow reuse of the instrumentor with a different
170 // configuration.
171 void clear() {
172 InstChoicesPRE.clear();
173 InstChoicesPOST.clear();
174 ParsedFunctionRegex = Regex();
175 }
176
177private:
178 /// Indicate if the module should be instrumented based on the target.
179 bool shouldInstrumentTarget();
180
181 /// Indicate if the function \p Fn should be instrumented.
182 bool shouldInstrumentFunction(Function &Fn);
183 bool shouldInstrumentGlobalVariable(GlobalVariable &GV);
184
185 /// Instrument instruction \p I if needed, and use the argument caches in \p
186 /// ICaches.
187 bool instrumentInstruction(Instruction &I, InstrumentationCaches &ICaches);
188
189 /// Instrument function \p Fn.
190 bool instrumentFunction(Function &Fn);
191 bool instrumentModule();
192
193 /// The instrumentation opportunities for instructions indexed by
194 /// their opcode.
196 InstChoicesPOST;
197
198 /// The instrumentor configuration.
200
201 /// The function regex filter, if any.
202 Regex ParsedFunctionRegex;
203
204 /// The underlying module.
205 Module &M;
206
207protected:
208 /// A special IR builder that keeps track of the inserted instructions.
210};
211
212} // end anonymous namespace
213
215 if (!Str.empty()) {
216 Regex RX(Str);
217 std::string ErrMsg;
218 if (!RX.isValid(ErrMsg)) {
220 Twine("failed to parse ") + Name + " regex: " + ErrMsg, DS_Error));
221 return Regex();
222 }
223 return RX;
224 }
225 return Regex();
226}
227
228bool InstrumentorImpl::shouldInstrumentTarget() {
229 const Triple &T = M.getTargetTriple();
230 const bool IsGPU = T.isAMDGPU() || T.isNVPTX();
231
232 bool RegexMatches = true;
233 Regex RX = createRegex(IConf.TargetRegex->getString(), "target", IIRB.Ctx);
234 if (RX.isValid())
235 RegexMatches = RX.match(T.str());
236
237 // Only instrument the module if the target has to be instrumented.
238 return ((IsGPU && IConf.GPUEnabled->getBool()) ||
239 (!IsGPU && IConf.HostEnabled->getBool())) &&
240 RegexMatches;
241}
242
243bool InstrumentorImpl::shouldInstrumentFunction(Function &Fn) {
244 if (Fn.isDeclaration())
245 return false;
246 bool RegexMatches = true;
247 if (ParsedFunctionRegex.isValid())
248 RegexMatches = ParsedFunctionRegex.match(Fn.getName());
249 return (RegexMatches && !Fn.getName().starts_with(IConf.getRTName())) ||
250 Fn.hasFnAttribute("instrument");
251}
252
253bool InstrumentorImpl::shouldInstrumentGlobalVariable(GlobalVariable &GV) {
254 return !GV.getName().starts_with("llvm.") &&
255 !GV.getName().starts_with(IConf.getRTName());
256}
257
258bool InstrumentorImpl::instrumentInstruction(Instruction &I,
259 InstrumentationCaches &ICaches) {
260 bool Changed = false;
261
262 // Skip instrumentation instructions.
263 if (IIRB.NewInsts.contains(&I))
264 return Changed;
265
266 // Count epochs eagerly.
267 ++IIRB.Epoch;
268
269 Value *IPtr = &I;
270 if (auto *IO = InstChoicesPRE.lookup(I.getOpcode())) {
271 IIRB.IRB.SetInsertPoint(&I);
272 ensureDbgLoc(IIRB.IRB);
273 IO->instrument(IPtr, Changed, IConf, IIRB, ICaches);
274 }
275
276 if (auto *IO = InstChoicesPOST.lookup(I.getOpcode())) {
277 IIRB.IRB.SetInsertPoint(I.getNextNode());
278 ensureDbgLoc(IIRB.IRB);
279 IO->instrument(IPtr, Changed, IConf, IIRB, ICaches);
280 }
281 IIRB.returnAllocas();
282
283 return Changed;
284}
285
286bool InstrumentorImpl::instrumentFunction(Function &Fn) {
287 bool Changed = false;
288 if (!shouldInstrumentFunction(Fn))
289 return Changed;
290
291 InstrumentationCaches ICaches;
293 ReversePostOrderTraversal<Function *> RPOT(&Fn);
294 for (auto &It : RPOT) {
295 for (auto &I : *It)
296 Changed |= instrumentInstruction(I, ICaches);
297
298 auto *TI = It->getTerminator();
299 if (!TI->getNumSuccessors())
300 FinalTIs.push_back(TI);
301 }
302
303 Value *FPtr = &Fn;
304 for (auto &[Name, IO] :
306 if (!IO->Enabled)
307 continue;
308 // Count epochs eagerly.
309 ++IIRB.Epoch;
310
311 IIRB.IRB.SetInsertPoint(
312 cast<Function>(FPtr)->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
313 ensureDbgLoc(IIRB.IRB);
314 IO->instrument(FPtr, Changed, IConf, IIRB, ICaches);
315 IIRB.returnAllocas();
316 }
317
318 for (auto &[Name, IO] :
320 if (!IO->Enabled)
321 continue;
322 // Count epochs eagerly.
323 ++IIRB.Epoch;
324
325 for (Instruction *FinalTI : FinalTIs) {
326 IIRB.IRB.SetInsertPoint(FinalTI);
327 ensureDbgLoc(IIRB.IRB);
328 IO->instrument(FPtr, Changed, IConf, IIRB, ICaches);
329 IIRB.returnAllocas();
330 }
331 }
332 return Changed;
333}
334
335bool InstrumentorImpl::instrumentModule() {
337 Globals.reserve(M.global_size());
338 for (GlobalVariable &GV : M.globals()) {
339 // llvm.metadata contains globals such as llvm.used.
340 if (GV.getSection() == "llvm.metadata" ||
341 GV.getName() == "llvm.global_dtors" ||
342 GV.getName() == "llvm.global_ctors")
343 continue;
344 Globals.push_back(&GV);
345 }
346
347 auto CreateYtor = [&](bool Ctor) {
348 Function *YtorFn = Function::Create(
349 FunctionType::get(IIRB.VoidTy, false), GlobalValue::PrivateLinkage,
350 IConf.getRTName(Ctor ? "ctor" : "dtor", ""), M);
351
352 auto *EntryBB = BasicBlock::Create(IIRB.Ctx, "entry", YtorFn);
353 IIRB.IRB.SetInsertPoint(EntryBB, EntryBB->begin());
354 ensureDbgLoc(IIRB.IRB);
355 IIRB.IRB.CreateRetVoid();
356
357 if (Ctor)
358 appendToGlobalCtors(M, YtorFn, 1000);
359 else
360 appendToGlobalDtors(M, YtorFn, 1000);
361 return YtorFn;
362 };
363
364 InstrumentationCaches ICaches;
365
366 Function *CtorFn = nullptr, *DtorFn = nullptr;
367 bool Changed = false;
370 bool IsPRE = InstrumentationLocation::isPRE(Loc);
371 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
372 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
373 auto *IO = ChoiceIt.second;
374 if (!IO->Enabled)
375 continue;
376 if (!YtorFn) {
377 YtorFn = CreateYtor(IsPRE);
378 Changed = true;
379 }
380 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
381 ensureDbgLoc(IIRB.IRB);
382 Value *YtorPtr = YtorFn;
383
384 // Count epochs eagerly.
385 ++IIRB.Epoch;
386
387 IO->instrument(YtorPtr, Changed, IConf, IIRB, ICaches);
388 IIRB.returnAllocas();
389 }
390 }
391
394 bool IsPRE = InstrumentationLocation::isPRE(Loc);
395 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
396 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
397 auto *IO = ChoiceIt.second;
398 if (!IO->Enabled)
399 continue;
400 if (!YtorFn) {
401 YtorFn = CreateYtor(IsPRE);
402 Changed = true;
403 }
404 for (GlobalVariable *GV : Globals) {
405 if (!shouldInstrumentGlobalVariable(*GV))
406 continue;
407 if (IsPRE)
408 IIRB.IRB.SetInsertPoint(YtorFn->getEntryBlock().getTerminator());
409 else
410 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
411 ensureDbgLoc(IIRB.IRB);
412 Value *GVPtr = GV;
413
414 // Count epochs eagerly.
415 ++IIRB.Epoch;
416
417 IO->instrument(GVPtr, Changed, IConf, IIRB, ICaches);
418 IIRB.returnAllocas();
419 }
420 }
421 }
422
423 return Changed;
424}
425
426bool InstrumentorImpl::instrument() {
427 bool Changed = false;
428 if (!shouldInstrumentTarget())
429 return Changed;
430
431 StringRef FunctionRegexStr = IConf.FunctionRegex->getString();
432 ParsedFunctionRegex = createRegex(FunctionRegexStr, "function", IIRB.Ctx);
433
434 // Helper to register an IO for all its opcodes.
435 auto RegisterForAllOpcodes = [](auto &InstChoices,
436 InstrumentationOpportunity *IO) {
437 ArrayRef<unsigned> Opcodes = IO->getAllOpcodes();
438 // Register for all opcodes.
439 for (unsigned Opcode : Opcodes)
440 InstChoices[Opcode] = IO;
441 };
442
443 for (auto &[Name, IO] :
445 if (IO->Enabled)
446 RegisterForAllOpcodes(InstChoicesPRE, IO);
447 for (auto &[Name, IO] :
449 if (IO->Enabled)
450 RegisterForAllOpcodes(InstChoicesPOST, IO);
451 Changed |= instrumentModule();
452
453 for (Function &Fn : M)
454 Changed |= instrumentFunction(Fn);
455
456 return Changed;
457}
458
460 InstrumentationConfig *IC,
461 InstrumentorIRBuilderTy *IIRB)
462 : FS(FS), UserIConf(IC), UserIIRB(IIRB) {
463 if (!FS)
464 this->FS = vfs::getRealFileSystem();
465}
466
467PreservedAnalyses InstrumentorPass::run(Module &M, InstrumentationConfig &IConf,
469 bool ReadConfig) {
470 bool Changed = false;
471 InstrumentorImpl Impl(IConf, IIRB, M);
472
473 // If this is a configuration driven run, iterate over all configurations
474 // provided by the user, if not, use the config as is and run the instrumentor
475 // once.
476 if (ReadConfig)
477 readConfigPathsFile(ConfigPathsFile, ConfigFiles, IIRB.Ctx, *FS);
478
479 bool MultipleConfigs = ConfigFiles.size() > 1;
480 unsigned Idx = 0;
481 do {
482 std::string ConfigFile =
483 ReadConfig && !ConfigFiles.empty() ? ConfigFiles[Idx] : "";
484
485 // Initialize the config to the base state but keep the caches around.
486 Impl.clear();
487 IConf.init(IIRB);
488
489 if (!readConfigFromJSON(IConf, ConfigFile, IIRB.Ctx, *FS))
490 continue;
491
492 writeConfigToJSON(IConf,
493 MultipleConfigs
494 ? OutputConfigFile + "." + std::to_string(Idx)
495 : OutputConfigFile,
496 IIRB.Ctx);
497
498 printRuntimeStub(IConf, IConf.RuntimeStubsFile->getString(), IIRB.Ctx);
499
500 Changed |= Impl.instrument();
501 } while (++Idx < ConfigFiles.size());
502
503 if (!Changed)
504 return PreservedAnalyses::all();
506}
507
509 // Only create them if the user did not provide them.
510 std::unique_ptr<InstrumentationConfig> IConfInt(
511 !UserIConf ? new InstrumentationConfig() : nullptr);
512 std::unique_ptr<InstrumentorIRBuilderTy> IIRBInt(
513 !UserIIRB ? new InstrumentorIRBuilderTy(M) : nullptr);
514
515 auto *IConf = IConfInt ? IConfInt.get() : UserIConf;
516 auto *IIRB = IIRBInt ? IIRBInt.get() : UserIIRB;
517
518 auto PA = run(M, *IConf, *IIRB, !UserIConf);
519
520 assert(!verifyModule(M, &errs()));
521 return PA;
522}
523
524std::unique_ptr<BaseConfigurationOption>
527 bool DefaultValue) {
528 auto BCO =
529 std::make_unique<BaseConfigurationOption>(Name, Description, BOOLEAN);
530 BCO->setBool(DefaultValue);
531 IConf.addBaseChoice(BCO.get());
532 return BCO;
533}
534
535std::unique_ptr<BaseConfigurationOption>
539 StringRef DefaultValue) {
540 auto BCO =
541 std::make_unique<BaseConfigurationOption>(Name, Description, STRING);
542 BCO->setString(DefaultValue);
543 IConf.addBaseChoice(BCO.get());
544 return BCO;
545}
546
548 /// List of all instrumentation opportunities.
549 BasePointerIO::populate(*this, IIRB);
550 ModuleIO::populate(*this, IIRB);
551 GlobalVarIO::populate(*this, IIRB);
552 FunctionIO::populate(*this, IIRB);
553 AllocaIO::populate(*this, IIRB);
554 UnreachableIO::populate(*this, IIRB);
555 LoadIO::populate(*this, IIRB);
556 StoreIO::populate(*this, IIRB);
557 CastIO::populate(*this, IIRB);
558 NumericIO::populate(*this, IIRB);
559}
560
562 LLVMContext &Ctx) {
563 auto *&ICPtr = IChoices[IO.getLocationKind()][IO.getName()];
564 if (ICPtr) {
566 Twine("registered two instrumentation opportunities for the same "
567 "location (") +
568 ICPtr->getName() + Twine(" vs ") + IO.getName() + Twine(")"),
569 DS_Warning));
570 }
571 ICPtr = &IO;
572}
573
574Value *
577 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
578
579 Value *Obj;
580 {
581 Value *&UnderlyingObj = UnderlyingObjsMap[&V];
582 if (!UnderlyingObj)
583 UnderlyingObj = const_cast<Value *>(getUnderlyingObjectAggressive(&V));
584 Obj = UnderlyingObj;
585 }
586
587 Value *&BPI = BasePointerInfoMap[{Obj, Fn}];
588 if (BPI)
589 return BPI;
590
591 auto *BPIO =
593 if (!BPIO || !BPIO->Enabled) {
595 "Base pointer info disabled but required, passing nullptr.",
596 DS_Warning));
597 return BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
598 }
599
601 if (auto *BasePtrI = dyn_cast<Instruction>(Obj)) {
602 std::optional<BasicBlock::iterator> IP =
603 BasePtrI->getInsertionPointAfterDef();
604 if (IP) {
605 IIRB.IRB.SetInsertPoint(*IP);
606 } else {
608 "Base pointer info could not be placed, passing nullptr.",
609 DS_Warning));
610 return BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
611 }
612 } else if (isa<Constant>(Obj) || isa<Argument>(Obj)) {
613 IIRB.IRB.SetInsertPointPastAllocas(IIRB.IRB.GetInsertBlock()->getParent());
614 } else {
615 LLVM_DEBUG(Obj->dump());
616 llvm_unreachable("Unexpected base pointer!");
617 }
618 ensureDbgLoc(IIRB.IRB);
619
620 // Use fresh caches for safety, as this function may be called from
621 // another instrumentation opportunity.
622 bool Changed;
623 InstrumentationCaches ICaches;
624 BPI = BPIO->instrument(Obj, Changed, *this, IIRB, ICaches);
625 IIRB.returnAllocas();
626 if (!BPI)
627 BPI = Constant::getNullValue(BPIO->getRetTy(IIRB.Ctx));
628 return BPI;
629}
630
634 return getCI(&Ty, getIdFromEpoch(IIRB.Epoch));
635}
636
640 return getCI(&Ty, -getIdFromEpoch(IIRB.Epoch), /*IsSigned=*/true);
641}
642
645 if (V.getType()->isVoidTy())
646 return Ty.isVoidTy() ? &V : Constant::getNullValue(&Ty);
647 return tryToCast(IIRB.IRB, &V, &Ty,
648 IIRB.IRB.GetInsertBlock()->getDataLayout());
649}
650
654 if (V.getType()->isVoidTy())
655 return &V;
656
657 auto *NewVCasted = &NewV;
658 if (auto *I = dyn_cast<Instruction>(&NewV)) {
660 IIRB.IRB.SetInsertPoint(I->getNextNode());
661 ensureDbgLoc(IIRB.IRB);
662 NewVCasted = tryToCast(IIRB.IRB, &NewV, V.getType(), IIRB.DL,
663 /*AllowTruncate=*/true);
664 }
665 V.replaceUsesWithIf(NewVCasted, [&](Use &U) {
666 if (IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) == IIRB.Epoch)
667 return false;
668 return !isa<LifetimeIntrinsic>(U.getUser()) && !U.getUser()->isDroppable();
669 });
670
671 return &V;
672}
673
675 Type *RetTy)
676 : IO(IO), RetTy(RetTy) {
677 for (auto &It : IO.IRTArgs) {
678 if (!It.Enabled)
679 continue;
680 NumReplaceableArgs += bool(It.Flags & IRTArg::REPLACABLE);
681 MightRequireIndirection |= It.Flags & IRTArg::POTENTIALLY_INDIRECT;
682 }
685}
686
689 const DataLayout &DL, bool ForceIndirection) {
690 assert(((ForceIndirection && MightRequireIndirection) ||
691 (!ForceIndirection && !RequiresIndirection)) &&
692 "Wrong indirection setting!");
693
694 SmallVector<Type *> ParamTypes;
695 for (auto &It : IO.IRTArgs) {
696 if (!It.Enabled)
697 continue;
698 if (!ForceIndirection || !isPotentiallyIndirect(It)) {
699 ParamTypes.push_back(It.Ty);
700 if (!RetTy && NumReplaceableArgs == 1 && (It.Flags & IRTArg::REPLACABLE))
701 RetTy = It.Ty;
702 continue;
703 }
704
705 // The indirection pointer and the size of the value.
706 ParamTypes.push_back(IIRB.PtrTy);
707 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE))
708 ParamTypes.push_back(IIRB.Int32Ty);
709 }
710 if (!RetTy)
711 RetTy = IIRB.VoidTy;
712
713 return FunctionType::get(RetTy, ParamTypes, /*isVarArg=*/false);
714}
715
719 const DataLayout &DL,
720 InstrumentationCaches &ICaches) {
721 SmallVector<Value *> CallParams;
722
724 auto IP = IIRB.IRB.GetInsertPoint();
725
726 bool ForceIndirection = RequiresIndirection;
727 for (auto &It : IO.IRTArgs) {
728 if (!It.Enabled)
729 continue;
730 auto *&Param = ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
731 if (!Param || It.NoCache)
732 // Avoid passing the caches to the getter.
733 Param = It.GetterCB(*V, *It.Ty, IConf, IIRB);
734 assert(Param);
735
736 if (Param->getType()->isVoidTy()) {
737 Param = Constant::getNullValue(It.Ty);
738 } else if (Param->getType()->isAggregateType() ||
739 DL.getTypeSizeInBits(Param->getType()) >
740 DL.getTypeSizeInBits(It.Ty)) {
741 if (!isPotentiallyIndirect(It)) {
743 Twine("indirection needed for ") + It.Name + Twine(" in ") +
744 IO.getName() +
745 Twine(", but not indicated. Instrumentation is skipped"),
746 DS_Warning));
747 return nullptr;
748 }
749 ForceIndirection = true;
750 } else {
751 Param = tryToCast(IIRB.IRB, Param, It.Ty, DL);
752 }
753 CallParams.push_back(Param);
754 }
755
756 if (ForceIndirection) {
757 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
758
759 unsigned Offset = 0;
760 for (auto &It : IO.IRTArgs) {
761 if (!It.Enabled)
762 continue;
763
764 if (!isPotentiallyIndirect(It)) {
765 ++Offset;
766 continue;
767 }
768 auto *&CallParam = CallParams[Offset++];
769 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE)) {
770 CallParams.insert(&CallParam + 1, IIRB.IRB.getInt32(DL.getTypeStoreSize(
771 CallParam->getType())));
772 Offset += 1;
773 }
774
775 auto *&CachedParam =
776 ICaches.IndirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
777 if (CachedParam) {
778 CallParam = CachedParam;
779 continue;
780 }
781
782 auto *AI = IIRB.getAlloca(Fn, CallParam->getType());
783 IIRB.IRB.CreateStore(CallParam, AI);
784 CallParam = CachedParam = AI;
785 }
786 }
787
788 if (!ForceIndirection)
789 IIRB.IRB.SetInsertPoint(IP);
790 ensureDbgLoc(IIRB.IRB);
791
792 auto *FnTy = createLLVMSignature(IConf, IIRB, DL, ForceIndirection);
793 auto CompleteName =
794 IConf.getRTName(IO.IP.isPRE() ? "pre_" : "post_", IO.getName(),
795 ForceIndirection ? "_ind" : "");
796 auto FC = IIRB.IRB.GetInsertBlock()->getModule()->getOrInsertFunction(
797 CompleteName, FnTy);
798 auto *CI = IIRB.IRB.CreateCall(FC, CallParams);
799 CI->addFnAttr(Attribute::get(IIRB.Ctx, Attribute::WillReturn));
800
801 for (unsigned I = 0, E = IO.IRTArgs.size(); I < E; ++I) {
802 if (!IO.IRTArgs[I].Enabled)
803 continue;
804 if (!isReplacable(IO.IRTArgs[I]))
805 continue;
806 bool IsCustomReplaceable = IO.IRTArgs[I].Flags & IRTArg::REPLACABLE_CUSTOM;
807 Value *NewValue = FnTy->isVoidTy() || IsCustomReplaceable
808 ? ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(),
809 IO.IRTArgs[I].Name}]
810 : CI;
811 assert(NewValue);
812 if (ForceIndirection && !IsCustomReplaceable &&
813 isPotentiallyIndirect(IO.IRTArgs[I])) {
814 auto *Q =
815 ICaches
816 .IndirectArgCache[{IIRB.Epoch, IO.getName(), IO.IRTArgs[I].Name}];
817 NewValue = IIRB.IRB.CreateLoad(V->getType(), Q);
818 }
819 V = IO.IRTArgs[I].SetterCB(*V, *NewValue, IConf, IIRB);
820 }
821 return CI;
822}
823
824template <typename Ty> constexpr static Value *getValue(Ty &ValueOrUse) {
825 if constexpr (std::is_same<Ty, Use>::value)
826 return ValueOrUse.get();
827 else
828 return static_cast<Value *>(&ValueOrUse);
829}
830
831template <typename Range>
834 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
835 auto *I32Ty = IIRB.IRB.getInt32Ty();
836 SmallVector<Constant *> ConstantValues;
839 for (auto &RE : R) {
840 Value *V = getValue(RE);
841 if (!V->getType()->isSized())
842 continue;
843 auto VSize = IIRB.DL.getTypeAllocSize(V->getType());
844 ConstantValues.push_back(getCI(I32Ty, VSize));
845 Types.push_back(I32Ty);
846 ConstantValues.push_back(getCI(I32Ty, V->getType()->getTypeID()));
847 Types.push_back(I32Ty);
848 if (uint32_t MisAlign = VSize % 8) {
849 Types.push_back(ArrayType::get(IIRB.Int8Ty, 8 - MisAlign));
850 ConstantValues.push_back(ConstantArray::getNullValue(Types.back()));
851 }
852 Types.push_back(V->getType());
853 if (auto *C = dyn_cast<Constant>(V)) {
854 ConstantValues.push_back(C);
855 continue;
856 }
857 Values.push_back({V, ConstantValues.size()});
858 ConstantValues.push_back(Constant::getNullValue(V->getType()));
859 }
860 if (Types.empty())
861 return ConstantPointerNull::get(IIRB.PtrTy);
862
863 StructType *STy = StructType::get(Fn->getContext(), Types, /*isPacked=*/true);
864 Constant *Initializer = ConstantStruct::get(STy, ConstantValues);
865
866 GlobalVariable *&GV = IConf.ConstantGlobalsCache[Initializer];
867 if (!GV)
868 GV = new GlobalVariable(*Fn->getParent(), STy, false,
869 GlobalValue::InternalLinkage, Initializer,
870 IConf.getRTName("", "value_pack"));
871
872 auto *AI = IIRB.getAlloca(Fn, STy);
873 IIRB.IRB.CreateMemCpy(AI, AI->getAlign(), GV, MaybeAlign(GV->getAlignment()),
874 IIRB.DL.getTypeAllocSize(STy));
875 for (auto [Param, Idx] : Values) {
876 auto *Ptr = IIRB.IRB.CreateStructGEP(STy, AI, Idx);
877 IIRB.IRB.CreateStore(Param, Ptr);
878 }
879 return AI;
880}
881
882template <typename Range>
883static void readValuePack(const Range &R, Value &Pack,
885 function_ref<void(int, Value *)> SetterCB) {
886 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
887 auto &DL = Fn->getDataLayout();
888 SmallVector<Value *> ParameterValues;
889 unsigned Offset = 0;
890 for (const auto &[Idx, RE] : enumerate(R)) {
891 Value *V = getValue(RE);
892 if (!V->getType()->isSized())
893 continue;
894 Offset += 8;
895 auto VSize = DL.getTypeAllocSize(V->getType());
896 auto Padding = alignTo(VSize, 8) - VSize;
897 Offset += Padding;
898 auto *Ptr = IIRB.IRB.CreateConstInBoundsGEP1_32(IIRB.Int8Ty, &Pack, Offset);
899 auto *NewV = IIRB.IRB.CreateLoad(V->getType(), Ptr);
900 SetterCB(Idx, NewV);
901 Offset += VSize;
902 }
903}
904
905/// FunctionIO
906/// {
908 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
909 using namespace std::placeholders;
910 if (UserConfig)
911 Config = *UserConfig;
912
914 if (Config.has(PassAddress))
915 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "address", "The function address.",
917 if (Config.has(PassName))
918 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The function name.",
920 if (Config.has(PassNumArguments))
921 IRTArgs.push_back(
922 IRTArg(IIRB.Int32Ty, "num_arguments",
923 "Number of function arguments (without varargs).", IRTArg::NONE,
924 std::bind(&FunctionIO::getNumArguments, this, _1, _2, _3, _4)));
925 if (Config.has(PassArguments))
926 IRTArgs.push_back(IRTArg(
927 IIRB.PtrTy, "arguments", "Description of the arguments.",
929 : IRTArg::NONE) |
931 std::bind(&FunctionIO::getArguments, this, _1, _2, _3, _4),
932 std::bind(&FunctionIO::setArguments, this, _1, _2, _3, _4)));
933 if (Config.has(PassIsMain))
934 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_main",
935 "Flag to indicate it is the main function.",
937 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
938 IConf.addChoice(*this, IIRB.Ctx);
939}
940
944 auto &Fn = cast<Function>(V);
945 if (Fn.isIntrinsic())
946 return Constant::getNullValue(&Ty);
947 return &V;
948}
952 auto &Fn = cast<Function>(V);
953 return IConf.getGlobalString(IConf.DemangleFunctionNames->getBool()
954 ? demangle(Fn.getName())
955 : Fn.getName(),
956 IIRB);
957}
961 auto &Fn = cast<Function>(V);
962 if (!Config.ArgFilter)
963 return getCI(&Ty, Fn.arg_size());
964 auto FRange = make_filter_range(Fn.args(), Config.ArgFilter);
965 return getCI(&Ty, std::distance(FRange.begin(), FRange.end()));
966}
970 auto &Fn = cast<Function>(V);
971 if (!Config.ArgFilter)
972 return createValuePack(Fn.args(), IConf, IIRB);
973 return createValuePack(make_filter_range(Fn.args(), Config.ArgFilter), IConf,
974 IIRB);
975}
979 auto &Fn = cast<Function>(V);
980 auto *AIt = Fn.arg_begin();
981 auto CB = [&](int Idx, Value *ReplV) {
982 while (Config.ArgFilter && !Config.ArgFilter(*AIt))
983 ++AIt;
984 Fn.getArg(Idx)->replaceUsesWithIf(ReplV, [&](Use &U) {
985 return IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) != IIRB.Epoch;
986 });
987 ++AIt;
988 };
989 if (!Config.ArgFilter)
990 readValuePack(Fn.args(), NewV, IIRB, CB);
991 else
992 readValuePack(make_filter_range(Fn.args(), Config.ArgFilter), NewV, IIRB,
993 CB);
994 return &Fn;
995}
999 auto &Fn = cast<Function>(V);
1000 return getCI(&Ty, Fn.getName() == "main");
1001}
1002
1005 auto &I = cast<Instruction>(V);
1006 return getCI(&Ty, I.getOpcode());
1007}
1008
1011 return getCI(&Ty, V.getType()->getTypeID());
1012}
1013
1016 auto &I = cast<Instruction>(V);
1017 auto &DL = I.getDataLayout();
1018 return getCI(&Ty, DL.getTypeStoreSize(V.getType()));
1019}
1020
1021/// UnreachableIO
1022///{
1024 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1025 if (UserConfig)
1026 Config = *UserConfig;
1027 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1028 IConf.addChoice(*this, IIRB.Ctx);
1029}
1030///}
1031
1032/// AllocaIO
1033///{
1035 ConfigTy *UserConfig) {
1036 if (UserConfig)
1037 Config = *UserConfig;
1038
1040 if (!IsPRE && Config.has(PassAddress))
1041 IRTArgs.push_back(
1042 IRTArg(IIRB.PtrTy, "address", "The allocated memory address.",
1046 if (Config.has(PassSize))
1047 IRTArgs.push_back(IRTArg(
1048 IIRB.Int64Ty, "size", "The allocation size.",
1050 getSize, setSize));
1051 if (Config.has(PassAlignment))
1052 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1053 "The allocation alignment.", IRTArg::NONE,
1054 getAlignment));
1055
1056 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1057 IConf.addChoice(*this, IIRB.Ctx);
1058}
1059
1062 auto &AI = cast<AllocaInst>(V);
1063 const DataLayout &DL = AI.getDataLayout();
1064 Value *SizeValue = nullptr;
1065 TypeSize TypeSize = DL.getTypeAllocSize(AI.getAllocatedType());
1066 if (TypeSize.isFixed()) {
1067 SizeValue = getCI(&Ty, TypeSize.getFixedValue());
1068 } else {
1069 auto *NullPtr = ConstantPointerNull::get(AI.getType());
1070 SizeValue = IIRB.IRB.CreatePtrToInt(
1071 IIRB.IRB.CreateGEP(AI.getAllocatedType(), NullPtr,
1072 {IIRB.IRB.getInt32(1)}),
1073 &Ty);
1074 }
1075 if (AI.isArrayAllocation())
1076 SizeValue = IIRB.IRB.CreateMul(
1077 SizeValue, IIRB.IRB.CreateZExtOrBitCast(AI.getArraySize(), &Ty));
1078 return SizeValue;
1079}
1080
1083 auto &AI = cast<AllocaInst>(V);
1084 const DataLayout &DL = AI.getDataLayout();
1085 auto *NewAI = IIRB.IRB.CreateAlloca(IIRB.IRB.getInt8Ty(),
1086 DL.getAllocaAddrSpace(), &NewV);
1087 NewAI->setAlignment(AI.getAlign());
1088 AI.replaceAllUsesWith(NewAI);
1089 IIRB.eraseLater(&AI);
1090 return NewAI;
1091}
1092
1095 return getCI(&Ty, cast<AllocaInst>(V).getAlign().value());
1096}
1097///}
1098
1100 ConfigTy *UserConfig) {
1101 if (UserConfig)
1102 Config = *UserConfig;
1103
1105 if (Config.has(PassPointer)) {
1106 IRTArgs.push_back(
1107 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1108 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1109 : IRTArg::NONE),
1111 }
1112 if (Config.has(PassPointerAS)) {
1113 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1114 "The address space of the accessed pointer.",
1116 }
1117 if (Config.has(PassBasePointerInfo)) {
1118 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1119 "The runtime provided base pointer info.",
1121 }
1122 if (Config.has(PassStoredValue)) {
1123 IRTArgs.push_back(
1124 IRTArg(getValueType(IIRB), "value", "The stored value.",
1127 : IRTArg::NONE),
1128 getValue));
1129 }
1130 if (Config.has(PassStoredValueSize)) {
1131 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1132 "The size of the stored value.", IRTArg::NONE,
1133 getValueSize));
1134 }
1135 if (Config.has(PassAlignment)) {
1136 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1137 "The known access alignment.", IRTArg::NONE,
1138 getAlignment));
1139 }
1140 if (Config.has(PassValueTypeId)) {
1141 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1142 "The type id of the stored value.", IRTArg::NONE,
1144 }
1145 if (Config.has(PassAtomicityOrdering)) {
1146 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1147 "The atomicity ordering of the store.",
1149 }
1150 if (Config.has(PassSyncScopeId)) {
1151 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1152 "The sync scope id of the store.", IRTArg::NONE,
1154 }
1155 if (Config.has(PassIsVolatile)) {
1156 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1157 "Flag indicating a volatile store.", IRTArg::NONE,
1158 isVolatile));
1159 }
1160
1161 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1162 IConf.addChoice(*this, IIRB.Ctx);
1163}
1164
1167 auto &SI = cast<StoreInst>(V);
1168 return SI.getPointerOperand();
1169}
1170
1173 auto &SI = cast<StoreInst>(V);
1174 SI.setOperand(SI.getPointerOperandIndex(), &NewV);
1175 return &SI;
1176}
1177
1180 auto &SI = cast<StoreInst>(V);
1181 return getCI(&Ty, SI.getPointerAddressSpace());
1182}
1183
1185 InstrumentationConfig &IConf,
1187 auto &SI = cast<StoreInst>(V);
1188 return IConf.getBasePointerInfo(*SI.getPointerOperand(), IIRB);
1189}
1190
1193 auto &SI = cast<StoreInst>(V);
1194 return SI.getValueOperand();
1195}
1196
1199 auto &SI = cast<StoreInst>(V);
1200 auto &DL = SI.getDataLayout();
1201 return getCI(&Ty, DL.getTypeStoreSize(SI.getValueOperand()->getType()));
1202}
1203
1206 auto &SI = cast<StoreInst>(V);
1207 return getCI(&Ty, SI.getAlign().value());
1208}
1209
1212 auto &SI = cast<StoreInst>(V);
1213 return getCI(&Ty, SI.getValueOperand()->getType()->getTypeID());
1214}
1215
1217 InstrumentationConfig &IConf,
1219 auto &SI = cast<StoreInst>(V);
1220 return getCI(&Ty, uint64_t(SI.getOrdering()));
1221}
1222
1225 auto &SI = cast<StoreInst>(V);
1226 return getCI(&Ty, uint64_t(SI.getSyncScopeID()));
1227}
1228
1231 auto &SI = cast<StoreInst>(V);
1232 return getCI(&Ty, SI.isVolatile());
1233}
1234
1236 ConfigTy *UserConfig) {
1238 if (UserConfig)
1239 Config = *UserConfig;
1240 if (Config.has(PassPointer)) {
1241 IRTArgs.push_back(
1242 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1243 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
1244 : IRTArg::NONE),
1246 }
1247 if (Config.has(PassPointerAS)) {
1248 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
1249 "The address space of the accessed pointer.",
1251 }
1252 if (Config.has(PassBasePointerInfo)) {
1253 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
1254 "The runtime provided base pointer info.",
1256 }
1257 if (!IsPRE && Config.has(PassValue)) {
1258 IRTArgs.push_back(
1259 IRTArg(getValueType(IIRB), "value", "The loaded value.",
1260 Config.has(ReplaceValue)
1263 : IRTArg::NONE)
1264 : IRTArg::NONE,
1265 getValue, Config.has(ReplaceValue) ? replaceValue : nullptr));
1266 }
1267 if (Config.has(PassValueSize)) {
1268 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
1269 "The size of the loaded value.", IRTArg::NONE,
1270 getValueSize));
1271 }
1272 if (Config.has(PassAlignment)) {
1273 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1274 "The known access alignment.", IRTArg::NONE,
1275 getAlignment));
1276 }
1277 if (Config.has(PassValueTypeId)) {
1278 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
1279 "The type id of the loaded value.", IRTArg::NONE,
1281 }
1282 if (Config.has(PassAtomicityOrdering)) {
1283 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1284 "The atomicity ordering of the load.",
1286 }
1287 if (Config.has(PassSyncScopeId)) {
1288 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
1289 "The sync scope id of the load.", IRTArg::NONE,
1291 }
1292 if (Config.has(PassIsVolatile)) {
1293 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
1294 "Flag indicating a volatile load.", IRTArg::NONE,
1295 isVolatile));
1296 }
1297
1298 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1299 IConf.addChoice(*this, IIRB.Ctx);
1300}
1301
1304 auto &LI = cast<LoadInst>(V);
1305 return LI.getPointerOperand();
1306}
1307
1310 auto &LI = cast<LoadInst>(V);
1311 LI.setOperand(LI.getPointerOperandIndex(), &NewV);
1312 return &LI;
1313}
1314
1317 auto &LI = cast<LoadInst>(V);
1318 return getCI(&Ty, LI.getPointerAddressSpace());
1319}
1320
1322 InstrumentationConfig &IConf,
1324 auto &LI = cast<LoadInst>(V);
1325 return IConf.getBasePointerInfo(*LI.getPointerOperand(), IIRB);
1326}
1327
1330 return &V;
1331}
1332
1335 auto &LI = cast<LoadInst>(V);
1336 auto &DL = LI.getDataLayout();
1337 return getCI(&Ty, DL.getTypeStoreSize(LI.getType()));
1338}
1339
1342 auto &LI = cast<LoadInst>(V);
1343 return getCI(&Ty, LI.getAlign().value());
1344}
1345
1348 auto &LI = cast<LoadInst>(V);
1349 return getCI(&Ty, LI.getType()->getTypeID());
1350}
1351
1353 InstrumentationConfig &IConf,
1355 auto &LI = cast<LoadInst>(V);
1356 return getCI(&Ty, uint64_t(LI.getOrdering()));
1357}
1358
1361 auto &LI = cast<LoadInst>(V);
1362 return getCI(&Ty, uint64_t(LI.getSyncScopeID()));
1363}
1364
1367 auto &LI = cast<LoadInst>(V);
1368 return getCI(&Ty, LI.isVolatile());
1369}
1370
1372 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1373 if (UserConfig)
1374 Config = *UserConfig;
1375 if (Config.has(PassPointer))
1376 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer",
1377 "The base pointer in question.",
1379 if (Config.has(PassPointerKind))
1380 IRTArgs.push_back(IRTArg(
1381 IIRB.Int32Ty, "base_pointer_kind",
1382 "The base pointer kind (argument, global, instruction, unknown).",
1384 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1385 IConf.addChoice(*this, IIRB.Ctx);
1386}
1387
1389 InstrumentationConfig &IConf,
1391 if (isa<Argument>(V))
1392 return getCI(&Ty, 0);
1393 if (isa<GlobalValue>(V))
1394 return getCI(&Ty, 1);
1395 if (isa<Instruction>(V))
1396 return getCI(&Ty, 2);
1397 return getCI(&Ty, 3);
1398}
1399
1401 ConfigTy *UserConfig) {
1402 if (UserConfig)
1403 Config = *UserConfig;
1404
1405 if (Config.has(PassName))
1406 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "module_name",
1407 "The module/translation unit name.",
1409 if (Config.has(PassTargetTriple))
1410 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "target_triple", "The target triple.",
1412
1413 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1414 IConf.addChoice(*this, IIRB.Ctx);
1415}
1418 // V is a constructor or destructor of the module we can place code in.
1419 auto &Fn = cast<Function>(V);
1420 return IConf.getGlobalString(Fn.getParent()->getName(), IIRB);
1421}
1423 InstrumentationConfig &IConf,
1425 // V is a constructor or destructor of the module we can place code in.
1426 auto &Fn = cast<Function>(V);
1427 return IConf.getGlobalString(Fn.getParent()->getTargetTriple().getTriple(),
1428 IIRB);
1429}
1430
1432 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1433 if (UserConfig)
1434 Config = *UserConfig;
1436 if (Config.has(PassAddress))
1437 IRTArgs.push_back(IRTArg(
1438 IIRB.PtrTy, "address",
1439 "The address of the global (replaceable for definitions).",
1442 if (Config.has(PassAS))
1443 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "address_space",
1444 "The address space of the global.", IRTArg::NONE,
1445 getAS));
1446 if (Config.has(PassDeclaredSize))
1447 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "declared_size",
1448 "The size of the declared type of the global.",
1450 if (Config.has(PassAlignment))
1451 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
1452 "The allocation alignment.", IRTArg::NONE,
1453 getAlignment));
1454 if (Config.has(PassName))
1455 IRTArgs.push_back(IRTArg(IIRB.PtrTy, "name", "The name of the global.",
1457 if (Config.has(PassInitialValue))
1458 IRTArgs.push_back(IRTArg(
1459 IIRB.Int64Ty, "initial_value", "The initial value of the global.",
1462 if (Config.has(PassIsConstant))
1463 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_constant",
1464 "Flag to indicate constant globals.", IRTArg::NONE,
1465 isConstant));
1466 if (Config.has(PassIsDefinition))
1467 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_definition",
1468 "Flag to indicate global definitions.",
1470 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1471 IConf.addChoice(*this, IIRB.Ctx);
1472}
1476 if (GV.getAddressSpace())
1477 return ConstantExpr::getAddrSpaceCast(&GV, IIRB.PtrTy);
1478 return &GV;
1479}
1481 InstrumentationConfig &IConf,
1484
1485 GlobalVariable *ShadowGV = nullptr;
1486 auto ShadowName = IConf.getRTName("shadow.", GV.getName());
1487 auto &DL = GV.getDataLayout();
1488 if (GV.isDeclaration()) {
1489 ShadowGV = new GlobalVariable(*GV.getParent(), GV.getType(), false,
1491 ShadowName, &GV, GV.getThreadLocalMode(),
1492 DL.getDefaultGlobalsAddressSpace());
1493 } else {
1494 ShadowGV = new GlobalVariable(
1495 *GV.getParent(), NewV.getType(), false, GV.getLinkage(),
1496 PoisonValue::get(NewV.getType()), ShadowName, &GV);
1497 IIRB.IRB.CreateStore(&NewV, ShadowGV);
1498 }
1499
1503 DenseMap<Value *, Instruction *> ConstToInstMap;
1505
1506 auto MakeInstForConst = [&](Use &U) {
1507 Instruction *&I = ConstToInstMap[U];
1508 if (I)
1509 return;
1510 if (U == &GV) {
1511 } else if (auto *CE = dyn_cast<ConstantExpr>(U)) {
1512 I = CE->getAsInstruction();
1513 }
1514 };
1515
1516 auto InsertConsts = [&](Instruction *UserI, Use &UserU) {
1518 auto *&Reload = ReloadMap[UserI->getFunction()];
1519 if (!Reload) {
1520 Reload = new LoadInst(
1521 GV.getType(), ShadowGV, GV.getName() + ".shadow_load",
1523 IIRB.NewInsts.insert({Reload, IIRB.Epoch});
1524 }
1525 Worklist.push_back({UserI, &UserU});
1526 while (!Worklist.empty()) {
1527 auto [I, U] = Worklist.pop_back_val();
1528 if (*U == &GV) {
1529 U->set(ReloadMap[I->getFunction()]);
1530 continue;
1531 }
1532 if (auto *CI = ConstToInstMap[*U]) {
1533 auto *CIClone = CI->clone();
1534 IIRB.NewInsts.insert({CIClone, IIRB.Epoch});
1535 if (auto *PHI = dyn_cast<PHINode>(I)) {
1536 auto *BB = PHI->getIncomingBlock(U->getOperandNo());
1537 CIClone->insertBefore(BB->getTerminator()->getIterator());
1538 } else {
1539 CIClone->insertBefore(I->getIterator());
1540 }
1541 U->set(CIClone);
1542 for (auto &CICUse : CIClone->operands()) {
1543 Worklist.push_back({CIClone, &CICUse});
1544 }
1545 }
1546 }
1547 };
1548
1549 SmallPtrSet<Use *, 8> Visited;
1550 while (!Worklist.empty()) {
1551 Use *U = Worklist.pop_back_val();
1552 if (!Done.insert(U).second)
1553 continue;
1554 MakeInstForConst(*U);
1555 auto *I = dyn_cast<Instruction>(U->getUser());
1556 if (!I) {
1557 append_range(Worklist, make_pointer_range(U->getUser()->uses()));
1558 continue;
1559 }
1560 if (IIRB.NewInsts.lookup(I) == IIRB.Epoch)
1561 continue;
1563 continue;
1564 if (auto *II = dyn_cast<IntrinsicInst>(I))
1565 if (II->getIntrinsicID() == Intrinsic::eh_typeid_for)
1566 continue;
1567 if (I->getParent())
1568 InsertConsts(I, *U);
1569 }
1570
1571 for (auto &It : ConstToInstMap)
1572 if (It.second)
1573 It.second->deleteValue();
1574
1575 return &V;
1576}
1580 return getCI(&Ty, GV.getAddressSpace());
1581}
1583 InstrumentationConfig &IConf,
1586 return getCI(&Ty, GV.getAlignment());
1587}
1589 InstrumentationConfig &IConf,
1592 auto &DL = GV.getDataLayout();
1593 return getCI(&Ty, DL.getTypeAllocSize(GV.getValueType()));
1594}
1596 InstrumentationConfig &IConf,
1599 return IConf.getGlobalString(GV.getName(), IIRB);
1600}
1611 return getCI(&Ty, GV.isConstant());
1612}
1614 InstrumentationConfig &IConf,
1617 return getCI(&Ty, !GV.isDeclaration());
1618}
1619
1620/// CastIO
1621/// {
1623 ConfigTy *UserConfig) {
1624 if (UserConfig)
1625 Config = *UserConfig;
1627 if (Config.has(PassInput))
1628 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "input", "Input value of the cast.",
1630 if (Config.has(PassInputTypeId))
1631 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_type_id",
1632 "The type id of the input value.", IRTArg::NONE,
1634 if (Config.has(PassInputSize))
1635 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "input_size",
1636 "The size of the input value.", IRTArg::NONE,
1637 getInputSize));
1638 if (!IsPRE && Config.has(PassResult))
1639 IRTArgs.push_back(
1640 IRTArg(IIRB.Int64Ty, "result", "Result of the cast.",
1642 Config.has(ReplaceResult) ? replaceValue : nullptr));
1643 if (Config.has(PassResultTypeId))
1644 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_type_id",
1645 "The type id of the result value.", IRTArg::NONE,
1647 if (Config.has(PassResultSize))
1648 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "result_size",
1649 "The size of the result value.", IRTArg::NONE,
1650 getResultSize));
1651 if (Config.has(PassOpcode))
1652 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode",
1653 "The opcode of the cast instruction.",
1655
1656 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1657 IConf.addChoice(*this, IIRB.Ctx);
1658}
1659
1662 auto &CI = cast<CastInst>(V);
1663 return CI.getOperand(0);
1664}
1665
1668 auto &CI = cast<CastInst>(V);
1669 return getCI(&Ty, CI.getSrcTy()->getTypeID());
1670}
1671
1674 auto &CI = cast<CastInst>(V);
1675 auto &DL = CI.getDataLayout();
1676 return getCI(&Ty, DL.getTypeStoreSize(CI.getSrcTy()));
1677}
1678
1681 auto &CI = cast<CastInst>(V);
1682 return getCI(&Ty, CI.getDestTy()->getTypeID());
1683}
1684
1687 auto &CI = cast<CastInst>(V);
1688 auto &DL = CI.getDataLayout();
1689 return getCI(&Ty, DL.getTypeStoreSize(CI.getDestTy()));
1690}
1691///}
1692
1695 auto &I = cast<Instruction>(V);
1696 return I.getOperand(0);
1697}
1698
1701 auto &I = cast<Instruction>(V);
1702 if (I.getNumOperands() > 1)
1703 return I.getOperand(1);
1704 else
1705 return PoisonValue::get(&Ty);
1706}
1707
1709 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1710 if (UserConfig)
1711 Config = UserConfig;
1713 const auto ValArgOpts =
1716 if (Config.has(PassTypeId))
1717 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "type_id",
1718 "The operation's type id.", IRTArg::NONE,
1719 getTypeId));
1720 if (Config.has(PassSize))
1721 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "size", "The operation's type size.",
1723 if (Config.has(PassOpcode))
1724 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
1726 if (Config.has(PassLeft))
1727 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
1728 "The operation's left operand.", ValArgOpts,
1729 getLeft));
1730 if (Config.has(PassRight))
1731 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
1732 "The operation's right operand. This value is "
1733 "poison for unary operations.",
1734 ValArgOpts, getRight));
1735 if (!IsPRE && Config.has(PassResult))
1736 IRTArgs.push_back(
1737 IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
1738 IRTArg::REPLACABLE | ValArgOpts, getValue,
1739 Config.has(ReplaceResult) ? replaceValue : nullptr));
1740 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
1741 IConf.addChoice(*this, IIRB.Ctx);
1742}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
Rewrite undef for PHI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
This file contains the declarations for the subclasses of Constant, which represent the different fla...
post inline ee instrument
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static void readValuePack(const Range &R, Value &Pack, InstrumentorIRBuilderTy &IIRB, function_ref< void(int, Value *)> SetterCB)
static Value * getTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static constexpr Value * getValue(Ty &ValueOrUse)
static Value * createValuePack(const Range &R, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Regex createRegex(StringRef Str, StringRef Name, LLVMContext &Ctx)
#define I(x, y, z)
Definition MD5.cpp:57
This file contains the declarations for metadata subclasses.
#define T
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
ModuleAnalysisManager MAM
if(PassOpts->AAPipeline)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
Defines the virtual file system interface vfs::FileSystem.
static unsigned getSize(unsigned Kind)
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
LLVM_ABI const_iterator getFirstNonPHIOrDbgOrAlloca() const
Returns an iterator to the first instruction in this block that is not a PHINode, a debug intrinsic,...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Diagnostic information for IR instrumentation reporting.
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
const BasicBlock & getEntryBlock() const
Definition Function.h:809
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:362
iterator_range< arg_iterator > args()
Definition Function.h:892
arg_iterator arg_begin()
Definition Function.h:868
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition Function.h:251
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:358
size_t arg_size() const
Definition Function.h:901
Argument * getArg(unsigned i) const
Definition Function.h:886
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:728
StringRef getSection() const
Get the custom section of this global if it has one.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:392
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:196
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
@ WeakODRLinkage
Same, but only replaced by something equivalent.
Definition GlobalValue.h:58
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
uint64_t getAlignment() const
FIXME: Remove this function once transition to Align is over.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
InstrumentorPass(IntrusiveRefCntPtr< vfs::FileSystem > FS=nullptr, InstrumentationConfig *IC=nullptr, InstrumentorIRBuilderTy *IIRB=nullptr)
Construct an instrumentor pass that will use the instrumentation configuration IC and the IR builder ...
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
An instruction for reading from memory.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1572
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition Module.h:284
size_t global_size() const
Definition Module.h:708
StringRef getName() const
Get a short "name" for the module.
Definition Module.h:272
iterator_range< global_iterator > globals()
Definition Module.h:711
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
LLVM_ABI bool isValid(std::string &Error) const
isValid - returns the error encountered during regex compilation, if any.
Definition Regex.cpp:69
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Definition Regex.cpp:83
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void reserve(size_type N)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:483
const std::string & getTriple() const
Definition Triple.h:503
bool isAMDGPU() const
Definition Triple.h:910
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:284
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:321
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
Definition Value.cpp:557
iterator_range< use_iterator > uses()
Definition Value.h:380
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:318
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
Definition TypeSize.h:171
An efficient, type-erasing, non-owning reference to a callable.
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
initializer< Ty > init(const Ty &Val)
void writeConfigToJSON(InstrumentationConfig &IConf, StringRef OutputFile, LLVMContext &Ctx)
Write the configuration in /p IConf to the file with path OutputFile.
bool readConfigPathsFile(StringRef InputFile, cl::list< std::string > &Configs, LLVMContext &Ctx, vfs::FileSystem &FS)
Read the configuration paths from the file with path InputFile into Configs.
bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile, LLVMContext &Ctx, vfs::FileSystem &FS)
Read the configuration from the file with path InputFile into /p IConf.
void printRuntimeStub(const InstrumentationConfig &IConf, StringRef StubRuntimeName, LLVMContext &Ctx)
Print a runtime stub file with the implementation of the instrumentation runtime functions correspond...
LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:558
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
MaybeAlign getAlign(const CallInst &I, unsigned Index)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2553
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Done
Definition Threading.h:60
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2207
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:551
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI const Value * getUnderlyingObjectAggressive(const Value *V)
Like getUnderlyingObject(), but will try harder to find a single underlying object.
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
LLVM_ABI void appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Same as appendToGlobalCtors(), but for global dtors.
DEMANGLE_ABI std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.
Definition Demangle.cpp:21
LLVM_ABI bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
}
BaseConfigTy< ConfigKind > ConfigTy
static Value * getSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * setSize(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static std::unique_ptr< BaseConfigurationOption > createStringOption(InstrumentationConfig &IC, StringRef Name, StringRef Description, StringRef DefaultValue)
Create a string option with Name name, Description description and DefaultValue as string default val...
static std::unique_ptr< BaseConfigurationOption > createBoolOption(InstrumentationConfig &IC, StringRef Name, StringRef Description, bool DefaultValue)
Create a boolean option with Name name, Description description and DefaultValue as boolean default v...
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static 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
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
CastIO {.
static Value * getResultTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getInputSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getResultSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getInput(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static Value * getInputTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
llvm::instrumentor::FunctionIO::ConfigTy Config
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Value * setArguments(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getFunctionAddress(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * isMainFunction(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Value * getArguments(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Value * getNumArguments(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getFunctionName(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
FunctionIO {.
static Value * setAddress(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
static Value * getAS(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getInitialValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * isDefinition(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getDeclaredSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getSymbolName(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAddress(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static Value * isConstant(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
bool isReplacable(IRTArg &IRTA) const
Return whether the IRTA argument can be replaced.
IRTCallDescription(InstrumentationOpportunity &IO, Type *RetTy=nullptr)
Construct an instrumentation function description linked to the IO instrumentation opportunity and Re...
bool MightRequireIndirection
Whether any argument may require indirection.
CallInst * createLLVMCall(Value *&V, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, const DataLayout &DL, InstrumentationCaches &ICaches)
Create a call instruction that calls to the instrumentation function and passes the corresponding arg...
Type * RetTy
The return type of the instrumentation function.
InstrumentationOpportunity & IO
The instrumentation opportunity which it is linked to.
FunctionType * createLLVMSignature(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, const DataLayout &DL, bool ForceIndirection)
Create the type of the instrumentation function.
unsigned NumReplaceableArgs
The number of arguments that can be replaced.
bool RequiresIndirection
Whether the function requires indirection in some argument.
bool isPotentiallyIndirect(IRTArg &IRTA) const
Return whether the function may have any indirect argument.
Helper that represent the caches for instrumentation call arguments.
DenseMap< std::tuple< unsigned, StringRef, StringRef >, Value * > DirectArgCache
A cache for direct and indirect arguments.
DenseMap< std::tuple< unsigned, StringRef, StringRef >, Value * > IndirectArgCache
The class that contains the configuration for the instrumentor.
virtual void populate(InstrumentorIRBuilderTy &IIRB)
Populate the instrumentation opportunities.
void addChoice(InstrumentationOpportunity &IO, LLVMContext &Ctx)
Register instrumentation opportunity IO.
Constant * getGlobalString(StringRef S, InstrumentorIRBuilderTy &IIRB)
DenseMap< Value *, Value * > UnderlyingObjsMap
Map to remember underlying objects for pointers.
std::unique_ptr< BaseConfigurationOption > HostEnabled
std::unique_ptr< BaseConfigurationOption > DemangleFunctionNames
void init(InstrumentorIRBuilderTy &IIRB)
Initialize the config to a clean base state without loosing cached values that can be reused across c...
DenseMap< std::pair< Value *, Function * >, Value * > BasePointerInfoMap
Map to remember base pointer info for values in a specific function.
EnumeratedArray< MapVector< StringRef, InstrumentationOpportunity * >, InstrumentationLocation::KindTy > IChoices
The map registered instrumentation opportunities.
std::unique_ptr< BaseConfigurationOption > GPUEnabled
DenseMap< Constant *, GlobalVariable * > ConstantGlobalsCache
Mapping from constants to globals with the constant as initializer.
Value * getBasePointerInfo(Value &V, InstrumentorIRBuilderTy &IIRB)
Return the base pointer info for V.
std::unique_ptr< BaseConfigurationOption > RuntimeStubsFile
StringRef getRTName() const
Get the runtime prefix for the instrumentation runtime functions.
void addBaseChoice(BaseConfigurationOption *BCO)
Add the base configuration option BCO into the list of base options.
std::unique_ptr< BaseConfigurationOption > FunctionRegex
std::unique_ptr< BaseConfigurationOption > TargetRegex
bool isPRE() const
Return whether the instrumentation location is before the event occurs.
Base class for instrumentation opportunities.
InstrumentationLocation::KindTy getLocationKind() const
Get the location kind of the instrumentation opportunity.
static Value * getIdPre(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Get the opportunity identifier for the pre and post positions.
static Value * forceCast(Value &V, Type &Ty, InstrumentorIRBuilderTy &IIRB)
Helpers to cast values, pass them to the runtime, and replace them.
static int32_t getIdFromEpoch(uint32_t CurrentEpoch)
}
static Value * getIdPost(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * replaceValue(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
virtual StringRef getName() const =0
Get the name of the instrumentation opportunity.
SmallVector< IRTArg > IRTArgs
The list of possible arguments for the instrumentation runtime function.
void addCommonArgs(InstrumentationConfig &IConf, LLVMContext &Ctx, bool PassId)
}
An IR builder augmented with extra information for the instrumentor pass.
IRBuilder< ConstantFolder, IRBuilderCallbackInserter > IRB
The underlying IR builder with insertion callback.
unsigned Epoch
The current epoch number.
AllocaInst * getAlloca(Function *Fn, Type *Ty, bool MatchType=false)
Get a temporary alloca to communicate (large) values with the runtime.
void returnAllocas()
Return the temporary allocas.
DenseMap< Instruction *, unsigned > NewInsts
A mapping from instrumentation instructions to the epoch they have been created.
void eraseLater(Instruction *I)
Save instruction I to be erased later.
static Value * getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAtomicityOrdering(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
virtual Type * getValueType(InstrumentorIRBuilderTy &IIRB) const
}
static Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getPointer(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Getters and setters for the arguments of the instrumentation function for the load opportunity.
static Value * isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getBasePointerInfo(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static Value * getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
}
static Value * getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
Initialize the load opportunity using the instrumentation config IConf and the user config UserConfig...
static Value * getModuleName(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getTargetTriple(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
BaseConfigTy< ConfigKind > ConfigTy
static Value * getLeft(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
}
static Value * getRight(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
static Value * getPointer(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
Getters and setters for the arguments of the instrumentation function for the store opportunity.
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
}
static Value * getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
virtual Type * getValueType(InstrumentorIRBuilderTy &IIRB) const
}
static Value * getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getValue(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
BaseConfigTy< ConfigKind > ConfigTy
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
Initialize the store opportunity using the instrumentation config IConf and the user config UserConfi...
static Value * getBasePointerInfo(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static Value * getAtomicityOrdering(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
static void populate(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig=nullptr)
UnreachableIO {.
BaseConfigTy< ConfigKind > ConfigTy