1+ /* ========================== begin_copyright_notice ============================
2+
3+ Copyright (C) 2024 Intel Corporation
4+
5+ SPDX-License-Identifier: MIT
6+
7+ ============================= end_copyright_notice ===========================*/
8+
9+ #include " InjectPrintf.hpp"
10+ #include " llvm/IR/IRBuilder.h"
11+ #include < common/igc_regkeys.hpp>
12+
13+ #include " common/LLVMWarningsPush.hpp"
14+ #include " common/LLVMWarningsPop.hpp"
15+ #include " Compiler/IGCPassSupport.h"
16+
17+
18+ using namespace IGC ;
19+ using namespace llvm ;
20+
21+ char InjectPrintf::ID = 0 ;
22+
23+ #define PASS_FLAG " inject-printf"
24+ #define PASS_DESCRIPTION " Inject printf before load and store operations for ptr Pass."
25+ #define PASS_CFG_ONLY false
26+ #define PASS_ANALYSIS false
27+ IGC_INITIALIZE_PASS_BEGIN (InjectPrintf, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
28+ IGC_INITIALIZE_PASS_END(InjectPrintf, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
29+
30+ enum class InjectPrintfFlagType {
31+ #define INJECT_PRINTF_OPTION (Name, Val ) Name = Val,
32+ #include " igc_regkeys_enums_defs.h"
33+ INJECT_PRINTF_OPTIONS
34+ #undef INJECT_PRINTF_OPTION
35+ #undef INJECT_PRINTF_OPTIONS
36+ };
37+
38+ InjectPrintf::InjectPrintf () : FunctionPass(ID) {
39+ initializeInjectPrintfPass (*PassRegistry::getPassRegistry ());
40+ }
41+
42+ GlobalVariable* InjectPrintf::createGlobalFormatStr (Module* Module, LLVMContext& Context) {
43+ IGC_ASSERT (Module != nullptr );
44+
45+ const char * FormatStrLiteral = " Pointer: %p, Type: %s\n " ;
46+ size_t MaxLength = 256 ;
47+ size_t FormatStrSize = strnlen (FormatStrLiteral, MaxLength) + 1 ;
48+
49+ GlobalVariable* FormatStrGlobal = new GlobalVariable (
50+ *Module,
51+ ArrayType::get (Type::getInt8Ty (Context), FormatStrSize),
52+ true ,
53+ GlobalValue::InternalLinkage,
54+ ConstantDataArray::getString (Context, FormatStrLiteral, true ),
55+ " " ,
56+ nullptr ,
57+ GlobalValue::ThreadLocalMode::NotThreadLocal,
58+ 2
59+ );
60+ FormatStrGlobal->setUnnamedAddr (GlobalValue::UnnamedAddr::Global);
61+
62+ return FormatStrGlobal;
63+ }
64+
65+ Value* InjectPrintf::createGEP (GlobalVariable* GlobalVariable, Instruction* InsertBefore) {
66+ IGC_ASSERT (GlobalVariable != nullptr );
67+ IGC_ASSERT (InsertBefore != nullptr );
68+
69+ LLVMContext& Context = GlobalVariable->getParent ()->getContext ();
70+ const auto Zero = ConstantInt::getSigned (Type::getInt32Ty (Context), 0 );
71+ auto Result = GetElementPtrInst::Create (
72+ GlobalVariable->getValueType (),
73+ GlobalVariable,
74+ { Zero, Zero },
75+ " " ,
76+ InsertBefore
77+ );
78+ Result->setIsInBounds (true );
79+ return Result;
80+ }
81+
82+ void InjectPrintf::insertPrintf (IRBuilder<>& Builder, FunctionCallee PrintfFunc, GlobalVariable* FormatStrGlobal, Instruction* Inst, Value* PointerOperand, Type* ValueType) {
83+ IGC_ASSERT (FormatStrGlobal != nullptr );
84+ IGC_ASSERT (Inst != nullptr );
85+ IGC_ASSERT (PointerOperand != nullptr );
86+ IGC_ASSERT (ValueType != nullptr );
87+
88+ Builder.SetInsertPoint (Inst);
89+ Value* FormatStr = createGEP (FormatStrGlobal, Inst);
90+ std::string TypeStr;
91+ raw_string_ostream RSO (TypeStr);
92+ ValueType->print (RSO);
93+ Value* TypeStrGlobal = Builder.CreateGlobalStringPtr (RSO.str ());
94+ Builder.CreateCall (PrintfFunc, { FormatStr, PointerOperand, TypeStrGlobal });
95+ }
96+
97+ bool InjectPrintf::runOnFunction (Function& F) {
98+ LLVMContext& Context = F.getContext ();
99+ Module* Module = F.getParent ();
100+ if (!Module) {
101+ errs () << " Error: Module is null\n " ;
102+ return false ;
103+ }
104+
105+ IRBuilder<> Builder (Context);
106+ GlobalVariable* FormatStrGlobal = createGlobalFormatStr (Module, Context);
107+
108+ FunctionCallee PrintfFunc = Module->getOrInsertFunction (
109+ " printf" ,
110+ FunctionType::get (
111+ IntegerType::getInt32Ty (Context),
112+ PointerType::get (Type::getInt8Ty (Context), 2 ),
113+ true
114+ )
115+ );
116+
117+ auto InjectPrintfFlag = static_cast <InjectPrintfFlagType>(IGC_GET_FLAG_VALUE (InjectPrintfFlag));
118+ for (auto & BB : F) {
119+ for (auto & I : BB) {
120+ if (auto * Load = dyn_cast<LoadInst>(&I)) {
121+ if (InjectPrintfFlag == InjectPrintfFlagType::InjectPrintfLoads || InjectPrintfFlag == InjectPrintfFlagType::InjectPrintfLoadsAndStores) {
122+ insertPrintf (Builder, PrintfFunc, FormatStrGlobal, Load, Load->getPointerOperand (), Load->getType ());
123+ }
124+ }
125+ if (auto * Store = dyn_cast<StoreInst>(&I)) {
126+ if (InjectPrintfFlag == InjectPrintfFlagType::InjectPrintfStores || InjectPrintfFlag == InjectPrintfFlagType::InjectPrintfLoadsAndStores) {
127+ insertPrintf (Builder, PrintfFunc, FormatStrGlobal, Store, Store->getPointerOperand (), Store->getValueOperand ()->getType ());
128+ }
129+ }
130+ }
131+ }
132+
133+ return true ;
134+ }
0 commit comments