LLVM 编写一个修改IR变量值的Pass

一、所需创建文件

如图所示层级关系以及所需文件:
在这里插入图片描述

二、输入测试的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.so llvm-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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

内存不足°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值