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::ZeroOrMore, 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(TheBB: EntryBB, IP: 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,
733 DL: IIRB.IRB.GetInsertBlock()->getDataLayout());
734}
735
736Value *InstrumentationOpportunity::replaceValue(Value &V, Value &NewV,
737 InstrumentationConfig &IConf,
738 InstrumentorIRBuilderTy &IIRB) {
739 if (V.getType()->isVoidTy())
740 return &V;
741
742 auto *NewVCasted = &NewV;
743 if (auto *I = dyn_cast<Instruction>(Val: &NewV)) {
744 IRBuilderBase::InsertPointGuard IPG(IIRB.IRB);
745 IIRB.IRB.SetInsertPoint(I->getNextNode());
746 ensureDbgLoc(IRB&: IIRB.IRB);
747 NewVCasted = tryToCast(IRB&: IIRB.IRB, V: &NewV, Ty: V.getType(), DL: IIRB.DL,
748 /*AllowTruncate=*/true);
749 }
750 V.replaceUsesWithIf(New: NewVCasted, ShouldReplace: [&](Use &U) {
751 if (IIRB.NewInsts.lookup(Val: cast<Instruction>(Val: U.getUser())) == IIRB.Epoch)
752 return false;
753 return !isa<LifetimeIntrinsic>(Val: U.getUser()) && !U.getUser()->isDroppable();
754 });
755
756 return &V;
757}
758
759IRTCallDescription::IRTCallDescription(InstrumentationOpportunity &IO,
760 Type *RetTy)
761 : IO(IO), RetTy(RetTy) {
762 for (auto &It : IO.IRTArgs) {
763 if (!It.Enabled)
764 continue;
765 NumReplaceableArgs += bool(It.Flags & IRTArg::REPLACABLE);
766 MightRequireIndirection |= It.Flags & IRTArg::POTENTIALLY_INDIRECT;
767 }
768 if (NumReplaceableArgs > 1)
769 MightRequireIndirection = RequiresIndirection = true;
770}
771
772FunctionType *IRTCallDescription::createLLVMSignature(
773 InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
774 const DataLayout &DL, bool ForceIndirection) {
775 assert(((ForceIndirection && MightRequireIndirection) ||
776 (!ForceIndirection && !RequiresIndirection)) &&
777 "Wrong indirection setting!");
778
779 SmallVector<Type *> ParamTypes;
780 for (auto &It : IO.IRTArgs) {
781 if (!It.Enabled)
782 continue;
783 if (!ForceIndirection || !isPotentiallyIndirect(IRTA&: It)) {
784 ParamTypes.push_back(Elt: It.Ty);
785 if (!RetTy && NumReplaceableArgs == 1 && (It.Flags & IRTArg::REPLACABLE))
786 RetTy = It.Ty;
787 continue;
788 }
789
790 // The indirection pointer and the size of the value.
791 ParamTypes.push_back(Elt: IIRB.PtrTy);
792 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE))
793 ParamTypes.push_back(Elt: IIRB.Int32Ty);
794 }
795 if (!RetTy)
796 RetTy = IIRB.VoidTy;
797
798 return FunctionType::get(Result: RetTy, Params: ParamTypes, /*isVarArg=*/false);
799}
800
801CallInst *IRTCallDescription::createLLVMCall(Value *&V,
802 InstrumentationConfig &IConf,
803 InstrumentorIRBuilderTy &IIRB,
804 const DataLayout &DL,
805 InstrumentationCaches &ICaches) {
806 SmallVector<Value *> CallParams;
807
808 IRBuilderBase::InsertPointGuard IRP(IIRB.IRB);
809 auto IP = IIRB.IRB.GetInsertPoint();
810
811 bool ForceIndirection = RequiresIndirection;
812 for (auto &It : IO.IRTArgs) {
813 if (!It.Enabled)
814 continue;
815 auto *&Param = ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
816 if (!Param || It.NoCache)
817 // Avoid passing the caches to the getter.
818 Param = It.GetterCB(*V, *It.Ty, IConf, IIRB);
819 assert(Param);
820
821 if (Param->getType()->isVoidTy()) {
822 Param = Constant::getNullValue(Ty: It.Ty);
823 } else if (Param->getType()->isAggregateType() ||
824 Param->getType()->isVectorTy() ||
825 DL.getTypeSizeInBits(Ty: Param->getType()) >
826 DL.getTypeSizeInBits(Ty: It.Ty)) {
827 if (!isPotentiallyIndirect(IRTA&: It)) {
828 IIRB.Ctx.diagnose(DI: DiagnosticInfoInstrumentation(
829 Twine("indirection needed for ") + It.Name + Twine(" in ") +
830 IO.getName() +
831 Twine(", but not indicated. Instrumentation is skipped"),
832 DS_Warning));
833 return nullptr;
834 }
835 ForceIndirection = true;
836 } else {
837 Param = tryToCast(IRB&: IIRB.IRB, V: Param, Ty: It.Ty, DL);
838 }
839 CallParams.push_back(Elt: Param);
840 }
841
842 if (ForceIndirection) {
843 Function *Fn = IIRB.IRB.GetInsertBlock()->getParent();
844
845 unsigned Offset = 0;
846 for (auto &It : IO.IRTArgs) {
847 if (!It.Enabled)
848 continue;
849
850 if (!isPotentiallyIndirect(IRTA&: It)) {
851 ++Offset;
852 continue;
853 }
854 auto *&CallParam = CallParams[Offset++];
855 if (!(It.Flags & IRTArg::INDIRECT_HAS_SIZE)) {
856 CallParams.insert(I: &CallParam + 1, Elt: IIRB.IRB.getInt32(C: DL.getTypeStoreSize(
857 Ty: CallParam->getType())));
858 Offset += 1;
859 }
860
861 auto *&CachedParam =
862 ICaches.IndirectArgCache[{IIRB.Epoch, IO.getName(), It.Name}];
863 if (CachedParam) {
864 CallParam = CachedParam;
865 continue;
866 }
867
868 auto *AI = IIRB.getAlloca(Fn, Ty: CallParam->getType());
869 IIRB.IRB.CreateStore(Val: CallParam, Ptr: AI);
870 CallParam = CachedParam = tryToCast(IRB&: IIRB.IRB, V: AI, Ty: IIRB.PtrTy, DL);
871 }
872 }
873
874 if (!ForceIndirection)
875 IIRB.IRB.SetInsertPoint(IP);
876 ensureDbgLoc(IRB&: IIRB.IRB);
877
878 auto *FnTy = createLLVMSignature(IConf, IIRB, DL, ForceIndirection);
879 auto CompleteName =
880 IConf.getRTName(Prefix: IO.IP.isPRE() ? "pre_" : "post_", Name: IO.getName(),
881 Suffix1: ForceIndirection ? "_ind" : "");
882 auto FC = IIRB.IRB.GetInsertBlock()->getModule()->getOrInsertFunction(
883 Name: CompleteName, T: FnTy);
884 auto *CI = IIRB.IRB.CreateCall(Callee: FC, Args: CallParams);
885 CI->addFnAttr(Attr: Attribute::get(Context&: IIRB.Ctx, Kind: Attribute::WillReturn));
886
887 for (unsigned I = 0, E = IO.IRTArgs.size(); I < E; ++I) {
888 if (!IO.IRTArgs[I].Enabled)
889 continue;
890 if (!isReplacable(IRTA&: IO.IRTArgs[I]))
891 continue;
892 bool IsCustomReplaceable = IO.IRTArgs[I].Flags & IRTArg::REPLACABLE_CUSTOM;
893 Value *NewValue = FnTy->isVoidTy() || IsCustomReplaceable
894 ? ICaches.DirectArgCache[{IIRB.Epoch, IO.getName(),
895 IO.IRTArgs[I].Name}]
896 : CI;
897 assert(NewValue);
898 if (ForceIndirection && !IsCustomReplaceable &&
899 isPotentiallyIndirect(IRTA&: IO.IRTArgs[I])) {
900 auto *Q =
901 ICaches
902 .IndirectArgCache[{IIRB.Epoch, IO.getName(), IO.IRTArgs[I].Name}];
903 NewValue = IIRB.IRB.CreateLoad(Ty: V->getType(), Ptr: Q);
904 }
905 V = IO.IRTArgs[I].SetterCB(*V, *NewValue, IConf, IIRB);
906 }
907 return CI;
908}
909
910template <typename Ty> constexpr static Value *getValue(Ty &ValueOrUse) {
911 if constexpr (std::is_same<Ty, Use>::value)
912 return ValueOrUse.get();
913 else
914 return static_cast<Value *>(&ValueOrUse);
915}
916
917template <typename Range>
918static Value *createValuePack(const Range &R, InstrumentationConfig &IConf,
919 InstrumentorIRBuilderTy &IIRB) {
920 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
921 auto *I32Ty = IIRB.IRB.getInt32Ty();
922 SmallVector<Constant *> ConstantValues;
923 SmallVector<std::pair<Value *, uint32_t>> Values;
924 SmallVector<Type *> Types;
925 for (auto &RE : R) {
926 Value *V = getValue(RE);
927 if (!V->getType()->isSized())
928 continue;
929 auto VSize = IIRB.DL.getTypeAllocSize(Ty: V->getType());
930 ConstantValues.push_back(Elt: getCI(IT: I32Ty, Val: VSize));
931 Types.push_back(Elt: I32Ty);
932 ConstantValues.push_back(Elt: getCI(IT: I32Ty, Val: V->getType()->getTypeID()));
933 Types.push_back(Elt: I32Ty);
934 if (uint32_t MisAlign = VSize % 8) {
935 Types.push_back(Elt: ArrayType::get(ElementType: IIRB.Int8Ty, NumElements: 8 - MisAlign));
936 ConstantValues.push_back(Elt: ConstantArray::getNullValue(Ty: Types.back()));
937 }
938 Types.push_back(Elt: V->getType());
939 if (auto *C = dyn_cast<Constant>(Val: V)) {
940 ConstantValues.push_back(Elt: C);
941 continue;
942 }
943 Values.push_back(Elt: {V, ConstantValues.size()});
944 ConstantValues.push_back(Elt: Constant::getNullValue(Ty: V->getType()));
945 }
946 if (Types.empty())
947 return ConstantPointerNull::get(T: IIRB.PtrTy);
948
949 StructType *STy = StructType::get(Context&: Fn->getContext(), Elements: Types, /*isPacked=*/true);
950 Constant *Initializer = ConstantStruct::get(T: STy, V: ConstantValues);
951
952 GlobalVariable *&GV = IConf.ConstantGlobalsCache[Initializer];
953 if (!GV)
954 GV = new GlobalVariable(*Fn->getParent(), STy, false,
955 GlobalValue::InternalLinkage, Initializer,
956 IConf.getRTName(Prefix: "", Name: "value_pack"));
957
958 auto *AI = IIRB.getAlloca(Fn, Ty: STy);
959 IIRB.IRB.CreateMemCpy(Dst: AI, DstAlign: AI->getAlign(), Src: GV, SrcAlign: GV->getAlign(),
960 Size: IIRB.DL.getTypeAllocSize(Ty: STy));
961 for (auto [Param, Idx] : Values) {
962 auto *Ptr = IIRB.IRB.CreateStructGEP(Ty: STy, Ptr: AI, Idx);
963 IIRB.IRB.CreateStore(Val: Param, Ptr);
964 }
965 return AI;
966}
967
968template <typename Range>
969static void readValuePack(const Range &R, Value &Pack,
970 InstrumentorIRBuilderTy &IIRB,
971 function_ref<void(int, Value *)> SetterCB) {
972 auto *Fn = IIRB.IRB.GetInsertBlock()->getParent();
973 auto &DL = Fn->getDataLayout();
974 SmallVector<Value *> ParameterValues;
975 unsigned Offset = 0;
976 for (const auto &[Idx, RE] : enumerate(R)) {
977 Value *V = getValue(RE);
978 if (!V->getType()->isSized())
979 continue;
980 Offset += 8;
981 auto VSize = DL.getTypeAllocSize(Ty: V->getType());
982 auto Padding = alignTo(Size: VSize, Align: 8) - VSize;
983 Offset += Padding;
984 auto *Ptr = IIRB.IRB.CreateConstInBoundsGEP1_32(Ty: IIRB.Int8Ty, Ptr: &Pack, Idx0: Offset);
985 auto *NewV = IIRB.IRB.CreateLoad(Ty: V->getType(), Ptr);
986 SetterCB(Idx, NewV);
987 Offset += VSize;
988 }
989}
990
991Value *BaseInstructionIO::getOpcode(Value &V, Type &Ty,
992 InstrumentationConfig &IConf,
993 InstrumentorIRBuilderTy &IIRB) {
994 auto &I = cast<Instruction>(Val&: V);
995 return getCI(IT: &Ty, Val: I.getOpcode());
996}
997
998Value *BaseInstructionIO::getTypeSize(Value &V, Type &Ty,
999 InstrumentationConfig &IConf,
1000 InstrumentorIRBuilderTy &IIRB) {
1001 auto &I = cast<Instruction>(Val&: V);
1002 auto &DL = I.getDataLayout();
1003 return getCI(IT: &Ty, Val: DL.getTypeStoreSize(Ty: V.getType()));
1004}
1005
1006Value *BaseInstructionIO::getLeftOperand(Value &V, Type &Ty,
1007 InstrumentationConfig &IConf,
1008 InstrumentorIRBuilderTy &IIRB) {
1009 auto &I = cast<Instruction>(Val&: V);
1010 return I.getOperand(i: 0);
1011}
1012
1013Value *BaseInstructionIO::getRightOperand(Value &V, Type &Ty,
1014 InstrumentationConfig &IConf,
1015 InstrumentorIRBuilderTy &IIRB) {
1016 auto &I = cast<Instruction>(Val&: V);
1017 if (I.getNumOperands() > 1)
1018 return I.getOperand(i: 1);
1019 return PoisonValue::get(T: &Ty);
1020}
1021
1022Value *BaseInstructionIO::getTypeId(Value &V, Type &Ty,
1023 InstrumentationConfig &IConf,
1024 InstrumentorIRBuilderTy &IIRB) {
1025 return getCI(IT: &Ty, Val: V.getType()->getTypeID());
1026}
1027
1028Value *BaseInstructionIO::getSubTypeId(Value &V, Type &Ty,
1029 InstrumentationConfig &IConf,
1030 InstrumentorIRBuilderTy &IIRB) {
1031 return getSubTypeID(OpTy&: *V.getType(), ReqTy&: Ty);
1032}
1033
1034/// FunctionIO
1035/// {
1036void FunctionIO::init(InstrumentationConfig &IConf,
1037 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1038 using namespace std::placeholders;
1039 if (UserConfig)
1040 Config = *UserConfig;
1041
1042 bool IsPRE = getLocationKind() == InstrumentationLocation::FUNCTION_PRE;
1043 if (Config.has(Opt: PassAddress))
1044 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "address", "The function address.",
1045 IRTArg::NONE, getFunctionAddress));
1046 if (Config.has(Opt: PassName))
1047 IRTArgs.push_back(Elt: IRTArg(IIRB.PtrTy, "name", "The function name.",
1048 IRTArg::STRING, getFunctionName));
1049 if (Config.has(Opt: PassNumArguments))
1050 IRTArgs.push_back(
1051 Elt: IRTArg(IIRB.Int32Ty, "num_arguments",
1052 "Number of function arguments (without varargs).", IRTArg::NONE,
1053 std::bind(f: &FunctionIO::getNumArguments, args: this, args: _1, args: _2, args: _3, args: _4)));
1054 if (Config.has(Opt: PassArguments))
1055 IRTArgs.push_back(Elt: IRTArg(
1056 IIRB.PtrTy, "arguments", "Description of the arguments.",
1057 (IsPRE && Config.has(Opt: ReplaceArguments) ? IRTArg::REPLACABLE_CUSTOM
1058 : IRTArg::NONE) |
1059 IRTArg::VALUE_PACK,
1060 std::bind(f: &FunctionIO::getArguments, args: this, args: _1, args: _2, args: _3, args: _4),
1061 std::bind(f: &FunctionIO::setArguments, args: this, args: _1, args: _2, args: _3, args: _4)));
1062 if (Config.has(Opt: PassIsMain))
1063 IRTArgs.push_back(Elt: IRTArg(IIRB.Int8Ty, "is_main",
1064 "Flag to indicate it is the main function.",
1065 IRTArg::NONE, isMainFunction));
1066 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1067 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1068}
1069
1070Value *FunctionIO::getFunctionAddress(Value &V, Type &Ty,
1071 InstrumentationConfig &IConf,
1072 InstrumentorIRBuilderTy &IIRB) {
1073 auto &Fn = cast<Function>(Val&: V);
1074 if (Fn.isIntrinsic())
1075 return Constant::getNullValue(Ty: &Ty);
1076 return &V;
1077}
1078Value *FunctionIO::getFunctionName(Value &V, Type &Ty,
1079 InstrumentationConfig &IConf,
1080 InstrumentorIRBuilderTy &IIRB) {
1081 auto &Fn = cast<Function>(Val&: V);
1082 return IConf.getGlobalString(S: IConf.DemangleFunctionNames->getBool()
1083 ? demangle(MangledName: Fn.getName())
1084 : Fn.getName(),
1085 IIRB);
1086}
1087Value *FunctionIO::getNumArguments(Value &V, Type &Ty,
1088 InstrumentationConfig &IConf,
1089 InstrumentorIRBuilderTy &IIRB) {
1090 auto &Fn = cast<Function>(Val&: V);
1091 if (!Config.ArgFilter)
1092 return getCI(IT: &Ty, Val: Fn.arg_size());
1093 auto FRange = make_filter_range(Range: Fn.args(), Pred: Config.ArgFilter);
1094 return getCI(IT: &Ty, Val: std::distance(first: FRange.begin(), last: FRange.end()));
1095}
1096Value *FunctionIO::getArguments(Value &V, Type &Ty,
1097 InstrumentationConfig &IConf,
1098 InstrumentorIRBuilderTy &IIRB) {
1099 auto &Fn = cast<Function>(Val&: V);
1100 if (!Config.ArgFilter)
1101 return createValuePack(R: Fn.args(), IConf, IIRB);
1102 return createValuePack(R: make_filter_range(Range: Fn.args(), Pred: Config.ArgFilter), IConf,
1103 IIRB);
1104}
1105Value *FunctionIO::setArguments(Value &V, Value &NewV,
1106 InstrumentationConfig &IConf,
1107 InstrumentorIRBuilderTy &IIRB) {
1108 auto &Fn = cast<Function>(Val&: V);
1109 auto *AIt = Fn.arg_begin();
1110 auto CB = [&](int Idx, Value *ReplV) {
1111 while (Config.ArgFilter && !Config.ArgFilter(*AIt))
1112 ++AIt;
1113 Fn.getArg(i: Idx)->replaceUsesWithIf(New: ReplV, ShouldReplace: [&](Use &U) {
1114 return IIRB.NewInsts.lookup(Val: cast<Instruction>(Val: U.getUser())) != IIRB.Epoch;
1115 });
1116 ++AIt;
1117 };
1118 if (!Config.ArgFilter)
1119 readValuePack(R: Fn.args(), Pack&: NewV, IIRB, SetterCB: CB);
1120 else
1121 readValuePack(R: make_filter_range(Range: Fn.args(), Pred: Config.ArgFilter), Pack&: NewV, IIRB,
1122 SetterCB: CB);
1123 return &Fn;
1124}
1125Value *FunctionIO::isMainFunction(Value &V, Type &Ty,
1126 InstrumentationConfig &IConf,
1127 InstrumentorIRBuilderTy &IIRB) {
1128 auto &Fn = cast<Function>(Val&: V);
1129 return getCI(IT: &Ty, Val: Fn.getName() == "main");
1130}
1131
1132/// UnreachableIO
1133///{
1134void UnreachableIO::init(InstrumentationConfig &IConf,
1135 InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
1136 if (UserConfig)
1137 Config = *UserConfig;
1138 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1139 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1140}
1141///}
1142
1143/// AllocaIO
1144///{
1145void AllocaIO::init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
1146 ConfigTy *UserConfig) {
1147 if (UserConfig)
1148 Config = *UserConfig;
1149
1150 bool IsPRE = getLocationKind() == InstrumentationLocation::INSTRUCTION_PRE;
1151 if (!IsPRE && Config.has(Opt: PassAddress))
1152 IRTArgs.push_back(
1153 Elt: IRTArg(IIRB.PtrTy, "address", "The allocated memory address.",
1154 Config.has(Opt: ReplaceAddress) ? IRTArg::REPLACABLE : IRTArg::NONE,
1155 InstrumentationOpportunity::getValue,
1156 InstrumentationOpportunity::replaceValue));
1157 if (Config.has(Opt: PassSize))
1158 IRTArgs.push_back(Elt: IRTArg(
1159 IIRB.Int64Ty, "size", "The allocation size.",
1160 (IsPRE && Config.has(Opt: ReplaceSize)) ? IRTArg::REPLACABLE : IRTArg::NONE,
1161 getSize, setSize));
1162 if (Config.has(Opt: PassAlignment))
1163 IRTArgs.push_back(Elt: IRTArg(IIRB.Int64Ty, "alignment",
1164 "The allocation alignment.", IRTArg::NONE,
1165 getAlignment));
1166
1167 addCommonArgs(IConf, Ctx&: IIRB.Ctx, PassId: Config.has(Opt: PassId));
1168 IConf.addChoice(IO&: *this, Ctx&: IIRB.Ctx);
1169}
1170
1171Value *AllocaIO::getSize(Value &V, Type &Ty, InstrumentationConfig &IO,
1172 InstrumentorIRBuilderTy &IIRB) {
1173 auto &AI = cast<AllocaInst>(Val&: V);
1174 const DataLayout &DL = AI.getDataLayout();
1175 Value *SizeValue = nullptr;
1176 TypeSize TypeSize = AI.getAllocationBaseSize(DL);
1177 if (TypeSize.isFixed()) {
1178 SizeValue = getCI(IT: &Ty, Val: TypeSize.getFixedValue());
1179 } else {
1180 auto *NullPtr = ConstantPointerNull::get(T: AI.getType());
1181 SizeValue = IIRB.IRB.CreatePtrToInt(
1182 V: IIRB.IRB.CreateGEP(Ty: AI.getAllocatedType(), Ptr: NullPtr,
1183 IdxList: {IIRB.IRB.getInt32(C: 1)}),
1184 DestTy: &Ty);
1185 }
1186 if (AI.isArrayAllocation())
1187 SizeValue = IIRB.IRB.CreateMul(
1188 LHS: SizeValue, RHS: IIRB.IRB.CreateZExtOrBitCast(V: AI.getArraySize(), DestTy: &Ty));
1189 return SizeValue;
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().getFirstNonPHIOrDbgOrAlloca());
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