llvm - 编写 LLVM 转换通道以在每个函数的开头注入延迟
问题描述
我是 LLVM 新手,我正在尝试编写一个 LLVM 转换通道,它将在运行时向每个调用函数的开头注入延迟。
我发现以下代码将 printf 语句注入到每个函数的开头。
如何相应地更改代码以注入延迟而不是 printf?(我使用的是 LLVM 10。)
下面是代码:
bool InjectFuncCall::runOnModule(Module &M) {
bool InsertedAtLeastOnePrintf = false;
auto &CTX = M.getContext();
PointerType *PrintfArgTy = PointerType::getUnqual(Type::getInt8Ty(CTX));
// STEP 1: Inject the declaration of printf
// ----------------------------------------
// Create (or _get_ in cases where it's already available) the following
// declaration in the IR module:
// declare i32 @printf(i8*, ...)
// It corresponds to the following C declaration:
// int printf(char *, ...)
FunctionType *PrintfTy = FunctionType::get(
IntegerType::getInt32Ty(CTX),
PrintfArgTy,
/*IsVarArgs=*/true);
FunctionCallee Printf = M.getOrInsertFunction("printf", PrintfTy);
// Set attributes as per inferLibFuncAttributes in BuildLibCalls.cpp
Function *PrintfF = dyn_cast<Function>(Printf.getCallee());
PrintfF->setDoesNotThrow();
PrintfF->addParamAttr(0, Attribute::NoCapture);
PrintfF->addParamAttr(0, Attribute::ReadOnly);
// STEP 2: Inject a global variable that will hold the printf format string
// ------------------------------------------------------------------------
llvm::Constant *PrintfFormatStr = llvm::ConstantDataArray::getString(
CTX, "(llvm-tutor) Hello from: %s\n(llvm-tutor) number of arguments: %d\n");
Constant *PrintfFormatStrVar =
M.getOrInsertGlobal("PrintfFormatStr", PrintfFormatStr->getType());
dyn_cast<GlobalVariable>(PrintfFormatStrVar)->setInitializer(PrintfFormatStr);
// STEP 3: For each function in the module, inject a call to printf
// ----------------------------------------------------------------
for (auto &F : M) {
if (F.isDeclaration())
continue;
// Get an IR builder. Sets the insertion point to the top of the function
IRBuilder<> Builder(&*F.getEntryBlock().getFirstInsertionPt());
// Inject a global variable that contains the function name
auto FuncName = Builder.CreateGlobalStringPtr(F.getName());
// Printf requires i8*, but PrintfFormatStrVar is an array: [n x i8]. Add
// a cast: [n x i8] -> i8*
llvm::Value *FormatStrPtr =
Builder.CreatePointerCast(PrintfFormatStrVar, PrintfArgTy, "formatStr");
// The following is visible only if you pass -debug on the command line
// *and* you have an assert build.
LLVM_DEBUG(dbgs() << " Injecting call to printf inside " << F.getName()
<< "\n");
// Finally, inject a call to printf
Builder.CreateCall(
Printf, {FormatStrPtr, FuncName, Builder.getInt32(F.arg_size())});
InsertedAtLeastOnePrintf = true;
}
return InsertedAtLeastOnePrintf;
}
如果有适合初学者的优秀 LLVM 教程的链接,那就太好了。
解决方案
您必须以与声明delay
相同的方式声明函数,printf
除非您要将参数类型从 更改i8*
为i32
。对于教程,您可以查看这些
https://anoopsarkar.github.io/compilers-class/llvm-practice.html\
https://www.usna.edu/Users/cs/wcbrown/courses/F19SI413/lab/l13/lab.html
推荐阅读
- r - 哪个 R 命令在 R 中显示整个数据帧数据和结构?
- gitlab - 托管多个需要在 gitlab ci 上打开相同端口的服务
- reactjs - HashRouter 多个布局将始终显示一个布局
- powershell - 当我选择“使用 powershell 运行”时,Powershell 脚本可以正确执行,但当我“使用”powershell 打开或双击它时不会正确执行
- android - 如何在 Firestore RecylerView (Firestore UI) 中过滤和排序我的文档?
- java - 布尔值不会改变 insade 类 java
- java - 从字节数组生成的 zip 文件无效
- python - Python函数调用堆栈:train_function错误
- mysql - 在mysql中垂直向上移动列数据
- html - 按下按钮时滚动到网页中某个部分的 HTML 代码