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