我是 LLVM-IR Pass 的初学者。 现在我想在每个 IR 指令中插入一个代码片段。 代码片段如下:
if (a==1) func1(); else func2();
a 是一个全局变量。
但是现在我遇到了几个错误,主要是: “指令有假父指针!” “‘main’函数中的基本块没有终止符!”
我需要知道我将这些代码插入到每条指令中的想法是否可行。 感谢您的帮助!
我尝试通过chatgpt解决这个问题,但失败了
我希望有人告诉我这个想法是否可行,我不在乎它有多困难。
`#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/BasicBlock.h"
using namespace llvm;
namespace {
struct InsertConditionalCallsPass : public FunctionPass {
static char ID;
InsertConditionalCallsPass() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
Module *M = F.getParent();
LLVMContext &Context = M->getContext();
FunctionCallee Func1 = M->getOrInsertFunction("func1", Type::getVoidTy(Context));
FunctionCallee Func2 = M->getOrInsertFunction("func2", Type::getVoidTy(Context));
GlobalVariable *VarA = M->getNamedGlobal("a");
if (!VarA) return false;
for (auto BI = F.begin(), BE = F.end(); BI != BE;) {
BasicBlock &BB = *BI++;
auto II = BB.begin();
if (II == BB.end()) continue;
Instruction *Inst = &*II;
BasicBlock *OldBB = Inst->getParent();
BasicBlock *CondBB = OldBB->splitBasicBlock(Inst);
OldBB->getTerminator()->eraseFromParent();
BasicBlock *ThenBB = BasicBlock::Create(Context, "then", &F, CondBB);
BasicBlock *ElseBB = BasicBlock::Create(Context, "else", &F, CondBB);
BasicBlock *MergeBB = BasicBlock::Create(Context, "ifcont", &F);
IRBuilder<> Builder(OldBB);
Value *LoadedA = Builder.CreateLoad(VarA->getType()->getPointerElementType(), VarA);
Value *Cond = Builder.CreateICmpEQ(LoadedA, Builder.getInt32(1));
Builder.CreateCondBr(Cond, ThenBB, ElseBB);
// Then block
Builder.SetInsertPoint(ThenBB);
Builder.CreateCall(Func1, {});
Builder.CreateBr(MergeBB);
// Else block
Builder.SetInsertPoint(ElseBB);
Builder.CreateCall(Func2, {});
Builder.CreateBr(MergeBB);
// Merge block
Builder.SetInsertPoint(MergeBB);
Builder.CreateBr(CondBB);
BB.getInstList().splice(MergeBB->begin(), BB.getInstList(), Inst);
}
return true;
}
};
}
char InsertConditionalCallsPass::ID = 0;
static RegisterPass<InsertConditionalCallsPass> X("insert-conditional-calls", "Insert Conditional Calls in Functions", false, false);
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/BasicBlock.h"
using namespace llvm;
namespace {
struct InsertConditionalCallsPass : public FunctionPass {
static char ID;
InsertConditionalCallsPass() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
Module *M = F.getParent();
LLVMContext &Context = M->getContext();
FunctionCallee Func1 = M->getOrInsertFunction("func1", Type::getVoidTy(Context));
FunctionCallee Func2 = M->getOrInsertFunction("func2", Type::getVoidTy(Context));
GlobalVariable *VarA = M->getNamedGlobal("a");
if (!VarA)
return false;
for (auto &BB : F) {
// Insert at the beginning of each basic block
IRBuilder<> Builder(&*BB.begin());
Value *LoadedA = Builder.CreateLoad(VarA->getType()->getPointerElementType(), VarA);
Value *Cond = Builder.CreateICmpEQ(LoadedA, Builder.getInt32(1));
Builder.CreateCondBr(Cond, BB.getTerminator()->getSuccessor(0), BB.getTerminator()->getSuccessor(1));
// Create new blocks and insert calls
BasicBlock *ThenBB = BasicBlock::Create(Context, "then", &F, BB.getTerminator()->getSuccessor(0));
BasicBlock *ElseBB = BasicBlock::Create(Context, "else", &F, BB.getTerminator()->getSuccessor(1));
BasicBlock *MergeBB = BasicBlock::Create(Context, "ifcont", &F);
Builder.SetInsertPoint(ThenBB);
Builder.CreateCall(Func1, {});
Builder.CreateBr(MergeBB);
Builder.SetInsertPoint(ElseBB);
Builder.CreateCall(Func2, {});
Builder.CreateBr(MergeBB);
Builder.SetInsertPoint(MergeBB);
}
return true;
}
};
}
char InsertConditionalCallsPass::ID = 0;
static RegisterPass<InsertConditionalCallsPass>
X("insert-conditional-calls", "Insert Conditional Calls in Functions", false, false);
在此更新的技术中,条件调用被插入到每个基本块的开头,从而保持正确的控制流结构。