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