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