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
22#include "llvm/ADT/StringMap.h"
23#include "llvm/ADT/iterator.h"
24#include "llvm/IR/Constant.h"
25#include "llvm/IR/Constants.h"
26#include "llvm/IR/DataLayout.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/IRBuilder.h"
31#include "llvm/IR/InstrTypes.h"
32#include "llvm/IR/Instruction.h"
35#include "llvm/IR/Intrinsics.h"
36#include "llvm/IR/LLVMContext.h"
37#include "llvm/IR/Metadata.h"
38#include "llvm/IR/Module.h"
39#include "llvm/IR/PassManager.h"
40#include "llvm/IR/Verifier.h"
44#include "llvm/Support/Regex.h"
45
46#include <cassert>
47#include <cstdint>
48#include <functional>
49#include <iterator>
50#include <memory>
51#include <string>
52#include <system_error>
53#include <type_traits>
54
55using namespace llvm;
56using namespace llvm::instrumentor;
57
58#define DEBUG_TYPE "instrumentor"
59
60namespace {
61
62/// The user option to specify an output JSON file to write the configuration.
63static cl::opt<std::string> WriteConfigFile(
64 "instrumentor-write-config-file",
66 "Write the instrumentor configuration into the specified JSON file"),
67 cl::init(""));
68
69/// The user option to specify an input JSON file to read the configuration.
70static cl::opt<std::string> ReadConfigFile(
71 "instrumentor-read-config-file",
73 "Read the instrumentor configuration from the specified JSON file"),
74 cl::init(""));
75
76/// Set the debug location, if not set, after changing the insertion point of
77/// the IR builder \p IRB.
78template <typename IRBuilderTy> void ensureDbgLoc(IRBuilderTy &IRB) {
79 if (IRB.getCurrentDebugLocation())
80 return;
81 auto *BB = IRB.GetInsertBlock();
82 if (auto *SP = BB->getParent()->getSubprogram())
83 IRB.SetCurrentDebugLocation(DILocation::get(BB->getContext(), 0, 0, SP));
84}
85
86/// Attempt to cast \p V to type \p Ty.
87template <typename IRBTy>
88Value *tryToCast(IRBTy &IRB, Value *V, Type *Ty, const DataLayout &DL,
89 bool AllowTruncate = false) {
90 if (!V)
92 Type *VTy = V->getType();
93 if (VTy == Ty)
94 return V;
95 if (VTy->isAggregateType())
96 return V;
97 TypeSize RequestedSize = DL.getTypeSizeInBits(Ty);
98 TypeSize ValueSize = DL.getTypeSizeInBits(VTy);
99 bool ShouldTruncate = RequestedSize < ValueSize;
100 if (ShouldTruncate && !AllowTruncate)
101 return V;
102 if (ShouldTruncate && AllowTruncate)
103 return tryToCast(IRB,
104 IRB.CreateIntCast(V, IRB.getIntNTy(RequestedSize),
105 /*IsSigned=*/false),
106 Ty, DL, AllowTruncate);
107 if (VTy->isPointerTy() && Ty->isPointerTy())
108 return IRB.CreatePointerBitCastOrAddrSpaceCast(V, Ty);
109 if (VTy->isIntegerTy() && Ty->isIntegerTy())
110 return IRB.CreateIntCast(V, Ty, /*IsSigned=*/false);
111 if (VTy->isFloatingPointTy() && Ty->isIntOrPtrTy()) {
112 return tryToCast(IRB, IRB.CreateBitCast(V, IRB.getIntNTy(ValueSize)), Ty,
113 DL, AllowTruncate);
114 }
115 return IRB.CreateBitOrPointerCast(V, Ty);
116}
117
118/// Get a constant integer/boolean of type \p IT and value \p Val.
119template <typename Ty>
120Constant *getCI(Type *IT, Ty Val, bool IsSigned = false) {
121 return ConstantInt::get(IT, Val, IsSigned);
122}
123
124/// The core of the instrumentor pass, which instruments the module as the
125/// instrumentation configuration mandates.
126class InstrumentorImpl final {
127public:
128 /// Construct an instrumentor implementation using the configuration \p IConf.
129 InstrumentorImpl(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
130 Module &M)
131 : IConf(IConf), M(M), IIRB(IIRB) {
132 IConf.populate(IIRB);
133 }
134
135 /// Instrument the module, public entry point.
136 bool instrument();
137
138private:
139 /// Indicate if the module should be instrumented based on the target.
140 bool shouldInstrumentTarget();
141
142 /// Indicate if the function \p Fn should be instrumented.
143 bool shouldInstrumentFunction(Function &Fn);
144
145 /// Instrument instruction \p I if needed, and use the argument caches in \p
146 /// ICaches.
147 bool instrumentInstruction(Instruction &I, InstrumentationCaches &ICaches);
148
149 /// Instrument function \p Fn.
150 bool instrumentFunction(Function &Fn);
151
152 /// The instrumentation opportunities for instructions indexed by
153 /// their opcode.
155 InstChoicesPOST;
156
157 /// The instrumentor configuration.
159
160 /// The underlying module.
161 Module &M;
162
163protected:
164 /// A special IR builder that keeps track of the inserted instructions.
166};
167
168} // end anonymous namespace
169
170bool InstrumentorImpl::shouldInstrumentTarget() {
171 const Triple &T = M.getTargetTriple();
172 const bool IsGPU = T.isAMDGPU() || T.isNVPTX();
173
174 bool RegexMatches = true;
175 const auto TargetRegexStr = IConf.TargetRegex->getString();
176 if (!TargetRegexStr.empty()) {
177 llvm::Regex TargetRegex(TargetRegexStr);
178 std::string ErrMsg;
179 if (!TargetRegex.isValid(ErrMsg)) {
180 IIRB.Ctx.diagnose(DiagnosticInfoInstrumentation(
181 Twine("failed to parse target regex: ") + ErrMsg, DS_Warning));
182 return false;
183 }
184 RegexMatches = TargetRegex.match(T.str());
185 }
186
187 // Only instrument the module if the target has to be instrumented.
188 return ((IsGPU && IConf.GPUEnabled->getBool()) ||
189 (!IsGPU && IConf.HostEnabled->getBool())) &&
190 RegexMatches;
191}
192
193bool InstrumentorImpl::shouldInstrumentFunction(Function &Fn) {
194 if (Fn.isDeclaration())
195 return false;
196 return !Fn.getName().starts_with(IConf.getRTName()) ||
197 Fn.hasFnAttribute("instrument");
198}
199
200bool InstrumentorImpl::instrumentInstruction(Instruction &I,
201 InstrumentationCaches &ICaches) {
202 bool Changed = false;
203
204 // Skip instrumentation instructions.
205 if (IIRB.NewInsts.contains(&I))
206 return Changed;
207
208 // Count epochs eagerly.
209 ++IIRB.Epoch;
210
211 Value *IPtr = &I;
212 if (auto *IO = InstChoicesPRE.lookup(I.getOpcode())) {
213 IIRB.IRB.SetInsertPoint(&I);
214 ensureDbgLoc(IIRB.IRB);
215 Changed |= bool(IO->instrument(IPtr, IConf, IIRB, ICaches));
216 }
217
218 if (auto *IO = InstChoicesPOST.lookup(I.getOpcode())) {
219 IIRB.IRB.SetInsertPoint(I.getNextNode());
220 ensureDbgLoc(IIRB.IRB);
221 Changed |= bool(IO->instrument(IPtr, IConf, IIRB, ICaches));
222 }
223 IIRB.returnAllocas();
224
225 return Changed;
226}
227
228bool InstrumentorImpl::instrumentFunction(Function &Fn) {
229 bool Changed = false;
230 if (!shouldInstrumentFunction(Fn))
231 return Changed;
232
233 InstrumentationCaches ICaches;
234 ReversePostOrderTraversal<Function *> RPOT(&Fn);
235 for (auto &It : RPOT)
236 for (auto &I : *It)
237 Changed |= instrumentInstruction(I, ICaches);
238
239 return Changed;
240}
241
242bool InstrumentorImpl::instrument() {
243 bool Changed = false;
244 if (!shouldInstrumentTarget())
245 return Changed;
246
248 if (It.second->Enabled)
249 InstChoicesPRE[It.second->getOpcode()] = It.second;
251 if (It.second->Enabled)
252 InstChoicesPOST[It.second->getOpcode()] = It.second;
253
254 for (Function &Fn : M)
255 Changed |= instrumentFunction(Fn);
256
257 return Changed;
258}
259
260PreservedAnalyses InstrumentorPass::run(Module &M, InstrumentationConfig &IConf,
261 InstrumentorIRBuilderTy &IIRB,
262 bool ReadConfig) {
263 InstrumentorImpl Impl(IConf, IIRB, M);
264 if (ReadConfig && !readConfigFromJSON(IConf, ReadConfigFile, IIRB.Ctx))
265 return PreservedAnalyses::all();
266
267 writeConfigToJSON(IConf, WriteConfigFile, IIRB.Ctx);
268
269 printRuntimeStub(IConf, IConf.RuntimeStubsFile->getString(), IIRB.Ctx);
270
271 bool Changed = Impl.instrument();
272 if (!Changed)
273 return PreservedAnalyses::all();
275}
276
278 // Only create them if the user did not provide them.
279 std::unique_ptr<InstrumentationConfig> IConfInt(
280 !UserIConf ? new InstrumentationConfig() : nullptr);
281 std::unique_ptr<InstrumentorIRBuilderTy> IIRBInt(
282 !UserIIRB ? new InstrumentorIRBuilderTy(M) : nullptr);
283
284 auto *IConf = IConfInt ? IConfInt.get() : UserIConf;
285 auto *IIRB = IIRBInt ? IIRBInt.get() : UserIIRB;
286
287 auto PA = run(M, *IConf, *IIRB, !UserIConf);
288
289 assert(!verifyModule(M, &errs()));
290 return PA;
291}
292
293std::unique_ptr<BaseConfigurationOption>
296 bool DefaultValue) {
297 auto BCO =
298 std::make_unique<BaseConfigurationOption>(Name, Description, BOOLEAN);
299 BCO->setBool(DefaultValue);
300 IConf.addBaseChoice(BCO.get());
301 return BCO;
302}
303
304std::unique_ptr<BaseConfigurationOption>
308 StringRef DefaultValue) {
309 auto BCO =
310 std::make_unique<BaseConfigurationOption>(Name, Description, STRING);
311 BCO->setString(DefaultValue);
312 IConf.addBaseChoice(BCO.get());
313 return BCO;
314}
315
317 /// List of all instrumentation opportunities.
318 LoadIO::populate(*this, IIRB);
319 StoreIO::populate(*this, IIRB);
320}
321
323 LLVMContext &Ctx) {
324 auto *&ICPtr = IChoices[IO.getLocationKind()][IO.getName()];
325 if (ICPtr) {
327 Twine("registered two instrumentation opportunities for the same "
328 "location (") +
329 ICPtr->getName() + Twine(" vs ") + IO.getName() + Twine(")"),
330 DS_Warning));
331 }
332 ICPtr = &IO;
333}
334
338 return getCI(&Ty, getIdFromEpoch(IIRB.Epoch));
339}
340
344 return getCI(&Ty, -getIdFromEpoch(IIRB.Epoch), /*IsSigned=*/true);
345}
346
349 if (V.getType()->isVoidTy())
350 return Ty.isVoidTy() ? &V : Constant::getNullValue(&Ty);
351 return tryToCast(IIRB.IRB, &V, &Ty,
352 IIRB.IRB.GetInsertBlock()->getDataLayout());
353}
354
358 if (V.getType()->isVoidTy())
359 return &V;
360
361 auto *NewVCasted = &NewV;
362 if (auto *I = dyn_cast<Instruction>(&NewV)) {
364 IIRB.IRB.SetInsertPoint(I->getNextNode());
365 ensureDbgLoc(IIRB.IRB);
366 NewVCasted = tryToCast(IIRB.IRB, &NewV, V.getType(), IIRB.DL,
367 /*AllowTruncate=*/true);
368 }
369 V.replaceUsesWithIf(NewVCasted, [&](Use &U) {
370 if (IIRB.NewInsts.lookup(cast<Instruction>(U.getUser())) == IIRB.Epoch)
371 return false;
372 return !isa<LifetimeIntrinsic>(U.getUser()) && !U.getUser()->isDroppable();
373 });
374
375 return &V;
376}
377
379 Type *RetTy)
380 : IO(IO), RetTy(RetTy) {
381 for (auto &It : IO.IRTArgs) {
382 if (!It.Enabled)
383 continue;
384 NumReplaceableArgs += bool(It.Flags & IRTArg::REPLACABLE);
385 MightRequireIndirection |= It.Flags & IRTArg::POTENTIALLY_INDIRECT;
386 }
389}
390
393 const DataLayout &DL, bool ForceIndirection) {
394 assert(((ForceIndirection && MightRequireIndirection) ||
395 (!ForceIndirection && !RequiresIndirection)) &&
396 "Wrong indirection setting!");
397
398 SmallVector<Type *> ParamTypes;
399 for (auto &It : IO.IRTArgs) {
400 if (!It.Enabled)
401 continue;
402 if (!ForceIndirection || !isPotentiallyIndirect(It)) {
403 ParamTypes.push_back(It.Ty);
404 if (!RetTy && NumReplaceableArgs == 1 && (It.Flags & IRTArg::REPLACABLE))
405 RetTy = It.Ty;
406 continue;
407 }
408
409 // The indirection pointer and the size of the value.
410 ParamTypes.push_back(IIRB.PtrTy);
411 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE))
412 ParamTypes.push_back(IIRB.Int32Ty);
413 }
414 if (!RetTy)
415 RetTy = IIRB.VoidTy;
416
417 return FunctionType::get(RetTy, ParamTypes, /*isVarArg=*/false);
418}
419
423 const DataLayout &DL,
424 InstrumentationCaches &ICaches) {
425 SmallVector<Value *> CallParams;
426
428 auto IP = IIRB.IRB.GetInsertPoint();
429
430 bool ForceIndirection = RequiresIndirection;
431 for (auto &It : IO.IRTArgs) {
432 if (!It.Enabled)
433 continue;
434 auto *&Param = ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
435 if (!Param || It.NoCache)
436 // Avoid passing the caches to the getter.
437 Param = It.GetterCB(*V, *It.Ty, IConf, IIRB);
438 assert(Param);
439
440 if (Param->getType()->isVoidTy()) {
441 Param = Constant::getNullValue(It.Ty);
442 } else if (Param->getType()->isAggregateType() ||
443 DL.getTypeSizeInBits(Param->getType()) >
444 DL.getTypeSizeInBits(It.Ty)) {
445 if (!isPotentiallyIndirect(It)) {
447 Twine("indirection needed for ") + It.Name + Twine(" in ") +
448 IO.getName() +
449 Twine(", but not indicated. Instrumentation is skipped"),
450 DS_Warning));
451 return nullptr;
452 }
453 ForceIndirection = true;
454 } else {
455 Param = tryToCast(IIRB.IRB, Param, It.Ty, DL);
456 }
457 CallParams.push_back(Param);
458 }
459
460 if (ForceIndirection) {
461 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
462
463 unsigned Offset = 0;
464 for (auto &It : IO.IRTArgs) {
465 if (!It.Enabled)
466 continue;
467
468 if (!isPotentiallyIndirect(It)) {
469 ++Offset;
470 continue;
471 }
472 auto *&CallParam = CallParams[Offset++];
473 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE)) {
474 CallParams.insert(&CallParam + 1, IIRB.IRB.getInt32(DL.getTypeStoreSize(
475 CallParam->getType())));
476 Offset += 1;
477 }
478
479 auto *&CachedParam =
480 ICaches.IndirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
481 if (CachedParam) {
482 CallParam = CachedParam;
483 continue;
484 }
485
486 auto *AI = IIRB.getAlloca(Fn, CallParam->getType());
487 IIRB.IRB.CreateStore(CallParam, AI);
488 CallParam = CachedParam = AI;
489 }
490 }
491
492 if (!ForceIndirection)
493 IIRB.IRB.SetInsertPoint(IP);
494 ensureDbgLoc(IIRB.IRB);
495
496 auto *FnTy = createLLVMSignature(IConf, IIRB, DL, ForceIndirection);
497 auto CompleteName =
498 IConf.getRTName(IO.IP.isPRE() ? "pre_" : "post_", IO.getName(),
499 ForceIndirection ? "_ind" : "");
500 auto FC = IIRB.IRB.GetInsertBlock()->getModule()->getOrInsertFunction(
501 CompleteName, FnTy);
502 auto *CI = IIRB.IRB.CreateCall(FC, CallParams);
503 CI->addFnAttr(Attribute::get(IIRB.Ctx, Attribute::WillReturn));
504
505 for (unsigned I = 0, E = IO.IRTArgs.size(); I < E; ++I) {
506 if (!IO.IRTArgs[I].Enabled)
507 continue;
508 if (!isReplacable(IO.IRTArgs[I]))
509 continue;
510 bool IsCustomReplaceable = IO.IRTArgs[I].Flags & IRTArg::REPLACABLE_CUSTOM;
511 Value *NewValue = FnTy->isVoidTy() || IsCustomReplaceable
512 ? ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(),
513 IO.IRTArgs[I].Name}]
514 : CI;
515 assert(NewValue);
516 if (ForceIndirection && !IsCustomReplaceable &&
517 isPotentiallyIndirect(IO.IRTArgs[I])) {
518 auto *Q =
519 ICaches
520 .IndirectArgCache[{IIRB.Epoch, IO.getName(), IO.IRTArgs[I].Name}];
521 NewValue = IIRB.IRB.CreateLoad(V->getType(), Q);
522 }
523 V = IO.IRTArgs[I].SetterCB(*V, *NewValue, IConf, IIRB);
524 }
525 return CI;
526}
527
529 ConfigTy *UserConfig) {
530 if (UserConfig)
531 Config = *UserConfig;
532
534 if (Config.has(PassPointer)) {
535 IRTArgs.push_back(
536 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
537 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
538 : IRTArg::NONE),
540 }
541 if (Config.has(PassPointerAS)) {
542 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
543 "The address space of the accessed pointer.",
545 }
546 if (Config.has(PassStoredValue)) {
547 IRTArgs.push_back(
548 IRTArg(getValueType(IIRB), "value", "The stored value.",
551 : IRTArg::NONE),
552 getValue));
553 }
554 if (Config.has(PassStoredValueSize)) {
555 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
556 "The size of the stored value.", IRTArg::NONE,
557 getValueSize));
558 }
559 if (Config.has(PassAlignment)) {
560 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
561 "The known access alignment.", IRTArg::NONE,
562 getAlignment));
563 }
564 if (Config.has(PassValueTypeId)) {
565 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
566 "The type id of the stored value.", IRTArg::NONE,
568 }
569 if (Config.has(PassAtomicityOrdering)) {
570 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
571 "The atomicity ordering of the store.",
573 }
574 if (Config.has(PassSyncScopeId)) {
575 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
576 "The sync scope id of the store.", IRTArg::NONE,
578 }
579 if (Config.has(PassIsVolatile)) {
580 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
581 "Flag indicating a volatile store.", IRTArg::NONE,
582 isVolatile));
583 }
584
585 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
586 IConf.addChoice(*this, IIRB.Ctx);
587}
588
591 auto &SI = cast<StoreInst>(V);
592 return SI.getPointerOperand();
593}
594
597 auto &SI = cast<StoreInst>(V);
598 SI.setOperand(SI.getPointerOperandIndex(), &NewV);
599 return &SI;
600}
601
604 auto &SI = cast<StoreInst>(V);
605 return getCI(&Ty, SI.getPointerAddressSpace());
606}
607
610 auto &SI = cast<StoreInst>(V);
611 return SI.getValueOperand();
612}
613
616 auto &SI = cast<StoreInst>(V);
617 auto &DL = SI.getDataLayout();
618 return getCI(&Ty, DL.getTypeStoreSize(SI.getValueOperand()->getType()));
619}
620
623 auto &SI = cast<StoreInst>(V);
624 return getCI(&Ty, SI.getAlign().value());
625}
626
629 auto &SI = cast<StoreInst>(V);
630 return getCI(&Ty, SI.getValueOperand()->getType()->getTypeID());
631}
632
636 auto &SI = cast<StoreInst>(V);
637 return getCI(&Ty, uint64_t(SI.getOrdering()));
638}
639
642 auto &SI = cast<StoreInst>(V);
643 return getCI(&Ty, uint64_t(SI.getSyncScopeID()));
644}
645
648 auto &SI = cast<StoreInst>(V);
649 return getCI(&Ty, SI.isVolatile());
650}
651
653 ConfigTy *UserConfig) {
655 if (UserConfig)
656 Config = *UserConfig;
657 if (Config.has(PassPointer)) {
658 IRTArgs.push_back(
659 IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
660 ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
661 : IRTArg::NONE),
663 }
664 if (Config.has(PassPointerAS)) {
665 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
666 "The address space of the accessed pointer.",
668 }
669 if (!IsPRE && Config.has(PassValue)) {
670 IRTArgs.push_back(
671 IRTArg(getValueType(IIRB), "value", "The loaded value.",
675 : IRTArg::NONE)
676 : IRTArg::NONE,
677 getValue, Config.has(ReplaceValue) ? replaceValue : nullptr));
678 }
679 if (Config.has(PassValueSize)) {
680 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
681 "The size of the loaded value.", IRTArg::NONE,
682 getValueSize));
683 }
684 if (Config.has(PassAlignment)) {
685 IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
686 "The known access alignment.", IRTArg::NONE,
687 getAlignment));
688 }
689 if (Config.has(PassValueTypeId)) {
690 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
691 "The type id of the loaded value.", IRTArg::NONE,
693 }
694 if (Config.has(PassAtomicityOrdering)) {
695 IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "atomicity_ordering",
696 "The atomicity ordering of the load.",
698 }
699 if (Config.has(PassSyncScopeId)) {
700 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
701 "The sync scope id of the load.", IRTArg::NONE,
703 }
704 if (Config.has(PassIsVolatile)) {
705 IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
706 "Flag indicating a volatile load.", IRTArg::NONE,
707 isVolatile));
708 }
709
710 addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
711 IConf.addChoice(*this, IIRB.Ctx);
712}
713
716 auto &LI = cast<LoadInst>(V);
717 return LI.getPointerOperand();
718}
719
722 auto &LI = cast<LoadInst>(V);
723 LI.setOperand(LI.getPointerOperandIndex(), &NewV);
724 return &LI;
725}
726
729 auto &LI = cast<LoadInst>(V);
730 return getCI(&Ty, LI.getPointerAddressSpace());
731}
732
735 return &V;
736}
737
740 auto &LI = cast<LoadInst>(V);
741 auto &DL = LI.getDataLayout();
742 return getCI(&Ty, DL.getTypeStoreSize(LI.getType()));
743}
744
747 auto &LI = cast<LoadInst>(V);
748 return getCI(&Ty, LI.getAlign().value());
749}
750
753 auto &LI = cast<LoadInst>(V);
754 return getCI(&Ty, LI.getType()->getTypeID());
755}
756
760 auto &LI = cast<LoadInst>(V);
761 return getCI(&Ty, uint64_t(LI.getOrdering()));
762}
763
766 auto &LI = cast<LoadInst>(V);
767 return getCI(&Ty, uint64_t(LI.getSyncScopeID()));
768}
769
772 auto &LI = cast<LoadInst>(V);
773 return getCI(&Ty, LI.isVolatile());
774}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
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.
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file contains the declarations for metadata subclasses.
#define T
ModuleAnalysisManager MAM
if(PassOpts->AAPipeline)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
This class represents a function call, abstracting a target machine's calling convention.
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
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.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:728
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
PointerType * getType() const
Global values are always pointers.
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.
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:67
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition Module.h:283
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
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
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
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:318
Changed
initializer< Ty > init(const Ty &Val)
bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile, LLVMContext &Ctx)
Read the configuration from the file with path InputFile into /p IConf.
void writeConfigToJSON(InstrumentationConfig &IConf, StringRef OutputFile, LLVMContext &Ctx)
Write the configuration in /p IConf to the file with path OutputFile.
void printRuntimeStub(const InstrumentationConfig &IConf, StringRef StubRuntimeName, LLVMContext &Ctx)
Print a runtime stub file with the implementation of the instrumentation runtime functions correspond...
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:557
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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
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...
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.
std::unique_ptr< BaseConfigurationOption > HostEnabled
std::unique_ptr< BaseConfigurationOption > GPUEnabled
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 > TargetRegex
EnumeratedArray< StringMap< InstrumentationOpportunity * >, InstrumentationLocation::KindTy > IChoices
The map registered instrumentation opportunities.
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 * 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.
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 * 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 * 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 * getAtomicityOrdering(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)