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