一、所需创建文件
如图所示层级关系以及所需文件:
二、输入测试的c代码
//test.c
int foo(int a,int b){
int c = a+b;
int d = a+b;
int e = c/d;
int f = c*d;
return c+d+e+f;
}
int main(){
int a = 1,b=2;
int sum = foo(a,b);
return 0;
}
三、创建Pass
//UpdateValues.cpp
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
using namespace llvm;
namespace {
struct UpdateValues : public FunctionPass {
static char ID;
UpdateValues() : FunctionPass(ID) {}
bool runOnFunction(Function& F) override {
if (F.getName() != "main") return false; //只对main函数中的变量值修改
int storeNumber = 0; //记录指令中Store个数
LLVMContext& context = F.getContext();
errs().write_escaped(F.getName()) << '\n'; //输出函数名
for (auto &BB :F)
{
for (auto &I :BB)
{
IRBuilder<> builder(&I); //使用IRBuilder
//errs() << I << "\n"; //输出每一条IR指令
//builder.SetInsertPoint(&i); //forward //插入 新指令 到 当前这条指令 前
Value* con_5 = ConstantInt::get(builder.getInt32Ty(), 5); //创建整形常变量 5
Value* con_10 = ConstantInt::get(builder.getInt32Ty(), 10);// 10
if (I.getOpcode() == Instruction::Store) { //判断是不是Store
storeNumber++;
//errs() << I.getOpcodeName() << ":"; //输出指令名
//errs() << " number is :" << I.getNumOperands()<<" \n"; //输出操作数个数
if (storeNumber > 1 && storeNumber <= 3) { //只对 a,b变量进行重新赋值(test.c中的a,b)
builder.SetInsertPoint(I.getNextNode());// back //插入 新指令 到 当前这条指令 后
I.eraseFromParent();//delete Instruction //删除此条指令
if(2 == storeNumber) //main函数中有返回值0 ,第一个Store是给返回值赋值0,后面两个是对 a,b赋值 (test.c)
builder.CreateStore(con_5, I.getOperand(1)); //getOperand(0)获取的是值的操作数,getOperand(1)获取的需要赋值的操作数,,重新赋值 常数 5 到 a 中
else
builder.CreateStore(con_10, I.getOperand(1));
}
}
}
}
return true;
}
};
}
char UpdateValues::ID = 0;
static RegisterPass<UpdateValues> X("updatevalues", "my Pass");
四、编译
1、将test.c 编译为 test.ll
clang -emit-llvm -S test.c -o -test.ll
2、编译出LLVMUpdateVaules.so
clang
llvm-config --cxxflags
-Wl,-znodelete -fno-rtti -fPIC -shared UpdateValues.cpp -o LLVMUpdateValues.sollvm-config --ldflags
3、生成出 change_test.ll
opt -enable-new-pm=0 -load ./LLVMUpdateValues.so -updatevalues<test.ll> change_test.ll -S
五、主要结果
1、改变前
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 1, i32* %2, align 4
store i32 2, i32* %3, align 4
%5 = load i32, i32* %2, align 4
%6 = load i32, i32* %3, align 4
%7 = call i32 @foo(i32 %5, i32 %6)
store i32 %7, i32* %4, align 4
ret i32 0
}
2、改变后
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 5, i32* %2, align 4
store i32 10, i32* %3, align 4
%5 = load i32, i32* %2, align 4
%6 = load i32, i32* %3, align 4
%7 = call i32 @foo(i32 %5, i32 %6)
store i32 %7, i32* %4, align 4
ret i32 0
}
六、参考文档
1、https://llvm.org/doxygen/IRBuilder_8h_source.html
2、https://blog.csdn.net/qq_42570601/article/details/108059403?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166640803416782414912648%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166640803416782414912648&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~sobaiduend~default-1-108059403-null-null.nonecase&utm_term=LLVM%20IRbuilder&spm=1018.2226.3001.4450