在LLVM自定义的pass中,向IR中插入一个函数,将llvm::instruction::getdebugloc()->getfilename()的返回值作为参数传入该函数,给出完整示例
时间: 2023-12-06 21:45:43 浏览: 108
llvm-semantics:K语言中LLVM IR的形式语义
下面是一个简单的示例,假设我们要向IR中插入一个函数,该函数接受一个字符串参数,并在标准输出中打印该字符串。我们将使用`getdebugloc()`函数来获取当前指令的源代码位置信息,并将其作为函数参数传递。
```c++
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
struct MyPass : public FunctionPass {
static char ID;
MyPass() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
LLVMContext &Context = F.getContext();
Module *M = F.getParent();
FunctionType *PrintFnTy = FunctionType::get(
Type::getVoidTy(Context), {Type::getInt8PtrTy(Context)}, false);
Function *PrintFn = Function::Create(
PrintFnTy, GlobalValue::ExternalLinkage, "print_string", M);
BasicBlock &EntryBB = F.getEntryBlock();
Instruction *FirstInst = EntryBB.getFirstNonPHIOrDbg();
IRBuilder<> Builder(FirstInst);
std::string FileName = F.getName().str() + ".cpp";
Value *FileNameArg =
Builder.CreateGlobalStringPtr(FileName, "filename");
Builder.CreateCall(PrintFn, {FileNameArg});
return true;
}
};
}
char MyPass::ID = 0;
static RegisterPass<MyPass> X("my-pass", "My Pass", false, false);
```
在这个示例中,我们定义了一个名为`MyPass`的函数pass,并在其中重写了`runOnFunction`方法。在这个方法中,我们首先获取当前函数的上下文和模块信息,然后定义了一个新的函数类型`PrintFnTy`,该函数接受一个`i8*`类型的指针参数,并返回`void`类型。接下来,我们使用`Function::Create`方法创建了一个名为`print_string`的新函数,并将其添加到当前模块中。
然后,我们获取了当前函数的第一个指令,并使用`IRBuilder`类创建了一个新的指令插入器。我们使用`Function::getName()`方法获取当前函数的名称,并将其与`.cpp`字符串连接,创建了一个新的文件名字符串。
接下来,我们使用`IRBuilder::CreateGlobalStringPtr`方法创建了一个全局字符串指针,该字符串指针指向我们刚刚创建的文件名字符串。最后,我们使用`IRBuilder::CreateCall`方法调用了我们刚刚创建的`print_string`函数,并将文件名字符串指针作为参数传递给它。
最后,我们将我们的pass注册为LLVM的函数pass,并命名为`my-pass`。当我们运行LLVM时,我们可以使用`-my-pass`选项来执行我们的pass。
阅读全文