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
14#include "llvm/Transforms/IPO/Instrumentor.h"
15#include "llvm/Transforms/IPO/InstrumentorConfigFile.h"
16#include "llvm/Transforms/IPO/InstrumentorRuntimeHelper.h"
17#include "llvm/Transforms/IPO/InstrumentorStubPrinter.h"
18
19#include "llvm/ADT/PostOrderIterator.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/iterator.h"
26#include "llvm/Analysis/ValueTracking.h"
27#include "llvm/Demangle/Demangle.h"
28#include "llvm/IR/Constant.h"
29#include "llvm/IR/Constants.h"
30#include "llvm/IR/DataLayout.h"
31#include "llvm/IR/DebugInfoMetadata.h"
32#include "llvm/IR/DiagnosticInfo.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"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/IntrinsicInst.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"
45#include "llvm/IRReader/IRReader.h"
46#include "llvm/Support/CommandLine.h"
47#include "llvm/Support/ErrorHandling.h"
48#include "llvm/Support/Regex.h"
49#include "llvm/Support/VirtualFileSystem.h"
50#include "llvm/Transforms/IPO/InstrumentorUtils.h"
51#include "llvm/Transforms/Utils/ModuleUtils.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",
72 cl::desc(
73 "Write the instrumentor configuration into the specified JSON file"),
74 cl::init(Val: ""));
75
76/// The user option to specify input JSON files to read the configuration from.
77static cl::list<std::string>
78 ConfigFiles("instrumentor-read-config-files",
79 cl::desc("Read the instrumentor configuration from the "
80 "specified JSON files (comma separated)"),
81 cl::ZeroOrMore, cl::CommaSeparated);
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(Val: ""));
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() || VTy->isVectorTy())
113 return V;
114 TypeSize RequestedSize = DL.getTypeSizeInBits(Ty);
115 TypeSize ValueSize = DL.getTypeSizeInBits(Ty: 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
158Constant *getSubTypeID(Type &OpTy, Type &ReqTy) {
159 switch (OpTy.getTypeID()) {
160 case Type::TypeID::ArrayTyID:
161 case Type::TypeID::FixedVectorTyID:
162 case Type::TypeID::ScalableVectorTyID:
163 return getCI(IT: &ReqTy, Val: OpTy.getContainedType(i: 0)->getTypeID());
164 default:
165 break;
166 }
167
168 return getCI(IT: &ReqTy, Val: -1, /*IsSigned=*/true);
169}
170
171/// The core of the instrumentor pass, which instruments the module as the
172/// instrumentation configuration mandates.
173class InstrumentorImpl final {
174public:
175 /// Construct an instrumentor implementation using the configuration \p IConf.
176 InstrumentorImpl(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
177 Module &M)
178 : IConf(IConf), M(M), IIRB(IIRB) {}
179
180 /// Instrument the module, public entry point.
181 bool instrument();
182
183 // Reset the state to allow reuse of the instrumentor with a different
184 // configuration.
185 void clear() {
186 InstChoicesPRE.clear();
187 InstChoicesPOST.clear();
188 ParsedFunctionRegex = Regex();
189 }
190
191private:
192 /// Indicate if the module should be instrumented based on the target.
193 bool shouldInstrumentTarget();
194
195 /// Indicate if the function \p Fn should be instrumented.
196 bool shouldInstrumentFunction(Function &Fn);
197 bool shouldInstrumentGlobalVariable(GlobalVariable &GV);
198
199 /// Instrument instruction \p I if needed, and use the argument caches in \p
200 /// ICaches.
201 bool instrumentInstruction(Instruction &I, InstrumentationCaches &ICaches);
202
203 /// Instrument function \p Fn.
204 bool instrumentFunction(Function &Fn);
205 bool instrumentModule();
206
207 /// The instrumentation opportunities for instructions indexed by
208 /// their opcode.
209 DenseMap<unsigned, InstrumentationOpportunity *> InstChoicesPRE,
210 InstChoicesPOST;
211
212 /// The instrumentor configuration.
213 InstrumentationConfig &IConf;
214
215 /// The function regex filter, if any.
216 Regex ParsedFunctionRegex;
217
218 /// The underlying module.
219 Module &M;
220
221protected:
222 /// A special IR builder that keeps track of the inserted instructions.
223 InstrumentorIRBuilderTy &IIRB;
224};
225
226} // end anonymous namespace
227
228static Regex createRegex(StringRef Str, StringRef Name, LLVMContext &Ctx) {
229 if (!Str.empty()) {
230 Regex RX(Str);
231 std::string ErrMsg;
232 if (!RX.isValid(Error&: ErrMsg)) {
233 Ctx.diagnose(DI: DiagnosticInfoInstrumentation(
234 Twine("failed to parse ") + Name + " regex: " + ErrMsg, DS_Error));
235 return Regex();
236 }
237 return RX;
238 }
239 return Regex();
240}
241
242bool InstrumentorImpl::shouldInstrumentTarget() {
243 const Triple &T = M.getTargetTriple();
244 const bool IsGPU = T.isAMDGPU() || T.isNVPTX();
245
246 bool RegexMatches = true;
247 Regex RX = createRegex(Str: IConf.TargetRegex->getString(), Name: "target", Ctx&: IIRB.Ctx);
248 if (RX.isValid())
249 RegexMatches = RX.match(String: T.str());
250
251 // Only instrument the module if the target has to be instrumented.
252 return ((IsGPU && IConf.GPUEnabled->getBool()) ||
253 (!IsGPU && IConf.HostEnabled->getBool())) &&
254 RegexMatches;
255}
256
257bool InstrumentorImpl::shouldInstrumentFunction(Function &Fn) {
258 if (Fn.isDeclaration())
259 return false;
260 bool RegexMatches = true;
261 if (ParsedFunctionRegex.isValid())
262 RegexMatches = ParsedFunctionRegex.match(String: Fn.getName());
263 return (RegexMatches && !Fn.getName().starts_with(Prefix: IConf.getRTName())) ||
264 Fn.hasFnAttribute(Kind: "instrument");
265}
266
267bool InstrumentorImpl::shouldInstrumentGlobalVariable(GlobalVariable &GV) {
268 return !GV.getName().starts_with(Prefix: "llvm.") &&
269 !GV.getName().starts_with(Prefix: IConf.getRTName());
270}
271
272bool InstrumentorImpl::instrumentInstruction(Instruction &I,
273 InstrumentationCaches &ICaches) {
274 bool Changed = false;
275
276 // Skip instrumentation instructions.
277 if (IIRB.NewInsts.contains(Val: &I))
278 return Changed;
279
280 // Count epochs eagerly.
281 ++IIRB.Epoch;
282
283 Value *IPtr = &I;
284 if (auto *IO = InstChoicesPRE.lookup(Val: I.getOpcode())) {
285 IIRB.IRB.SetInsertPoint(&I);
286 ensureDbgLoc(IRB&: IIRB.IRB);
287 IO->instrument(V&: IPtr, Changed, IConf, IIRB, ICaches);
288 }
289
290 if (auto *IO = InstChoicesPOST.lookup(Val: I.getOpcode())) {
291 IIRB.IRB.SetInsertPoint(I.getNextNode());
292 ensureDbgLoc(IRB&: IIRB.IRB);
293 IO->instrument(V&: IPtr, Changed, IConf, IIRB, ICaches);
294 }
295 IIRB.returnAllocas();
296
297 return Changed;
298}
299
300bool InstrumentorImpl::instrumentFunction(Function &Fn) {
301 bool Changed = false;
302 if (!shouldInstrumentFunction(Fn))
303 return Changed;
304
305 InstrumentationCaches ICaches;
306 SmallVector<Instruction *> FinalTIs;
307 ReversePostOrderTraversal<Function *> RPOT(&Fn);
308 for (auto &It : RPOT) {
309 for (auto &I : *It)
310 Changed |= instrumentInstruction(I, ICaches);
311
312 auto *TI = It->getTerminator();
313 if (!TI->getNumSuccessors())
314 FinalTIs.push_back(Elt: TI);
315 }
316
317 Value *FPtr = &Fn;
318 for (auto &[Name, IO] :
319 IConf.IChoices[InstrumentationLocation::FUNCTION_PRE]) {
320 if (!IO->Enabled)
321 continue;
322 // Count epochs eagerly.
323 ++IIRB.Epoch;
324
325 IIRB.IRB.SetInsertPoint(
326 cast<Function>(Val: FPtr)->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
327 ensureDbgLoc(IRB&: IIRB.IRB);
328 IO->instrument(V&: FPtr, Changed, IConf, IIRB, ICaches);
329 IIRB.returnAllocas();
330 }
331
332 for (auto &[Name, IO] :
333 IConf.IChoices[InstrumentationLocation::FUNCTION_POST]) {
334 if (!IO->Enabled)
335 continue;
336 // Count epochs eagerly.
337 ++IIRB.Epoch;
338
339 for (Instruction *FinalTI : FinalTIs) {
340 IIRB.IRB.SetInsertPoint(FinalTI);
341 ensureDbgLoc(IRB&: IIRB.IRB);
342 IO->instrument(V&: FPtr, Changed, IConf, IIRB, ICaches);
343 IIRB.returnAllocas();
344 }
345 }
346 return Changed;
347}
348
349bool InstrumentorImpl::instrumentModule() {
350 SmallVector<GlobalVariable *> Globals;
351 Globals.reserve(N: M.global_size());
352 for (GlobalVariable &GV : M.globals()) {
353 // llvm.metadata contains globals such as llvm.used.
354 if (GV.getSection() == "llvm.metadata" ||
355 GV.getName() == "llvm.global_dtors" ||
356 GV.getName() == "llvm.global_ctors")
357 continue;
358 Globals.push_back(Elt: &GV);
359 }
360
361 auto CreateYtor = [&](bool Ctor) {
362 Function *YtorFn = Function::Create(
363 Ty: FunctionType::get(Result: IIRB.VoidTy, isVarArg: false), Linkage: GlobalValue::PrivateLinkage,
364 N: IConf.getRTName(Prefix: Ctor ? "ctor" : "dtor", Name: ""), M);
365
366 auto *EntryBB = BasicBlock::Create(Context&: IIRB.Ctx, Name: "entry", Parent: YtorFn);
367 IIRB.IRB.SetInsertPoint(TheBB: EntryBB, IP: EntryBB->begin());
368 ensureDbgLoc(IRB&: IIRB.IRB);
369 IIRB.IRB.CreateRetVoid();
370
371 if (Ctor)
372 appendToGlobalCtors(M, F: YtorFn, Priority: 1000);
373 else
374 appendToGlobalDtors(M, F: YtorFn, Priority: 1000);
375 return YtorFn;
376 };
377
378 InstrumentationCaches ICaches;
379
380 Function *CtorFn = nullptr, *DtorFn = nullptr;
381 bool Changed = false;
382 for (auto Loc : {InstrumentationLocation::MODULE_PRE,
383 InstrumentationLocation::MODULE_POST}) {
384 bool IsPRE = InstrumentationLocation::isPRE(Kind: Loc);
385 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
386 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
387 auto *IO = ChoiceIt.second;
388 if (!IO->Enabled)
389 continue;
390 if (!YtorFn) {
391 YtorFn = CreateYtor(IsPRE);
392 Changed = true;
393 }
394 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
395 ensureDbgLoc(IRB&: IIRB.IRB);
396 Value *YtorPtr = YtorFn;
397
398 // Count epochs eagerly.
399 ++IIRB.Epoch;
400
401 IO->instrument(V&: YtorPtr, Changed, IConf, IIRB, ICaches);
402 IIRB.returnAllocas();
403 }
404 }
405
406 for (auto Loc : {InstrumentationLocation::GLOBAL_PRE,
407 InstrumentationLocation::GLOBAL_POST}) {
408 bool IsPRE = InstrumentationLocation::isPRE(Kind: Loc);
409 Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
410 for (auto &ChoiceIt : IConf.IChoices[Loc]) {
411 auto *IO = ChoiceIt.second;
412 if (!IO->Enabled)
413 continue;
414 if (!YtorFn) {
415 YtorFn = CreateYtor(IsPRE);
416 Changed = true;
417 }
418 for (GlobalVariable *GV : Globals) {
419 if (!shouldInstrumentGlobalVariable(GV&: *GV))
420 continue;
421 if (IsPRE)
422 IIRB.IRB.SetInsertPoint(YtorFn->getEntryBlock().getTerminator());
423 else
424 IIRB.IRB.SetInsertPointPastAllocas(YtorFn);
425 ensureDbgLoc(IRB&: IIRB.IRB);
426 Value *GVPtr = GV;
427
428 // Count epochs eagerly.
429 ++IIRB.Epoch;
430
431 IO->instrument(V&: GVPtr, Changed, IConf, IIRB, ICaches);
432 IIRB.returnAllocas();
433 }
434 }
435 }
436
437 return Changed;
438}
439
440bool InstrumentorImpl::instrument() {
441 bool Changed = false;
442 if (!shouldInstrumentTarget())
443 return Changed;
444
445 StringRef FunctionRegexStr = IConf.FunctionRegex->getString();
446 ParsedFunctionRegex = createRegex(Str: FunctionRegexStr, Name: "function", Ctx&: IIRB.Ctx);
447
448 // Helper to register an IO for all its opcodes.
449 auto RegisterForAllOpcodes = [](auto &InstChoices,
450 InstrumentationOpportunity *IO) {
451 ArrayRef<unsigned> Opcodes = IO->getAllOpcodes();
452 // Register for all opcodes.
453 for (unsigned Opcode : Opcodes)
454 InstChoices[Opcode] = IO;
455 };
456
457 for (auto &[Name, IO] :
458 IConf.IChoices[InstrumentationLocation::INSTRUCTION_PRE])
459 if (IO->Enabled)
460 RegisterForAllOpcodes(InstChoicesPRE, IO);
461 for (auto &[Name, IO] :
462 IConf.IChoices[InstrumentationLocation::INSTRUCTION_POST])
463 if (IO->Enabled)
464 RegisterForAllOpcodes(InstChoicesPOST, IO);
465 Changed |= instrumentModule();
466
467 for (Function &Fn : M)
468 Changed |= instrumentFunction(Fn);
469
470 return Changed;
471}
472
473InstrumentorPass::InstrumentorPass(IntrusiveRefCntPtr<vfs::FileSystem> FS,
474 InstrumentationConfig *IC,
475 InstrumentorIRBuilderTy *IIRB)
476 : FS(FS), UserIConf(IC), UserIIRB(IIRB) {
477 if (!FS)
478 this->FS = vfs::getRealFileSystem();
479}
480
481PreservedAnalyses InstrumentorPass::run(Module &M, InstrumentationConfig &IConf,
482 InstrumentorIRBuilderTy &IIRB,
483 bool ReadConfig) {
484 bool Changed = false;
485 InstrumentorImpl Impl(IConf, IIRB, M);
486
487 // If this is a configuration driven run, iterate over all configurations
488 // provided by the user, if not, use the config as is and run the instrumentor
489 // once.
490 if (ReadConfig)
491 readConfigPathsFile(InputFile: ConfigPathsFile, Configs&: ConfigFiles, Ctx&: IIRB.Ctx, FS&: *FS);
492
493 bool MultipleConfigs = ConfigFiles.size() > 1;
494 unsigned Idx = 0;
495 do {
496 std::string ConfigFile =
497 ReadConfig && !ConfigFiles.empty() ? ConfigFiles[Idx] : "";
498
499 // Initialize the config to the base state but keep the caches around.
500 Impl.clear();
501 IConf.init(IIRB);
502
503 if (!readConfigFromJSON(IConf, InputFile: ConfigFile, Ctx&: IIRB.Ctx, FS&: *FS))
504 continue;
505
506 writeConfigToJSON(IConf,
507 OutputFile: MultipleConfigs
508 ? OutputConfigFile + "." + std::to_string(val: Idx)
509 : OutputConfigFile,
510 Ctx&: IIRB.Ctx);
511
512 printRuntimeStub(IConf, StubRuntimeName: IConf.RuntimeStubsFile->getString(), Ctx&: IIRB.Ctx);
513
514 Changed |= Impl.instrument();
515 } while (++Idx < ConfigFiles.size());
516
517 if (!Changed)
518 return PreservedAnalyses::all();
519 return PreservedAnalyses::none();
520}
521
522PreservedAnalyses InstrumentorPass::run(Module &M, ModuleAnalysisManager &MAM) {
523 // Only create them if the user did not provide them.
524 std::unique_ptr<InstrumentationConfig> IConfInt(
525 !UserIConf ? new InstrumentationConfig() : nullptr);
526 std::unique_ptr<InstrumentorIRBuilderTy> IIRBInt(
527 !UserIIRB ? new InstrumentorIRBuilderTy(M) : nullptr);
528
529 auto *IConf = IConfInt ? IConfInt.get() : UserIConf;
530 auto *IIRB = IIRBInt ? IIRBInt.get() : UserIIRB;
531
532 auto PA = run(M, IConf&: *IConf, IIRB&: *IIRB, ReadConfig: !UserIConf);
533
534 assert(!verifyModule(M, &errs()));
535 return PA;
536}
537
538std::unique_ptr<BaseConfigurationOption>
539BaseConfigurationOption::createBoolOption(InstrumentationConfig &IConf,
540 StringRef Name, StringRef Description,
541 bool DefaultValue) {
542 auto BCO =
543 std::make_unique<BaseConfigurationOption>(args&: Name, args&: Description, args: BOOLEAN);
544 BCO->setBool(DefaultValue);
545 IConf.addBaseChoice(BCO: BCO.get());
546 return BCO;
547}
548
549std::unique_ptr<BaseConfigurationOption>
550BaseConfigurationOption::createStringOption(InstrumentationConfig &IConf,
551 StringRef Name,
552 StringRef Description,
553 StringRef DefaultValue) {
554 auto BCO =
555 std::make_unique<BaseConfigurationOption>(args&: Name, args&: Description, args: STRING);
556 BCO->setString(DefaultValue);
557 IConf.addBaseChoice(BCO: BCO.get());
558 return BCO;
559}
560
561void InstrumentationConfig::populate(InstrumentorIRBuilderTy &IIRB) {
562 /// List of all instrumentation opportunities.
563 BasePointerIO::populate(IConf&: *this, IIRB);
564 ModuleIO::populate(IConf&: *this, IIRB);
565 GlobalVarIO::populate(IConf&: *this, IIRB);
566 FunctionIO::populate(IConf&: *this, IIRB);
567 AllocaIO::populate(IConf&: *this, IIRB);
568 UnreachableIO::populate(IConf&: *this, IIRB);
569 LoadIO::populate(IConf&: *this, IIRB);
570 StoreIO::populate(IConf&: *this, IIRB);
571 CastIO::populate(IConf&: *this, IIRB);
572 NumericIO::populate(IConf&: *this, IIRB);
573 CompareIO::populate(IConf&: *this, IIRB);
574}
575
576void InstrumentationConfig::addChoice(InstrumentationOpportunity &IO,
577 LLVMContext &Ctx) {
578 auto *&ICPtr = IChoices[IO.getLocationKind()][IO.getName()];
579 if (ICPtr) {
580 Ctx.diagnose(DI: DiagnosticInfoInstrumentation(
581 Twine("registered two instrumentation opportunities for the same "
582 "location (") +
583 ICPtr->getName() + Twine(" vs ") + IO.getName() + Twine(")"),
584 DS_Warning));
585 }
586 ICPtr = &IO;
587}
588
589Value *
590InstrumentationConfig::getBasePointerInfo(Value &V,
591 InstrumentorIRBuilderTy &IIRB) {
592 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
593
594 Value *Obj;
595 {
596 Value *&UnderlyingObj = UnderlyingObjsMap[&V];
597 if (!UnderlyingObj)
598 UnderlyingObj = const_cast<Value *>(getUnderlyingObjectAggressive(V: &V));
599 Obj = UnderlyingObj;
600 }
601
602 Value *&BPI = BasePointerInfoMap[{Obj, Fn}];
603 if (BPI)
604 return BPI;
605
606 auto *BPIO =
607 IChoices[InstrumentationLocation::SPECIAL_VALUE]["base_pointer_info"];
608 if (!BPIO || !BPIO->Enabled) {
609 IIRB.Ctx.diagnose(DI: DiagnosticInfoInstrumentation(
610 "Base pointer info disabled but required, passing nullptr.",
611 DS_Warning));
612 return BPI = Constant::getNullValue(Ty: BPIO->getRetTy(Ctx&: IIRB.Ctx));
613 }
614
615 IRBuilderBase::InsertPointGuard IP(IIRB.IRB);
616 if (auto *BasePtrI = dyn_cast<Instruction>(Val: Obj)) {
617 std::optional<BasicBlock::iterator> IP =
618 BasePtrI->getInsertionPointAfterDef();
619 if (IP) {
620 IIRB.IRB.SetInsertPoint(*IP);
621 } else {
622 IIRB.Ctx.diagnose(DI: DiagnosticInfoInstrumentation(
623 "Base pointer info could not be placed, passing nullptr.",
624 DS_Warning));
625 return BPI = Constant::getNullValue(Ty: BPIO->getRetTy(Ctx&: IIRB.Ctx));
626 }
627 } else if (isa<Constant>(Val: Obj) || isa<Argument>(Val: Obj)) {
628 IIRB.IRB.SetInsertPointPastAllocas(IIRB.IRB.GetInsertBlock()->getParent());
629 } else {
630 LLVM_DEBUG(Obj->dump());
631 llvm_unreachable("Unexpected base pointer!");
632 }
633 ensureDbgLoc(IRB&: IIRB.IRB);
634
635 // Use fresh caches for safety, as this function may be called from
636 // another instrumentation opportunity.
637 bool Changed;
638 InstrumentationCaches ICaches;
639 BPI = BPIO->instrument(V&: Obj, Changed, IConf&: *this, IIRB, ICaches);
640 IIRB.returnAllocas();
641 if (!BPI)
642 BPI = Constant::getNullValue(Ty: BPIO->getRetTy(Ctx&: IIRB.Ctx));
643 return BPI;
644}
645
646Value *InstrumentationOpportunity::getIdPre(Value &V, Type &Ty,
647 InstrumentationConfig &IConf,
648 InstrumentorIRBuilderTy &IIRB) {
649 return getCI(IT: &Ty, Val: getIdFromEpoch(CurrentEpoch: IIRB.Epoch));
650}
651
652Value *InstrumentationOpportunity::getIdPost(Value &V, Type &Ty,
653 InstrumentationConfig &IConf,
654 InstrumentorIRBuilderTy &IIRB) {
655 return getCI(IT: &Ty, Val: -getIdFromEpoch(CurrentEpoch: IIRB.Epoch), /*IsSigned=*/true);
656}
657
658Value *InstrumentationOpportunity::forceCast(Value &V, Type &Ty,
659 InstrumentorIRBuilderTy &IIRB) {
660 if (V.getType()->isVoidTy())
661 return Ty.isVoidTy() ? &V : Constant::getNullValue(Ty: &Ty);
662 return tryToCast(IRB&: IIRB.IRB, V: &V, Ty: &Ty,
663 DL: IIRB.IRB.GetInsertBlock()->getDataLayout());
664}
665
666Value *InstrumentationOpportunity::replaceValue(Value &V, Value &NewV,
667 InstrumentationConfig &IConf,
668 InstrumentorIRBuilderTy &IIRB) {
669 if (V.getType()->isVoidTy())
670 return &V;
671
672 auto *NewVCasted = &NewV;
673 if (auto *I = dyn_cast<Instruction>(Val: &NewV)) {
674 IRBuilderBase::InsertPointGuard IPG(IIRB.IRB);
675 IIRB.IRB.SetInsertPoint(I->getNextNode());
676 ensureDbgLoc(IRB&: IIRB.IRB);
677 NewVCasted = tryToCast(IRB&: IIRB.IRB, V: &NewV, Ty: V.getType(), DL: IIRB.DL,
678 /*AllowTruncate=*/true);
679 }
680 V.replaceUsesWithIf(New: NewVCasted, ShouldReplace: [&](Use &U) {
681 if (IIRB.NewInsts.lookup(Val: cast<Instruction>(Val: U.getUser())) == IIRB.Epoch)
682 return false;
683 return !isa<LifetimeIntrinsic>(Val: U.getUser()) && !U.getUser()->isDroppable();
684 });
685
686 return &V;
687}
688
689IRTCallDescription::IRTCallDescription(InstrumentationOpportunity &IO,
690 Type *RetTy)
691 : IO(IO), RetTy(RetTy) {
692 for (auto &It : IO.IRTArgs) {
693 if (!It.Enabled)
694 continue;
695 NumReplaceableArgs += bool(It.Flags & IRTArg::REPLACABLE);
696 MightRequireIndirection |= It.Flags & IRTArg::POTENTIALLY_INDIRECT;
697 }
698 if (NumReplaceableArgs > 1)
699 MightRequireIndirection = RequiresIndirection = true;
700}
701
702FunctionType *IRTCallDescription::createLLVMSignature(
703 InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
704 const DataLayout &DL, bool ForceIndirection) {
705 assert(((ForceIndirection && MightRequireIndirection) ||
706 (!ForceIndirection && !RequiresIndirection)) &&
707 "Wrong indirection setting!");
708
709 SmallVector<Type *> ParamTypes;
710 for (auto &It : IO.IRTArgs) {
711 if (!It.Enabled)
712 continue;
713 if (!ForceIndirection || !isPotentiallyIndirect(IRTA&: It)) {
714 ParamTypes.push_back(Elt: It.Ty);
715 if (!RetTy && NumReplaceableArgs == 1 && (It.Flags & IRTArg::REPLACABLE))
716 RetTy = It.Ty;
717 continue;
718 }
719
720 // The indirection pointer and the size of the value.
721 ParamTypes.push_back(Elt: IIRB.PtrTy);
722 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE))
723 ParamTypes.push_back(Elt: IIRB.Int32Ty);
724 }
725 if (!RetTy)
726 RetTy = IIRB.VoidTy;
727
728 return FunctionType::get(Result: RetTy, Params: ParamTypes, /*isVarArg=*/false);
729}
730
731CallInst *IRTCallDescription::createLLVMCall(Value *&V,
732 InstrumentationConfig &IConf,
733 InstrumentorIRBuilderTy &IIRB,
734 const DataLayout &DL,
735 InstrumentationCaches &ICaches) {
736 SmallVector<Value *> CallParams;
737
738 IRBuilderBase::InsertPointGuard IRP(IIRB.IRB);
739 auto IP = IIRB.IRB.GetInsertPoint();
740
741 bool ForceIndirection = RequiresIndirection;
742 for (auto &It : IO.IRTArgs) {
743 if (!It.Enabled)
744 continue;
745 auto *&Param = ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
746 if (!Param || It.NoCache)
747 // Avoid passing the caches to the getter.
748 Param = It.GetterCB(*V, *It.Ty, IConf, IIRB);
749 assert(Param);
750
751 if (Param->getType()->isVoidTy()) {
752 Param = Constant::getNullValue(Ty: It.Ty);
753 } else if (Param->getType()->isAggregateType() ||
754 Param->getType()->isVectorTy() ||
755 DL.getTypeSizeInBits(Ty: Param->getType()) >
756 DL.getTypeSizeInBits(Ty: It.Ty)) {
757 if (!isPotentiallyIndirect(IRTA&: It)) {
758 IIRB.Ctx.diagnose(DI: DiagnosticInfoInstrumentation(
759 Twine("indirection needed for ") + It.Name + Twine(" in ") +
760 IO.getName() +
761 Twine(", but not indicated. Instrumentation is skipped"),
762 DS_Warning));
763 return nullptr;
764 }
765 ForceIndirection = true;
766 } else {
767 Param = tryToCast(IRB&: IIRB.IRB, V: Param, Ty: It.Ty, DL);
768 }
769 CallParams.push_back(Elt: Param);
770 }
771
772 if (ForceIndirection) {
773 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
774
775 unsigned Offset = 0;
776 for (auto &It : IO.IRTArgs) {
777 if (!It.Enabled)
778 continue;
779
780 if (!isPotentiallyIndirect(IRTA&: It)) {
781 ++Offset;
782 continue;
783 }
784 auto *&CallParam = CallParams[Offset++];
785 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE)) {
786 CallParams.insert(I: &CallParam + 1, Elt: IIRB.IRB.getInt32(C: DL.getTypeStoreSize(
787 Ty: CallParam->getType())));
788 Offset += 1;
789 }
790
791 auto *&CachedParam =
792 ICaches.IndirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
793 if (CachedParam) {
794 CallParam = CachedParam;
795 continue;
796 }
797
798 auto *AI = IIRB.getAlloca(Fn, Ty: CallParam->getType());
799 IIRB.IRB.CreateStore(Val: CallParam, Ptr: AI);
800 CallParam = CachedParam = AI;
801 }
802 }
803
804 if (!ForceIndirection)
805 IIRB.IRB.SetInsertPoint(IP);
806 ensureDbgLoc(IRB&: IIRB.IRB);
807
808 auto *FnTy = createLLVMSignature(IConf, IIRB, DL, ForceIndirection);
809 auto CompleteName =
810 IConf.getRTName(Prefix: IO.IP.isPRE() ? "pre_" : "post_", Name: IO.getName(),
811 Suffix1: ForceIndirection ? "_ind" : "");
812 auto FC = IIRB.IRB.GetInsertBlock()->getModule()->getOrInsertFunction(
813 Name: CompleteName, T: FnTy);
814 auto *CI = IIRB.IRB.CreateCall(Callee: FC, Args: CallParams);
815 CI->addFnAttr(Attr: Attribute::get(Context&: IIRB.Ctx, Kind: Attribute::WillReturn));
816
817 for (unsigned I = 0, E = IO.IRTArgs.size(); I < E; ++I) {
818 if (!IO.IRTArgs[I].Enabled)
819 continue;
820 if (!isReplacable(IRTA&: IO.IRTArgs[I]))
821 continue;
822 bool IsCustomReplaceable = IO.IRTArgs[I].Flags & IRTArg::REPLACABLE_CUSTOM;
823 Value *NewValue = FnTy->isVoidTy() || IsCustomReplaceable
824 ? ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(),
825 IO.IRTArgs[I].Name}]
826 : CI;
827 assert(NewValue);
828 if (ForceIndirection && !IsCustomReplaceable &&
829 isPotentiallyIndirect(IRTA&: IO.IRTArgs[I])) {
830 auto *Q =
831 ICaches
832 .IndirectArgCache[{IIRB.Epoch, IO.getName(), IO.IRTArgs[I].Name}];
833 NewValue = IIRB.IRB.CreateLoad(Ty: V->getType(), Ptr: Q);
834 }
835 V = IO.IRTArgs[I].SetterCB(*V, *NewValue, IConf, IIRB);
836 }
837 return CI;
838}
839
840template <typename Ty> constexpr static Value *getValue(Ty &ValueOrUse) {
841 if constexpr (std::is_same<Ty, Use>::value)
842 return ValueOrUse.get();
843 else
844 return static_cast<Value *>(&ValueOrUse);
845}
846
847template <typename Range>
848static Value *createValuePack(const Range &R, InstrumentationConfig &IConf,
849 InstrumentorIRBuilderTy &IIRB) {
850 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
851 auto *I32Ty = IIRB.IRB.getInt32Ty();
852 SmallVector<Constant *> ConstantValues;
853 SmallVector<std::pair<Value *, uint32_t>> Values;
854 SmallVector<Type *> Types;
855 for (auto &RE : R) {
856 Value *V = getValue(RE);
857 if (!V->getType()->isSized())
858 continue;
859 auto VSize = IIRB.DL.getTypeAllocSize(Ty: V->getType());
860 ConstantValues.push_back(Elt: getCI(IT: I32Ty, Val: VSize));
861 Types.push_back(Elt: I32Ty);
862 ConstantValues.push_back(Elt: getCI(IT: I32Ty, Val: V->getType()->getTypeID()));
863 Types.push_back(Elt: I32Ty);
864 if (uint32_t MisAlign = VSize % 8) {
865 Types.push_back(Elt: ArrayType::get(ElementType: IIRB.Int8Ty, NumElements: 8 - MisAlign));
866 ConstantValues.push_back(Elt: ConstantArray::getNullValue(Ty: Types.back()));
867 }
868 Types.push_back(Elt: V->getType());
869 if (auto *C = dyn_cast<Constant>(Val: V)) {
870 ConstantValues.push_back(Elt: C);
871 continue;
872 }
873 Values.push_back(Elt: {V, ConstantValues.size()});
874 ConstantValues.push_back(Elt: Constant::getNullValue(Ty: V->getType()));
875 }
876 if (Types.empty())
877 return ConstantPointerNull::get(T: IIRB.PtrTy);
878
879 StructType *STy = StructType::get(Context&: Fn->getContext(), Elements: Types, /*isPacked=*/true);
880 Constant *Initializer = ConstantStruct::get(T: STy, V: ConstantValues);
881
882 GlobalVariable *&GV = IConf.ConstantGlobalsCache[Initializer];
883 if (!GV)
884 GV = new GlobalVariable(*Fn->getParent(), STy, false,
885 GlobalValue::InternalLinkage, Initializer,
886 IConf.getRTName(Prefix: "", Name: "value_pack"));
887
888 auto *AI = IIRB.getAlloca(Fn, Ty: STy);
889 IIRB.IRB.CreateMemCpy(Dst: AI, DstAlign: AI->getAlign(), Src: GV, SrcAlign: MaybeAlign(GV->getAlignment()),
890 Size: IIRB.DL.getTypeAllocSize(Ty: STy));
891 for (auto [Param, Idx] : Values) {
892 auto *Ptr = IIRB.IRB.CreateStructGEP(Ty: STy, Ptr: AI, Idx);
893 IIRB.IRB.CreateStore(Val: Param, Ptr);
894 }
895 return AI;
896}
897
898template <typename Range>
899static void readValuePack(const Range &R, Value &Pack,
900 InstrumentorIRBuilderTy &IIRB,
901 function_ref<void(int, Value *)> SetterCB) {
902 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
903 auto &DL = Fn->getDataLayout();
904 SmallVector<Value *> ParameterValues;
905 unsigned Offset = 0;
906 for (const auto &[Idx, RE] : enumerate(R)) {
907 Value *V = getValue(RE);
908 if (!V->getType()->isSized())
909 continue;
910 Offset += 8;
911 auto VSize = DL.getTypeAllocSize(Ty: V->getType());
912 auto Padding = alignTo(Size: VSize, Align: 8) - VSize;
913 Offset += Padding;
914 auto *Ptr = IIRB.IRB.CreateConstInBoundsGEP1_32(Ty: IIRB.Int8Ty, Ptr: &Pack, Idx0: Offset);
915 auto *NewV = IIRB.IRB.CreateLoad(Ty: V->getType(), Ptr);
916 SetterCB(Idx, NewV);
917 Offset += VSize;
918 }
919}
920
921Value *BaseInstructionIO::getOpcode(Value &V, Type &Ty,
922 InstrumentationConfig &IConf,
923 InstrumentorIRBuilderTy &IIRB) {
924 auto &I = cast<Instruction>(Val&: V);
925 return getCI(IT: &Ty, Val: I.getOpcode());
926}
927
928Value *BaseInstructionIO::getTypeSize(Value &V, Type &Ty,
929 InstrumentationConfig &IConf,
930 InstrumentorIRBuilderTy &IIRB) {
931 auto &I = cast<Instruction>(Val&: V);
932 auto &DL = I.getDataLayout();
933 return getCI(IT: &Ty, Val: DL.getTypeStoreSize(Ty: V.getType()));
934}
935
936Value *BaseInstructionIO::getLeftOperand(Value &V, Type &Ty,
937 InstrumentationConfig &IConf,
938 InstrumentorIRBuilderTy &IIRB) {
939 auto &I = cast<Instruction>(Val&: V);
940 return I.getOperand(i: 0);
941}
942
943Value *BaseInstructionIO::getRightOperand(Value &V, Type &Ty,
944 InstrumentationConfig &IConf,
945 InstrumentorIRBuilderTy &IIRB) {
946 auto &I = cast<Instruction>(Val&: V);
947 if (I.getNumOperands() > 1)
948 return I.getOperand(i: 1);
949 return PoisonValue::get(T: &Ty);
950}
951
952Value *BaseInstructionIO::getTypeId(Value &V, Type &Ty,
953 InstrumentationConfig &IConf,
954 InstrumentorIRBuilderTy &IIRB) {
955 return getCI(IT: &Ty, Val: V.getType()->getTypeID());
956}
957
958Value *BaseInstructionIO::getSubTypeId(Value &V, Type &Ty,
959 InstrumentationConfig &IConf,
960 InstrumentorIRBuilderTy &IIRB) {
961 return getSubTypeID(OpTy&: *V.getType(), ReqTy&: Ty);
962}
963
964/// FunctionIO
965/// {
966void FunctionIO::init(InstrumentationConfig &IConf,
967 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
968 using namespace std::placeholders;
969 if (UserConfig)
970 Config = *UserConfig;
971
972 bool IsPRE = getLocationKind() == InstrumentationLocation::FUNCTION_PRE;
973 if (Config.has(Opt: PassAddress))
974 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "address", "The function address.",
975 IRTArg::NONE, getFunctionAddress));
976 if (Config.has(Opt: PassName))
977 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "name", "The function name.",
978 IRTArg::STRING, getFunctionName));
979 if (Config.has(Opt: PassNumArguments))
980 IRTArgs.push_back(
981 Elt: IRTArg(IIRB.Int32Ty, "num_arguments",
982 "Number of function arguments (without varargs).", IRTArg::NONE,
983 std::bind(f: &FunctionIO::getNumArguments, args: this, args: _1, args: _2, args: _3, args: _4)));
984 if (Config.has(Opt: PassArguments))
985 IRTArgs.push_back(Elt: IRTArg(
986 IIRB.PtrTy, "arguments", "Description of the arguments.",
987 (IsPRE && Config.has(Opt: ReplaceArguments) ? IRTArg::REPLACABLE_CUSTOM
988 : IRTArg::NONE) |
989 IRTArg::VALUE_PACK,
990 std::bind(f: &FunctionIO::getArguments, args: this, args: _1, args: _2, args: _3, args: _4),
991 std::bind(f: &FunctionIO::setArguments, args: this, args: _1, args: _2, args: _3, args: _4)));
992 if (Config.has(Opt: PassIsMain))
993 IRTArgs.push_back(Elt: IRTArg(IIRB.Int8Ty, "is_main",
994 "Flag to indicate it is the main function.",
995 IRTArg::NONE, isMainFunction));
996 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
997 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
998}
999
1000Value *FunctionIO::getFunctionAddress(Value &V, Type &Ty,
1001 InstrumentationConfig &IConf,
1002 InstrumentorIRBuilderTy &IIRB) {
1003 auto &Fn = cast<Function>(Val&: V);
1004 if (Fn.isIntrinsic())
1005 return Constant::getNullValue(Ty: &Ty);
1006 return &V;
1007}
1008Value *FunctionIO::getFunctionName(Value &V, Type &Ty,
1009 InstrumentationConfig &IConf,
1010 InstrumentorIRBuilderTy &IIRB) {
1011 auto &Fn = cast<Function>(Val&: V);
1012 return IConf.getGlobalString(S: IConf.DemangleFunctionNames->getBool()
1013 ? demangle(MangledName: Fn.getName())
1014 : Fn.getName(),
1015 IIRB);
1016}
1017Value *FunctionIO::getNumArguments(Value &V, Type &Ty,
1018 InstrumentationConfig &IConf,
1019 InstrumentorIRBuilderTy &IIRB) {
1020 auto &Fn = cast<Function>(Val&: V);
1021 if (!Config.ArgFilter)
1022 return getCI(IT: &Ty, Val: Fn.arg_size());
1023 auto FRange = make_filter_range(Range: Fn.args(), Pred: Config.ArgFilter);
1024 return getCI(IT: &Ty, Val: std::distance(first: FRange.begin(), last: FRange.end()));
1025}
1026Value *FunctionIO::getArguments(Value &V, Type &Ty,
1027 InstrumentationConfig &IConf,
1028 InstrumentorIRBuilderTy &IIRB) {
1029 auto &Fn = cast<Function>(Val&: V);
1030 if (!Config.ArgFilter)
1031 return createValuePack(R: Fn.args(), IConf, IIRB);
1032 return createValuePack(R: make_filter_range(Range: Fn.args(), Pred: Config.ArgFilter), IConf,
1033 IIRB);
1034}
1035Value *FunctionIO::setArguments(Value &V, Value &NewV,
1036 InstrumentationConfig &IConf,
1037 InstrumentorIRBuilderTy &IIRB) {
1038 auto &Fn = cast<Function>(Val&: V);
1039 auto *AIt = Fn.arg_begin();
1040 auto CB = [&](int Idx, Value *ReplV) {
1041 while (Config.ArgFilter && !Config.ArgFilter(*AIt))
1042 ++AIt;
1043 Fn.getArg(i: Idx)->replaceUsesWithIf(New: ReplV, ShouldReplace: [&](Use &U) {
1044 return IIRB.NewInsts.lookup(Val: cast<Instruction>(Val: U.getUser())) != IIRB.Epoch;
1045 });
1046 ++AIt;
1047 };
1048 if (!Config.ArgFilter)
1049 readValuePack(R: Fn.args(), Pack&: NewV, IIRB, SetterCB: CB);
1050 else
1051 readValuePack(R: make_filter_range(Range: Fn.args(), Pred: Config.ArgFilter), Pack&: NewV, IIRB,
1052 SetterCB: CB);
1053 return &Fn;
1054}
1055Value *FunctionIO::isMainFunction(Value &V, Type &Ty,
1056 InstrumentationConfig &IConf,
1057 InstrumentorIRBuilderTy &IIRB) {
1058 auto &Fn = cast<Function>(Val&: V);
1059 return getCI(IT: &Ty, Val: Fn.getName() == "main");
1060}
1061
1062/// UnreachableIO
1063///{
1064void UnreachableIO::init(InstrumentationConfig &IConf,
1065 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1066 if (UserConfig)
1067 Config = *UserConfig;
1068 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1069 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1070}
1071///}
1072
1073/// AllocaIO
1074///{
1075void AllocaIO::init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
1076 ConfigTy *UserConfig) {
1077 if (UserConfig)
1078 Config = *UserConfig;
1079
1080 bool IsPRE = getLocationKind() == InstrumentationLocation::INSTRUCTION_PRE;
1081 if (!IsPRE && Config.has(Opt: PassAddress))
1082 IRTArgs.push_back(
1083 Elt: IRTArg(IIRB.PtrTy, "address", "The allocated memory address.",
1084 Config.has(Opt: ReplaceAddress) ? IRTArg::REPLACABLE : IRTArg::NONE,
1085 InstrumentationOpportunity::getValue,
1086 InstrumentationOpportunity::replaceValue));
1087 if (Config.has(Opt: PassSize))
1088 IRTArgs.push_back(Elt: IRTArg(
1089 IIRB.Int64Ty, "size", "The allocation size.",
1090 (IsPRE && Config.has(Opt: ReplaceSize)) ? IRTArg::REPLACABLE : IRTArg::NONE,
1091 getSize, setSize));
1092 if (Config.has(Opt: PassAlignment))
1093 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "alignment",
1094 "The allocation alignment.", IRTArg::NONE,
1095 getAlignment));
1096
1097 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1098 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1099}
1100
1101Value *AllocaIO::getSize(Value &V, Type &Ty, InstrumentationConfig &IO,
1102 InstrumentorIRBuilderTy &IIRB) {
1103 auto &AI = cast<AllocaInst>(Val&: V);
1104 const DataLayout &DL = AI.getDataLayout();
1105 Value *SizeValue = nullptr;
1106 TypeSize TypeSize = DL.getTypeAllocSize(Ty: AI.getAllocatedType());
1107 if (TypeSize.isFixed()) {
1108 SizeValue = getCI(IT: &Ty, Val: TypeSize.getFixedValue());
1109 } else {
1110 auto *NullPtr = ConstantPointerNull::get(T: AI.getType());
1111 SizeValue = IIRB.IRB.CreatePtrToInt(
1112 V: IIRB.IRB.CreateGEP(Ty: AI.getAllocatedType(), Ptr: NullPtr,
1113 IdxList: {IIRB.IRB.getInt32(C: 1)}),
1114 DestTy: &Ty);
1115 }
1116 if (AI.isArrayAllocation())
1117 SizeValue = IIRB.IRB.CreateMul(
1118 LHS: SizeValue, RHS: IIRB.IRB.CreateZExtOrBitCast(V: AI.getArraySize(), DestTy: &Ty));
1119 return SizeValue;
1120}
1121
1122Value *AllocaIO::setSize(Value &V, Value &NewV, InstrumentationConfig &IO,
1123 InstrumentorIRBuilderTy &IIRB) {
1124 auto &AI = cast<AllocaInst>(Val&: V);
1125 const DataLayout &DL = AI.getDataLayout();
1126 auto *NewAI = IIRB.IRB.CreateAlloca(Ty: IIRB.IRB.getInt8Ty(),
1127 AddrSpace: DL.getAllocaAddrSpace(), ArraySize: &NewV);
1128 NewAI->setAlignment(AI.getAlign());
1129 AI.replaceAllUsesWith(V: NewAI);
1130 IIRB.eraseLater(I: &AI);
1131 return NewAI;
1132}
1133
1134Value *AllocaIO::getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf,
1135 InstrumentorIRBuilderTy &IIRB) {
1136 return getCI(IT: &Ty, Val: cast<AllocaInst>(Val&: V).getAlign().value());
1137}
1138///}
1139
1140void StoreIO::init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
1141 ConfigTy *UserConfig) {
1142 if (UserConfig)
1143 Config = *UserConfig;
1144
1145 bool IsPRE = getLocationKind() == InstrumentationLocation::INSTRUCTION_PRE;
1146 if (Config.has(Opt: PassPointer)) {
1147 IRTArgs.push_back(
1148 Elt: IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1149 ((IsPRE && Config.has(Opt: ReplacePointer)) ? IRTArg::REPLACABLE
1150 : IRTArg::NONE),
1151 getPointer, setPointer));
1152 }
1153 if (Config.has(Opt: PassPointerAS)) {
1154 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "pointer_as",
1155 "The address space of the accessed pointer.",
1156 IRTArg::NONE, getPointerAS));
1157 }
1158 if (Config.has(Opt: PassBasePointerInfo)) {
1159 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "base_pointer_info",
1160 "The runtime provided base pointer info.",
1161 IRTArg::NONE, getBasePointerInfo));
1162 }
1163 if (Config.has(Opt: PassStoredValue)) {
1164 IRTArgs.push_back(
1165 Elt: IRTArg(getValueType(IIRB), "value", "The stored value.",
1166 IRTArg::POTENTIALLY_INDIRECT |
1167 (Config.has(Opt: PassStoredValueSize) ? IRTArg::INDIRECT_HAS_SIZE
1168 : IRTArg::NONE),
1169 getValue));
1170 }
1171 if (Config.has(Opt: PassStoredValueSize)) {
1172 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "value_size",
1173 "The size of the stored value.", IRTArg::NONE,
1174 getValueSize));
1175 }
1176 if (Config.has(Opt: PassAlignment)) {
1177 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "alignment",
1178 "The known access alignment.", IRTArg::NONE,
1179 getAlignment));
1180 }
1181 if (Config.has(Opt: PassValueTypeId)) {
1182 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "value_type_id",
1183 "The type id of the stored value.", IRTArg::TYPEID,
1184 getValueTypeId));
1185 }
1186 if (Config.has(Opt: PassValueSubTypeId)) {
1187 IRTArgs.push_back(Elt: IRTArg(
1188 IIRB.Int32Ty, "value_sub_type_id",
1189 "The type id of the stored value (for arrays and vectors, or -1).",
1190 IRTArg::TYPEID, getValueSubTypeId));
1191 }
1192 if (Config.has(Opt: PassAtomicityOrdering)) {
1193 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1194 "The atomicity ordering of the store.",
1195 IRTArg::NONE, getAtomicityOrdering));
1196 }
1197 if (Config.has(Opt: PassSyncScopeId)) {
1198 IRTArgs.push_back(Elt: IRTArg(IIRB.Int8Ty, "sync_scope_id",
1199 "The sync scope id of the store.", IRTArg::NONE,
1200 getSyncScopeId));
1201 }
1202 if (Config.has(Opt: PassIsVolatile)) {
1203 IRTArgs.push_back(Elt: IRTArg(IIRB.Int8Ty, "is_volatile",
1204 "Flag indicating a volatile store.", IRTArg::NONE,
1205 isVolatile));
1206 }
1207
1208 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1209 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1210}
1211
1212Value *StoreIO::getPointer(Value &V, Type &Ty, InstrumentationConfig &IConf,
1213 InstrumentorIRBuilderTy &IIRB) {
1214 auto &SI = cast<StoreInst>(Val&: V);
1215 return SI.getPointerOperand();
1216}
1217
1218Value *StoreIO::setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf,
1219 InstrumentorIRBuilderTy &IIRB) {
1220 auto &SI = cast<StoreInst>(Val&: V);
1221 SI.setOperand(i_nocapture: SI.getPointerOperandIndex(), Val_nocapture: &NewV);
1222 return &SI;
1223}
1224
1225Value *StoreIO::getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf,
1226 InstrumentorIRBuilderTy &IIRB) {
1227 auto &SI = cast<StoreInst>(Val&: V);
1228 return getCI(IT: &Ty, Val: SI.getPointerAddressSpace());
1229}
1230
1231Value *StoreIO::getBasePointerInfo(Value &V, Type &Ty,
1232 InstrumentationConfig &IConf,
1233 InstrumentorIRBuilderTy &IIRB) {
1234 auto &SI = cast<StoreInst>(Val&: V);
1235 return IConf.getBasePointerInfo(V&: *SI.getPointerOperand(), IIRB);
1236}
1237
1238Value *StoreIO::getValue(Value &V, Type &Ty, InstrumentationConfig &IConf,
1239 InstrumentorIRBuilderTy &IIRB) {
1240 auto &SI = cast<StoreInst>(Val&: V);
1241 return SI.getValueOperand();
1242}
1243
1244Value *StoreIO::getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
1245 InstrumentorIRBuilderTy &IIRB) {
1246 auto &SI = cast<StoreInst>(Val&: V);
1247 auto &DL = SI.getDataLayout();
1248 return getCI(IT: &Ty, Val: DL.getTypeStoreSize(Ty: SI.getValueOperand()->getType()));
1249}
1250
1251Value *StoreIO::getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf,
1252 InstrumentorIRBuilderTy &IIRB) {
1253 auto &SI = cast<StoreInst>(Val&: V);
1254 return getCI(IT: &Ty, Val: SI.getAlign().value());
1255}
1256
1257Value *StoreIO::getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
1258 InstrumentorIRBuilderTy &IIRB) {
1259 auto &SI = cast<StoreInst>(Val&: V);
1260 return getCI(IT: &Ty, Val: SI.getValueOperand()->getType()->getTypeID());
1261}
1262
1263Value *StoreIO::getValueSubTypeId(Value &V, Type &Ty,
1264 InstrumentationConfig &IConf,
1265 InstrumentorIRBuilderTy &IIRB) {
1266 auto &SI = cast<StoreInst>(Val&: V);
1267 return getSubTypeID(OpTy&: *SI.getValueOperand()->getType(), ReqTy&: Ty);
1268}
1269
1270Value *StoreIO::getAtomicityOrdering(Value &V, Type &Ty,
1271 InstrumentationConfig &IConf,
1272 InstrumentorIRBuilderTy &IIRB) {
1273 auto &SI = cast<StoreInst>(Val&: V);
1274 return getCI(IT: &Ty, Val: uint64_t(SI.getOrdering()));
1275}
1276
1277Value *StoreIO::getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
1278 InstrumentorIRBuilderTy &IIRB) {
1279 auto &SI = cast<StoreInst>(Val&: V);
1280 return getCI(IT: &Ty, Val: uint64_t(SI.getSyncScopeID()));
1281}
1282
1283Value *StoreIO::isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf,
1284 InstrumentorIRBuilderTy &IIRB) {
1285 auto &SI = cast<StoreInst>(Val&: V);
1286 return getCI(IT: &Ty, Val: SI.isVolatile());
1287}
1288
1289void LoadIO::init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
1290 ConfigTy *UserConfig) {
1291 bool IsPRE = getLocationKind() == InstrumentationLocation::INSTRUCTION_PRE;
1292 if (UserConfig)
1293 Config = *UserConfig;
1294 if (Config.has(Opt: PassPointer)) {
1295 IRTArgs.push_back(
1296 Elt: IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
1297 ((IsPRE && Config.has(Opt: ReplacePointer)) ? IRTArg::REPLACABLE
1298 : IRTArg::NONE),
1299 getPointer, setPointer));
1300 }
1301 if (Config.has(Opt: PassPointerAS)) {
1302 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "pointer_as",
1303 "The address space of the accessed pointer.",
1304 IRTArg::NONE, getPointerAS));
1305 }
1306 if (Config.has(Opt: PassBasePointerInfo)) {
1307 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "base_pointer_info",
1308 "The runtime provided base pointer info.",
1309 IRTArg::NONE, getBasePointerInfo));
1310 }
1311 if (!IsPRE && Config.has(Opt: PassValue)) {
1312 IRTArgs.push_back(
1313 Elt: IRTArg(getValueType(IIRB), "value", "The loaded value.",
1314 Config.has(Opt: ReplaceValue)
1315 ? IRTArg::REPLACABLE | IRTArg::POTENTIALLY_INDIRECT |
1316 (Config.has(Opt: PassValueSize) ? IRTArg::INDIRECT_HAS_SIZE
1317 : IRTArg::NONE)
1318 : IRTArg::NONE,
1319 getValue, Config.has(Opt: ReplaceValue) ? replaceValue : nullptr));
1320 }
1321 if (Config.has(Opt: PassValueSize)) {
1322 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "value_size",
1323 "The size of the loaded value.", IRTArg::NONE,
1324 getValueSize));
1325 }
1326 if (Config.has(Opt: PassAlignment)) {
1327 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "alignment",
1328 "The known access alignment.", IRTArg::NONE,
1329 getAlignment));
1330 }
1331 if (Config.has(Opt: PassValueTypeId)) {
1332 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "value_type_id",
1333 "The type id of the loaded value.", IRTArg::TYPEID,
1334 getValueTypeId));
1335 }
1336 if (Config.has(Opt: PassValueSubTypeId)) {
1337 IRTArgs.push_back(Elt: IRTArg(
1338 IIRB.Int32Ty, "value_sub_type_id",
1339 "The sub type id of the loaded value (for arrays and vectors, or -1).",
1340 IRTArg::TYPEID, getValueSubTypeId));
1341 }
1342 if (Config.has(Opt: PassAtomicityOrdering)) {
1343 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "atomicity_ordering",
1344 "The atomicity ordering of the load.",
1345 IRTArg::NONE, getAtomicityOrdering));
1346 }
1347 if (Config.has(Opt: PassSyncScopeId)) {
1348 IRTArgs.push_back(Elt: IRTArg(IIRB.Int8Ty, "sync_scope_id",
1349 "The sync scope id of the load.", IRTArg::NONE,
1350 getSyncScopeId));
1351 }
1352 if (Config.has(Opt: PassIsVolatile)) {
1353 IRTArgs.push_back(Elt: IRTArg(IIRB.Int8Ty, "is_volatile",
1354 "Flag indicating a volatile load.", IRTArg::NONE,
1355 isVolatile));
1356 }
1357
1358 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1359 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1360}
1361
1362Value *LoadIO::getPointer(Value &V, Type &Ty, InstrumentationConfig &IConf,
1363 InstrumentorIRBuilderTy &IIRB) {
1364 auto &LI = cast<LoadInst>(Val&: V);
1365 return LI.getPointerOperand();
1366}
1367
1368Value *LoadIO::setPointer(Value &V, Value &NewV, InstrumentationConfig &IConf,
1369 InstrumentorIRBuilderTy &IIRB) {
1370 auto &LI = cast<LoadInst>(Val&: V);
1371 LI.setOperand(i_nocapture: LI.getPointerOperandIndex(), Val_nocapture: &NewV);
1372 return &LI;
1373}
1374
1375Value *LoadIO::getPointerAS(Value &V, Type &Ty, InstrumentationConfig &IConf,
1376 InstrumentorIRBuilderTy &IIRB) {
1377 auto &LI = cast<LoadInst>(Val&: V);
1378 return getCI(IT: &Ty, Val: LI.getPointerAddressSpace());
1379}
1380
1381Value *LoadIO::getBasePointerInfo(Value &V, Type &Ty,
1382 InstrumentationConfig &IConf,
1383 InstrumentorIRBuilderTy &IIRB) {
1384 auto &LI = cast<LoadInst>(Val&: V);
1385 return IConf.getBasePointerInfo(V&: *LI.getPointerOperand(), IIRB);
1386}
1387
1388Value *LoadIO::getValue(Value &V, Type &Ty, InstrumentationConfig &IConf,
1389 InstrumentorIRBuilderTy &IIRB) {
1390 return &V;
1391}
1392
1393Value *LoadIO::getValueSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
1394 InstrumentorIRBuilderTy &IIRB) {
1395 auto &LI = cast<LoadInst>(Val&: V);
1396 auto &DL = LI.getDataLayout();
1397 return getCI(IT: &Ty, Val: DL.getTypeStoreSize(Ty: LI.getType()));
1398}
1399
1400Value *LoadIO::getAlignment(Value &V, Type &Ty, InstrumentationConfig &IConf,
1401 InstrumentorIRBuilderTy &IIRB) {
1402 auto &LI = cast<LoadInst>(Val&: V);
1403 return getCI(IT: &Ty, Val: LI.getAlign().value());
1404}
1405
1406Value *LoadIO::getValueTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
1407 InstrumentorIRBuilderTy &IIRB) {
1408 auto &LI = cast<LoadInst>(Val&: V);
1409 return getCI(IT: &Ty, Val: LI.getType()->getTypeID());
1410}
1411
1412Value *LoadIO::getValueSubTypeId(Value &V, Type &Ty,
1413 InstrumentationConfig &IConf,
1414 InstrumentorIRBuilderTy &IIRB) {
1415 auto &LI = cast<LoadInst>(Val&: V);
1416 return getSubTypeID(OpTy&: *LI.getType(), ReqTy&: Ty);
1417}
1418
1419Value *LoadIO::getAtomicityOrdering(Value &V, Type &Ty,
1420 InstrumentationConfig &IConf,
1421 InstrumentorIRBuilderTy &IIRB) {
1422 auto &LI = cast<LoadInst>(Val&: V);
1423 return getCI(IT: &Ty, Val: uint64_t(LI.getOrdering()));
1424}
1425
1426Value *LoadIO::getSyncScopeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
1427 InstrumentorIRBuilderTy &IIRB) {
1428 auto &LI = cast<LoadInst>(Val&: V);
1429 return getCI(IT: &Ty, Val: uint64_t(LI.getSyncScopeID()));
1430}
1431
1432Value *LoadIO::isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf,
1433 InstrumentorIRBuilderTy &IIRB) {
1434 auto &LI = cast<LoadInst>(Val&: V);
1435 return getCI(IT: &Ty, Val: LI.isVolatile());
1436}
1437
1438void BasePointerIO::init(InstrumentationConfig &IConf,
1439 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1440 if (UserConfig)
1441 Config = *UserConfig;
1442 if (Config.has(Opt: PassPointer))
1443 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "base_pointer",
1444 "The base pointer in question.",
1445 IRTArg::REPLACABLE, getValue, setValueNoop));
1446 if (Config.has(Opt: PassPointerKind))
1447 IRTArgs.push_back(Elt: IRTArg(
1448 IIRB.Int32Ty, "base_pointer_kind",
1449 "The base pointer kind (argument, global, instruction, unknown).",
1450 IRTArg::NONE, getPointerKind));
1451 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1452 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1453}
1454
1455Value *BasePointerIO::getPointerKind(Value &V, Type &Ty,
1456 InstrumentationConfig &IConf,
1457 InstrumentorIRBuilderTy &IIRB) {
1458 if (isa<Argument>(Val: V))
1459 return getCI(IT: &Ty, Val: 0);
1460 if (isa<GlobalValue>(Val: V))
1461 return getCI(IT: &Ty, Val: 1);
1462 if (isa<Instruction>(Val: V))
1463 return getCI(IT: &Ty, Val: 2);
1464 return getCI(IT: &Ty, Val: 3);
1465}
1466
1467void ModuleIO::init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
1468 ConfigTy *UserConfig) {
1469 if (UserConfig)
1470 Config = *UserConfig;
1471
1472 if (Config.has(Opt: PassName))
1473 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "module_name",
1474 "The module/translation unit name.",
1475 IRTArg::STRING, getModuleName));
1476 if (Config.has(Opt: PassTargetTriple))
1477 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "target_triple", "The target triple.",
1478 IRTArg::STRING, getTargetTriple));
1479
1480 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1481 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1482}
1483Value *ModuleIO::getModuleName(Value &V, Type &Ty, InstrumentationConfig &IConf,
1484 InstrumentorIRBuilderTy &IIRB) {
1485 // V is a constructor or destructor of the module we can place code in.
1486 auto &Fn = cast<Function>(Val&: V);
1487 return IConf.getGlobalString(S: Fn.getParent()->getName(), IIRB);
1488}
1489Value *ModuleIO::getTargetTriple(Value &V, Type &Ty,
1490 InstrumentationConfig &IConf,
1491 InstrumentorIRBuilderTy &IIRB) {
1492 // V is a constructor or destructor of the module we can place code in.
1493 auto &Fn = cast<Function>(Val&: V);
1494 return IConf.getGlobalString(S: Fn.getParent()->getTargetTriple().getTriple(),
1495 IIRB);
1496}
1497
1498void GlobalVarIO::init(InstrumentationConfig &IConf,
1499 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1500 if (UserConfig)
1501 Config = *UserConfig;
1502 bool IsPRE = InstrumentationLocation::isPRE(Kind: getLocationKind());
1503 if (Config.has(Opt: PassAddress))
1504 IRTArgs.push_back(Elt: IRTArg(
1505 IIRB.PtrTy, "address",
1506 "The address of the global (replaceable for definitions).",
1507 IsPRE && Config.has(Opt: ReplaceAddress) ? IRTArg::REPLACABLE : IRTArg::NONE,
1508 getAddress, setAddress));
1509 if (Config.has(Opt: PassAS))
1510 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "address_space",
1511 "The address space of the global.", IRTArg::NONE,
1512 getAS));
1513 if (Config.has(Opt: PassDeclaredSize))
1514 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "declared_size",
1515 "The size of the declared type of the global.",
1516 IRTArg::NONE, getDeclaredSize));
1517 if (Config.has(Opt: PassAlignment))
1518 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "alignment",
1519 "The allocation alignment.", IRTArg::NONE,
1520 getAlignment));
1521 if (Config.has(Opt: PassName))
1522 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "name", "The name of the global.",
1523 IRTArg::STRING, getSymbolName));
1524 if (Config.has(Opt: PassInitialValue))
1525 IRTArgs.push_back(Elt: IRTArg(
1526 IIRB.Int64Ty, "initial_value", "The initial value of the global.",
1527 IRTArg::POTENTIALLY_INDIRECT | IRTArg::INDIRECT_HAS_SIZE,
1528 getInitialValue));
1529 if (Config.has(Opt: PassIsConstant))
1530 IRTArgs.push_back(Elt: IRTArg(IIRB.Int8Ty, "is_constant",
1531 "Flag to indicate constant globals.", IRTArg::NONE,
1532 isConstant));
1533 if (Config.has(Opt: PassIsDefinition))
1534 IRTArgs.push_back(Elt: IRTArg(IIRB.Int8Ty, "is_definition",
1535 "Flag to indicate global definitions.",
1536 IRTArg::NONE, isDefinition));
1537 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1538 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1539}
1540Value *GlobalVarIO::getAddress(Value &V, Type &Ty, InstrumentationConfig &IConf,
1541 InstrumentorIRBuilderTy &IIRB) {
1542 GlobalVariable &GV = cast<GlobalVariable>(Val&: V);
1543 if (GV.getAddressSpace())
1544 return ConstantExpr::getAddrSpaceCast(C: &GV, Ty: IIRB.PtrTy);
1545 return &GV;
1546}
1547Value *GlobalVarIO::setAddress(Value &V, Value &NewV,
1548 InstrumentationConfig &IConf,
1549 InstrumentorIRBuilderTy &IIRB) {
1550 GlobalVariable &GV = cast<GlobalVariable>(Val&: V);
1551
1552 GlobalVariable *ShadowGV = nullptr;
1553 auto ShadowName = IConf.getRTName(Prefix: "shadow.", Name: GV.getName());
1554 auto &DL = GV.getDataLayout();
1555 if (GV.isDeclaration()) {
1556 ShadowGV = new GlobalVariable(*GV.getParent(), GV.getType(), false,
1557 GlobalVariable::WeakODRLinkage, &GV,
1558 ShadowName, &GV, GV.getThreadLocalMode(),
1559 DL.getDefaultGlobalsAddressSpace());
1560 } else {
1561 ShadowGV = new GlobalVariable(
1562 *GV.getParent(), NewV.getType(), false, GV.getLinkage(),
1563 PoisonValue::get(T: NewV.getType()), ShadowName, &GV);
1564 IIRB.IRB.CreateStore(Val: &NewV, Ptr: ShadowGV);
1565 }
1566
1567 SmallVector<Use *> Worklist(make_pointer_range(Range: GV.uses()));
1568 SmallPtrSet<Use *, 32> Done;
1569 DenseMap<std::pair<Value *, Function *>, Instruction *> VMap;
1570 DenseMap<Value *, Instruction *> ConstToInstMap;
1571 DenseMap<Function *, Instruction *> ReloadMap;
1572
1573 auto MakeInstForConst = [&](Use &U) {
1574 Instruction *&I = ConstToInstMap[U];
1575 if (I)
1576 return;
1577 if (U == &GV) {
1578 } else if (auto *CE = dyn_cast<ConstantExpr>(Val&: U)) {
1579 I = CE->getAsInstruction();
1580 }
1581 };
1582
1583 auto InsertConsts = [&](Instruction *UserI, Use &UserU) {
1584 SmallVector<std::pair<Instruction *, Use *>> Worklist;
1585 auto *&Reload = ReloadMap[UserI->getFunction()];
1586 if (!Reload) {
1587 Reload = new LoadInst(
1588 GV.getType(), ShadowGV, GV.getName() + ".shadow_load",
1589 UserI->getFunction()->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
1590 IIRB.NewInsts.insert(KV: {Reload, IIRB.Epoch});
1591 }
1592 Worklist.push_back(Elt: {UserI, &UserU});
1593 while (!Worklist.empty()) {
1594 auto [I, U] = Worklist.pop_back_val();
1595 if (*U == &GV) {
1596 U->set(ReloadMap[I->getFunction()]);
1597 continue;
1598 }
1599 if (auto *CI = ConstToInstMap[*U]) {
1600 auto *CIClone = CI->clone();
1601 IIRB.NewInsts.insert(KV: {CIClone, IIRB.Epoch});
1602 if (auto *PHI = dyn_cast<PHINode>(Val: I)) {
1603 auto *BB = PHI->getIncomingBlock(i: U->getOperandNo());
1604 CIClone->insertBefore(InsertPos: BB->getTerminator()->getIterator());
1605 } else {
1606 CIClone->insertBefore(InsertPos: I->getIterator());
1607 }
1608 U->set(CIClone);
1609 for (auto &CICUse : CIClone->operands()) {
1610 Worklist.push_back(Elt: {CIClone, &CICUse});
1611 }
1612 }
1613 }
1614 };
1615
1616 SmallPtrSet<Use *, 8> Visited;
1617 while (!Worklist.empty()) {
1618 Use *U = Worklist.pop_back_val();
1619 if (!Done.insert(Ptr: U).second)
1620 continue;
1621 MakeInstForConst(*U);
1622 auto *I = dyn_cast<Instruction>(Val: U->getUser());
1623 if (!I) {
1624 append_range(C&: Worklist, R: make_pointer_range(Range: U->getUser()->uses()));
1625 continue;
1626 }
1627 if (IIRB.NewInsts.lookup(Val: I) == IIRB.Epoch)
1628 continue;
1629 if (isa<LandingPadInst>(Val: I))
1630 continue;
1631 if (auto *II = dyn_cast<IntrinsicInst>(Val: I))
1632 if (II->getIntrinsicID() == Intrinsic::eh_typeid_for)
1633 continue;
1634 if (I->getParent())
1635 InsertConsts(I, *U);
1636 }
1637
1638 for (auto &It : ConstToInstMap)
1639 if (It.second)
1640 It.second->deleteValue();
1641
1642 return &V;
1643}
1644Value *GlobalVarIO::getAS(Value &V, Type &Ty, InstrumentationConfig &IConf,
1645 InstrumentorIRBuilderTy &IIRB) {
1646 GlobalVariable &GV = cast<GlobalVariable>(Val&: V);
1647 return getCI(IT: &Ty, Val: GV.getAddressSpace());
1648}
1649Value *GlobalVarIO::getAlignment(Value &V, Type &Ty,
1650 InstrumentationConfig &IConf,
1651 InstrumentorIRBuilderTy &IIRB) {
1652 GlobalVariable &GV = cast<GlobalVariable>(Val&: V);
1653 return getCI(IT: &Ty, Val: GV.getAlignment());
1654}
1655Value *GlobalVarIO::getDeclaredSize(Value &V, Type &Ty,
1656 InstrumentationConfig &IConf,
1657 InstrumentorIRBuilderTy &IIRB) {
1658 GlobalVariable &GV = cast<GlobalVariable>(Val&: V);
1659 auto &DL = GV.getDataLayout();
1660 return getCI(IT: &Ty, Val: DL.getTypeAllocSize(Ty: GV.getValueType()));
1661}
1662Value *GlobalVarIO::getSymbolName(Value &V, Type &Ty,
1663 InstrumentationConfig &IConf,
1664 InstrumentorIRBuilderTy &IIRB) {
1665 GlobalVariable &GV = cast<GlobalVariable>(Val&: V);
1666 return IConf.getGlobalString(S: GV.getName(), IIRB);
1667}
1668Value *GlobalVarIO::getInitialValue(Value &V, Type &Ty,
1669 InstrumentationConfig &IConf,
1670 InstrumentorIRBuilderTy &IIRB) {
1671 GlobalVariable &GV = cast<GlobalVariable>(Val&: V);
1672 return GV.hasInitializer() ? GV.getInitializer()
1673 : Constant::getNullValue(Ty: &Ty);
1674}
1675Value *GlobalVarIO::isConstant(Value &V, Type &Ty, InstrumentationConfig &IConf,
1676 InstrumentorIRBuilderTy &IIRB) {
1677 GlobalVariable &GV = cast<GlobalVariable>(Val&: V);
1678 return getCI(IT: &Ty, Val: GV.isConstant());
1679}
1680Value *GlobalVarIO::isDefinition(Value &V, Type &Ty,
1681 InstrumentationConfig &IConf,
1682 InstrumentorIRBuilderTy &IIRB) {
1683 GlobalVariable &GV = cast<GlobalVariable>(Val&: V);
1684 return getCI(IT: &Ty, Val: !GV.isDeclaration());
1685}
1686
1687/// CastIO
1688/// {
1689void CastIO::init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
1690 ConfigTy *UserConfig) {
1691 if (UserConfig)
1692 Config = *UserConfig;
1693 bool IsPRE = getLocationKind() == InstrumentationLocation::INSTRUCTION_PRE;
1694 if (Config.has(Opt: PassInput))
1695 IRTArgs.push_back(
1696 Elt: IRTArg(IIRB.Int64Ty, "input", "Input value of the cast.",
1697 IRTArg::POTENTIALLY_INDIRECT |
1698 (Config.has(Opt: PassResultSize) ? IRTArg::INDIRECT_HAS_SIZE
1699 : IRTArg::NONE),
1700 getInput));
1701 if (Config.has(Opt: PassInputTypeId))
1702 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "input_type_id",
1703 "The type id of the input value.", IRTArg::TYPEID,
1704 getInputTypeId));
1705 if (Config.has(Opt: PassInputSubTypeId))
1706 IRTArgs.push_back(Elt: IRTArg(
1707 IIRB.Int32Ty, "input_sub_type_id",
1708 "The sub type id of the input value (for arrays and vectors, or -1).",
1709 IRTArg::TYPEID, getInputSubTypeId));
1710 if (Config.has(Opt: PassInputSize))
1711 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "input_size",
1712 "The size of the input value.", IRTArg::NONE,
1713 getInputSize));
1714 if (!IsPRE && Config.has(Opt: PassResult))
1715 IRTArgs.push_back(
1716 Elt: IRTArg(IIRB.Int64Ty, "result", "Result of the cast.",
1717 (IRTArg::REPLACABLE | IRTArg::POTENTIALLY_INDIRECT) |
1718 (Config.has(Opt: PassResultSize) ? IRTArg::INDIRECT_HAS_SIZE
1719 : IRTArg::NONE),
1720 getValue, Config.has(Opt: ReplaceResult) ? replaceValue : nullptr));
1721 if (Config.has(Opt: PassResultTypeId))
1722 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "result_type_id",
1723 "The type id of the result value.", IRTArg::TYPEID,
1724 getResultTypeId));
1725 if (Config.has(Opt: PassResultSubTypeId))
1726 IRTArgs.push_back(Elt: IRTArg(
1727 IIRB.Int32Ty, "result_sub_type_id",
1728 "The sub type id of the result value (for arrays and vectors, or -1).",
1729 IRTArg::TYPEID, getResultSubTypeId));
1730 if (Config.has(Opt: PassResultSize))
1731 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "result_size",
1732 "The size of the result value.", IRTArg::NONE,
1733 getResultSize));
1734 if (Config.has(Opt: PassOpcode))
1735 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "opcode",
1736 "The opcode of the cast instruction.",
1737 IRTArg::NONE, getOpcode));
1738
1739 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1740 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1741}
1742
1743Value *CastIO::getInput(Value &V, Type &Ty, InstrumentationConfig &IConf,
1744 InstrumentorIRBuilderTy &IIRB) {
1745 auto &CI = cast<CastInst>(Val&: V);
1746 return CI.getOperand(i_nocapture: 0);
1747}
1748
1749Value *CastIO::getInputTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
1750 InstrumentorIRBuilderTy &IIRB) {
1751 auto &CI = cast<CastInst>(Val&: V);
1752 return getCI(IT: &Ty, Val: CI.getSrcTy()->getTypeID());
1753}
1754
1755Value *CastIO::getInputSubTypeId(Value &V, Type &Ty,
1756 InstrumentationConfig &IConf,
1757 InstrumentorIRBuilderTy &IIRB) {
1758 auto &CI = cast<CastInst>(Val&: V);
1759 return getSubTypeID(OpTy&: *CI.getSrcTy(), ReqTy&: Ty);
1760}
1761
1762Value *CastIO::getInputSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
1763 InstrumentorIRBuilderTy &IIRB) {
1764 auto &CI = cast<CastInst>(Val&: V);
1765 auto &DL = CI.getDataLayout();
1766 return getCI(IT: &Ty, Val: DL.getTypeStoreSize(Ty: CI.getSrcTy()));
1767}
1768
1769Value *CastIO::getResultTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
1770 InstrumentorIRBuilderTy &IIRB) {
1771 auto &CI = cast<CastInst>(Val&: V);
1772 return getCI(IT: &Ty, Val: CI.getDestTy()->getTypeID());
1773}
1774
1775Value *CastIO::getResultSubTypeId(Value &V, Type &Ty,
1776 InstrumentationConfig &IConf,
1777 InstrumentorIRBuilderTy &IIRB) {
1778 auto &CI = cast<CastInst>(Val&: V);
1779 return getSubTypeID(OpTy&: *CI.getDestTy(), ReqTy&: Ty);
1780}
1781
1782Value *CastIO::getResultSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
1783 InstrumentorIRBuilderTy &IIRB) {
1784 auto &CI = cast<CastInst>(Val&: V);
1785 auto &DL = CI.getDataLayout();
1786 return getCI(IT: &Ty, Val: DL.getTypeStoreSize(Ty: CI.getDestTy()));
1787}
1788///}
1789
1790Value *NumericIO::getFlags(Value &V, Type &Ty, InstrumentationConfig &IConf,
1791 InstrumentorIRBuilderTy &IIRB) {
1792 auto &I = cast<Instruction>(Val&: V);
1793 uint64_t Flag = NUMERIC_FLAG_NONE;
1794
1795 switch (I.getOpcode()) {
1796 case Instruction::Add:
1797 case Instruction::Sub:
1798 case Instruction::Mul:
1799 case Instruction::Shl:
1800 if (I.hasNoSignedWrap())
1801 Flag |= NUMERIC_FLAG_NO_SIGNED_WRAP;
1802 if (I.hasNoUnsignedWrap())
1803 Flag |= NUMERIC_FLAG_NO_UNSIGNED_WRAP;
1804 break;
1805 case Instruction::FAdd:
1806 case Instruction::FSub:
1807 case Instruction::FMul:
1808 case Instruction::FDiv:
1809 case Instruction::FNeg:
1810 if (I.hasNoNaNs())
1811 Flag |= NUMERIC_FLAG_HAS_NO_NANS;
1812 if (I.hasNoInfs())
1813 Flag |= NUMERIC_FLAG_HAS_NO_INFS;
1814 if (I.hasNoSignedZeros())
1815 Flag |= NUMERIC_FLAG_HAS_NO_SIGNED_ZEROS;
1816 break;
1817 case Instruction::AShr:
1818 case Instruction::LShr:
1819 case Instruction::SDiv:
1820 case Instruction::UDiv:
1821 if (I.isExact())
1822 Flag |= NUMERIC_FLAG_IS_EXACT;
1823 break;
1824 }
1825
1826 if (auto *DI = dyn_cast<PossiblyDisjointInst>(Val: &V))
1827 if (DI->isDisjoint())
1828 Flag |= NUMERIC_FLAG_IS_DISJOINT;
1829
1830 return getCI(IT: &Ty, Val: Flag);
1831}
1832
1833void NumericIO::init(InstrumentationConfig &IConf,
1834 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1835 if (UserConfig)
1836 Config = UserConfig;
1837 bool IsPRE = getLocationKind() == InstrumentationLocation::INSTRUCTION_PRE;
1838 const auto ValArgOpts =
1839 IRTArg::POTENTIALLY_INDIRECT |
1840 (Config.has(Opt: PassSize) ? IRTArg::INDIRECT_HAS_SIZE : IRTArg::NONE);
1841 if (Config.has(Opt: PassTypeId))
1842 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "type_id",
1843 "The operation's type id.", IRTArg::TYPEID,
1844 getTypeId));
1845 if (Config.has(Opt: PassSubTypeId))
1846 IRTArgs.push_back(
1847 Elt: IRTArg(IIRB.Int32Ty, "sub_type_id",
1848 "The operation's sub type id (for arrays and vectors, or -1).",
1849 IRTArg::TYPEID, getSubTypeId));
1850 if (Config.has(Opt: PassSize))
1851 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "size", "The operation's type size.",
1852 IRTArg::NONE, getTypeSize));
1853 if (Config.has(Opt: PassOpcode))
1854 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
1855 IRTArg::NONE, getOpcode));
1856 if (Config.has(Opt: PassLeft))
1857 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "left",
1858 "The operation's left operand.", ValArgOpts,
1859 getLeftOperand));
1860 if (Config.has(Opt: PassRight))
1861 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "right",
1862 "The operation's right operand. This value is "
1863 "poison for unary operations.",
1864 ValArgOpts, getRightOperand));
1865 if (!IsPRE && Config.has(Opt: PassResult))
1866 IRTArgs.push_back(
1867 Elt: IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
1868 IRTArg::REPLACABLE | ValArgOpts, getValue,
1869 Config.has(Opt: ReplaceResult) ? replaceValue : nullptr));
1870 if (Config.has(Opt: PassFlags))
1871 IRTArgs.push_back(
1872 Elt: IRTArg(IIRB.Int64Ty, "flags",
1873 "A bitmask value signaling which instruction flags are present.",
1874 IRTArg::NONE, getFlags));
1875 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1876 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1877}
1878
1879Value *CompareIO::getOperandTypeId(Value &V, Type &Ty,
1880 InstrumentationConfig &IConf,
1881 InstrumentorIRBuilderTy &IIRB) {
1882 auto &I = cast<Instruction>(Val&: V);
1883 return getCI(IT: &Ty, Val: I.getOperand(i: 0)->getType()->getTypeID());
1884}
1885
1886Value *CompareIO::getOperandSize(Value &V, Type &Ty,
1887 InstrumentationConfig &IConf,
1888 InstrumentorIRBuilderTy &IIRB) {
1889 auto &I = cast<Instruction>(Val&: V);
1890 auto &DL = I.getDataLayout();
1891 return getCI(IT: &Ty, Val: DL.getTypeStoreSize(Ty: I.getOperand(i: 0)->getType()));
1892}
1893
1894Value *CompareIO::getPredicate(Value &V, Type &Ty, InstrumentationConfig &IConf,
1895 InstrumentorIRBuilderTy &IIRB) {
1896 auto *CI = dyn_cast<CmpInst>(Val: &V);
1897 return getCI(IT: &Ty, Val: CI->getPredicate());
1898}
1899
1900Value *CompareIO::getFlags(Value &V, Type &Ty, InstrumentationConfig &IConf,
1901 InstrumentorIRBuilderTy &IIRB) {
1902 auto &I = cast<Instruction>(Val&: V);
1903 uint64_t Flag = NUMERIC_FLAG_NONE;
1904
1905 switch (I.getOpcode()) {
1906 case Instruction::ICmp:
1907 if (dyn_cast<ICmpInst>(Val: &V)->hasSameSign())
1908 Flag |= COMPARE_FLAG_SAMESIGN;
1909 break;
1910 case Instruction::FCmp:
1911 if (I.hasNoNaNs())
1912 Flag |= COMPARE_FLAG_HAS_NO_NANS;
1913 if (I.hasNoInfs())
1914 Flag |= COMPARE_FLAG_HAS_NO_INFS;
1915 if (I.hasNoSignedZeros())
1916 Flag |= COMPARE_FLAG_HAS_NO_SIGNED_ZEROS;
1917 break;
1918 }
1919
1920 return getCI(IT: &Ty, Val: Flag);
1921}
1922
1923void CompareIO::init(InstrumentationConfig &IConf,
1924 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1925 if (UserConfig)
1926 Config = UserConfig;
1927 bool IsPRE = getLocationKind() == InstrumentationLocation::INSTRUCTION_PRE;
1928 const auto OperandArgOpts =
1929 IRTArg::POTENTIALLY_INDIRECT |
1930 (Config.has(Opt: PassOpSize) ? IRTArg::INDIRECT_HAS_SIZE : IRTArg::NONE);
1931 if (Config.has(Opt: PassOpTypeId))
1932 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "operand_type_id",
1933 "The operand type id.", IRTArg::NONE,
1934 getOperandTypeId));
1935 if (Config.has(Opt: PassOpSize))
1936 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "operand_size",
1937 "The operand type size.", IRTArg::NONE,
1938 getOperandSize));
1939 if (Config.has(Opt: PassOpcode))
1940 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
1941 IRTArg::NONE, getOpcode));
1942 if (Config.has(Opt: PassPredicate))
1943 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "predicate",
1944 "The comparison predicate ID.", IRTArg::NONE,
1945 getPredicate));
1946 if (Config.has(Opt: PassLeft))
1947 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "left",
1948 "The comparison's left operand.", OperandArgOpts,
1949 getLeftOperand));
1950 if (Config.has(Opt: PassRight))
1951 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "right",
1952 "The comparison's right operand.", OperandArgOpts,
1953 getRightOperand));
1954 if (!IsPRE && Config.has(Opt: PassResultSize))
1955 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "result_type_id",
1956 "The result value's type ID.", IRTArg::NONE,
1957 getTypeId));
1958 if (!IsPRE && Config.has(Opt: PassResultSize))
1959 IRTArgs.push_back(Elt: IRTArg(IIRB.Int32Ty, "result_size",
1960 "Size of the result value.", IRTArg::NONE,
1961 getTypeSize));
1962 if (!IsPRE && Config.has(Opt: PassResult))
1963 IRTArgs.push_back(
1964 Elt: IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
1965 IRTArg::REPLACABLE | IRTArg::POTENTIALLY_INDIRECT |
1966 (Config.has(Opt: PassResultSize) ? IRTArg::INDIRECT_HAS_SIZE
1967 : IRTArg::NONE),
1968 getValue, Config.has(Opt: ReplaceResult) ? replaceValue : nullptr));
1969 if (Config.has(Opt: PassFlags))
1970 IRTArgs.push_back(
1971 Elt: IRTArg(IIRB.Int64Ty, "flags",
1972 "A bitmask value signaling which instruction flags are present.",
1973 IRTArg::NONE, getFlags));
1974 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1975 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1976}
1977