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