#include<DAG.h>
struct str {
x,y;
};
//Convert ConstantExpr as Instruction
//%1 = load volatile i64, i64* getelementptr inbounds (%struct.str, %struct.str* @global, i64 0, i32 1)
//->%1.1 = getelementptr inbounds (%struct.str, %struct.str* @global, i64 0, i32 1);
// %1 = load volatile i64, i64* %1.1
void ConvertConstantExprToInst(Module &m);
//build StructType's StructTypeDAG, vertex is StructType
StructTypeDAG *struct_type_DAG = new StructTypeDAG();
//function_list save bc’s function process sequence
list<Function*> function_list;
void TraverseIR(function_list) {
//firstly, get the Module's Function_List(save the list starting from main)
(1)unordered_set<Function *> function_set;
//secondly, process each instructions of function
//get the function_main, traverse the function_main
(2)TraverseFunctionInstruction(Function *f, function_list);
//the result of function_list has repeated elements, just save the first time data by function_set;
(3)getFunctionList(function_list)
(final_1)function_set.clear()
}
void TraverseFunctionInstruction(Function *f, function_list) {
for each Instruction of f :
if (Instruction is AllocaInst with structType) {
//add the new structType in StructTypeDAG
} else if (Instruction is CallInst) {
//go to the called function
//if the function does not have callInst, put the function into function_list
TraverseFunctionInstruction(f_call,function_list);
}
//traverse all of instructions
function_list.push_back(f);
}
void RemoveStruct::BuildHierarchyInfo(list<Function*> &function_list) {
TraverseIdentifiedStructTypes();
//process the BC to get the function_list & struct_type_DAG
TraverseIR(function_list);
struct_type_DAG->printStructType();
}
// the main function of RemoveStruct
void RemoveStruct::RemoveStructMain(){
//Convert ConstantExpr as Instruction
ConvertConstantExprToInst();
//func_list save bc's function process sequence
list<Function*> func_list;
BuildHierarchyInfo(func_list);
processStructValue();
}
void processStructValue(Module &m) {
//save delete values
list<Value*> delete_list;
//Correspondence of new value and old value (include function arguments)
unordered_map<Value *, vector<Value *> > Value_umap;
//uset save the StructType to be processed
unordered_set<StructType *> uset;
struct_type_DAG.TopLevelStructType(uset);
while struct_type_DAG->hasTopLevelVertex() {
void processGlobalVar(uset);
for each Function of function_list : {
if (Function in func_umap_) {
processFuncBody(Mid_func, uset);
} else {
processFuncBody(Function, uset);
}
}
struct_type_DAG.ProcessTopLevelVertex(uset);
}
}
void processGlobalVar(uset) {
for each GlobalVariables of GlobalVariableList:
//查找StructType *a是否存在,用uset.find(a)
if(GlobalVariable's Type in uset)
{
new gv_x, gv_y :Value_umap.insert(GlobalVariable,vector<Value*>(gv_x,gv_y))
GlobalVariable insert delete_list
} else {
continue;
}
}
void processFuncArgu(Value_umap){
for each arg of Function:{
if (arg in Value_umap){
//arg.x, arg.y get from Value_umap.find(arg);
create new_function(arg.x, arg.y)
Value_umap.insert(arg, vector<Value*>(arg.x,arg.y))
Function insert delete_list
}
}
for each Value of delete_list{
delete Value
}
}
void processFuncBody(Value_umap,Function) {
for each Value of function:{
if(Value is variable) {
if (variable's Type in uset)
{
new sub_variable :Value_umap.insert(variable, vector<Value*>(sub_variables))
variable insert delete_list
} else {
continue;
}
}
//start to process the Instructions in function
//processReslovedValue(inst)
else if (Value is an operation Instruction) {
if(Instruction中的input value in Value_umap) {
if(%1 = LoadInst(str)) {
//str.x、str.y get from Value_umap.find(str);
表达方式:%2 = LoadInst(str.x); %3 = LoadInst(str.y);
Value_umap.insert(%1, vector<Value*>(%2,%3))
%1 insert delete_list
} else if (%1 = GetElementPtrInst(str)) {
表达方式:%2 = GetElementPtrInst(str.x);
Value_umap.insert(%1, vector<Value*>(%2))
%1 insert delete_list
} else if (%1 = MemCpyInst(str_1,str_2)) {
//str_1.x,str_1.y get from Value_umap.find(str_1); str_2.x,str_2.y get from Value_umap.find(str_2);
表达方式:%2 = MemCpyInst(str_1.x,str_2.x); %3 = MemCpyInst(str_1.y,str_2.y);
Value_umap.insert(%1, vector<Value*>(%2,%3))
%1 insert delete_list
} else if (%1 = CallInst(str_1,str_2)) {
表达方式:%2 = CallInst(str_1.x,str_1.y,str_2.x,str_2.y);
Value_umap.insert(%1, vector<Value*>(%2))
表达方式:CallFunction(arg_str_1,arg_str_2):分解 arg_str_1:arg_str_1_x,arg_str_1_y arg_str_2:arg_str_2_x,arg_str_2_y
Value_umap.insert(arg_str_1, vector<Value*>(arg_str_1_x,arg_str_1_y))
Value_umap.insert(arg_str_2, vector<Value*>(arg_str_2_x,arg_str_2_y))
%1 insert delete_list
} else if (%1 = BitcastInst(str)) {
//语句不改变,记录str.x str.y
Value_umap.insert(%1, vector<Value*>(%1, str.x, str.y))
} else if ((%1 = StoreInst(str to dest)) {
表达方式:%2 = StoreInst(str.x to dest.x); %3 = StoreInst(str.y to dest.y);
Value_umap.insert(%1, vector<Value*>(%2,%3))
}
//如果当前指令无法分解,就记录该指令及其sub_value信息于Value_umap,等待使用该条指令再分解。
Instruction insert delete_list
} else {
continue;
}
}
}
}
一、CallInstProcess()
//callInst是最终指令,直接处理,不需要被别人调用。
//callInst A_x,A_y的类型需要与A保持一致,function的同样
callInst(A,B),其中A decompose to A_x,A_y
(1)处理main函数时,中途遇到callInst(A),处理old_func(A),
(2)创建有body的Mid_func(A,A_x,A_y) [func_map(old_func, Mid_func),umap(A, vector(A_x, A_y))]
(3)创建new_func(A_x,A_y) 目的:给callInst生成callInst(A_x,A_y) [func_map(Mid_func,new_func)]
(4)当function_list遇到old_func时,处理Mid_func,得到最终的Mid_func,只有其参数需删除
(5)替换Mid_func,将其body copy给new_func。
(6)new_func代替old_func在function_list中的位置 [old_func->eraseFromParent();Mid_func->eraseFromParent()]
拿到一条callInst,需要分解的变量为N个,同时得到N个分解后子变量
(1)需要修改的变量:Type为structure的struct变量 ,其对应处理函数是PointerAsFunctionArg()。
(2)需要修改的变量:Type为iN的struct变量,其对应处理函数是LoadiNAsFunctionArg()
(1)operation为allocaInst或global或argument,都是variable, value_umap_必然保存了该变量。
(2)operation为其他Inst,转入处理
二、LoadInstProcess()
Value *load_src = inst->getOperand(0);
if (value_umap_.find(load_src) != value_umap_.end()) {
if (isVariable(load_src)) {
assert(0);
} else {
//需要处理loadInst+load_src两个指令,分情况讨论。
if (isa<llvm::BitCastInst>(load_src)) {
if (load_src return type is iN) {
//BitcastNextLoadProcess(loadI);
//%2 = bitcast %1 to iN*
//%3 = load iN* %2
首先(%1的Type、iN)得到memoryTable的表,表中存的是sub_value及其lsb与msb
map_table(%3,memorytable)
} else {
assert(0);
}
} else if (isa<llvm::GetElementPtrInst>(load_src)) {
if (GetElementPtrInst return structType) {
}
}
}
}
二、otherInst(inst){
//shl、lshr、ashr、and、or、xor、trunc、zext、sext
value_umap_.insert(inst,inst) //assert(inst==isnt)
if (map_table.find(inst)) {
}
}
二、StoreInstProcess()
if (Store_src is LoadInst) {
map_table(LoadInst,memorytable),利用memorytable处理。
}
if (Store_dest is BitCastInst) {
}
二、BitCastInstProcess()
//单独一条指令,无法做任何处理
//暂时只将bitcastInst放入value_umap_,等待其user处理。
%120 = getelementptr inbounds [2 x [2 x %struct.point]], [2 x [2 x %struct.point]]* @global_8, i64 0, i64 1
%121 = bitcast [2 x %struct.point]* %120 to i16*
inst_1(inst_2) & map(inst_2,inst_3)// when have inst_1,actually we get inst_2 & inst_3
三、GetElementPtrInstProcess(inst):
//(1)getelementptrInst中第二个operand不是constantInt 0,则必须保留。
//(2)特殊情况:
// %3 = i8* getelementptr inbounds (%struct.str, %struct.str* @global, i32 0, i32 0);
// call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %3, i64 20, i32 4, i1 true),
// can not resolved directly
//(3)注意delete_list_需要搜集的instruction
拿到一个getelementptr,先判断src是否在value_umap_,在判断src是不是variable。
(1)为variable时,判断inst能否分解:
能分解value_umap_(inst,sub_value)
不能分解value_umap_(inst,inst)需要下面语句一起处理
(2)不为variable时,是一条instruction
src_inst在value_umap_中的vector中的inst不是src_inst,说明src_inst已经处理好,不需要再次处理。跳过。
src_inst在value_umap_中的vector中的inst是src_inst,说明两条语句结合处理。
处理结果放于vector。能处理完毕就放new_inst,不能就放src_inst自身。等待下次遇到再处理。
if (value_umap_ find input_val) {
//写成一个函数
if (input_val为allocainst或global或argument) {
if (input_val->isStructType()) {
if (inst->getNumOperands() > 2) {
value_umap_.insert(inst,inst_x);
//GetelementptrStructResloved(inst);
}
} else if (input_val->isArrayStructType()) {
if (inst->getNumOperands() > array_layers + 2) {
value_umap_.insert(inst,inst_x);
}
} else {
assert(0);
}
}
else {
//另外一个函数
//process instructions
vector<Value *> vec;
vec = value_umap_.find(input_val);
input_val = vec.at(0);
if (isa<llvm::GetElementPtrInst>(input_val)) {
%3 = input_val + inst;
if (%3 可以分解出子变量inst_x) {
value_umap_.insert(inst,inst_x);
} else {
value_umap_.insert(inst,%3);
}
} else if (isa<llvm::BitCastInst>(input_val)) {
// %struct.point = type { float, double }
// %54 = bitcast %struct.point* %0 to { float, double }*
// %55 = getelementptr inbounds { float, double }, { float, double }* %54, i32 0, i32 0
//分解出%0的元素
value_umap_.insert(inst,%0_x);
} else {
assert(0);
}
}
}
二、MemcpyInstrProcess(inst):
if (value_umap_ find src_val) {
if (src_val is BitcastInst) {
} else if(src_val is GetElementPtrInst) {
//GetElementPtrInstWithMemcpy(inst);
}
}
if (value_umap_ find dest_val) {
if (dest_val is BitcastInst) {
} else if(dest_val is GetElementPtrInst) {
//GetElementPtrInstWithMemcpy(inst);
}
}
if (st_dest == st_src) process
#include<DAG.h>
class StructTypeDAG {
private:
typedef struct TypeMemory {
Type *ty;
int LSB;
int MSB;
TypeMemory(Type *Ty, int L, int M) {
ty = Ty;
LSB = L;
MSB = M;
}
}type_mem;
struct Vertex{
StructType *struct_Type_;
//build edge to children vertex
std::unordered_set<Vertex *> vertex_children_;
//StructType memoryTable
std::unordered_map<int , type_mem> memoryTable;
};
public:
// Contructor
StructTypeDAG() {}
// Destructor
~StructTypeDAG();
//create graph Vertex
bool FindStructType(StructType *struct_Type);
void CreateVertex(StructType *struct_Type);
//put zero indegree vertexs's StructType into uset
void TopLevelStructType(unordered_set<StructType *> &uset);
void DestroyVertex(unordered_set<StructType *> &uset);
private:
//bulid hierarchy relationship
void ConnectVertex(Vertex *parent, Vertex *child) const;
//look up the position of StructType in DAG
unordered_map<StructType *, Vertex *> StructType_map_;
};
(1)外部输入一个StructType *st
if(!StructTypeDAG_->hasStructType(st)){
StructTypeDAG_->addStructTypeToDAG(st);
}
(2) addStructTypeToDAG(StructType *st){
//new vertex
1、new_vertex = CreateVertex(st);
//build relationship between struct_type & new_vertex
2、StructType_map_.insert((struct_type, new_vertex));
//Perfect information of new_vertex
//info: vertex_parent & vertex_children & memoryTable & alignment & length
3、CreateVertexMemoryTable(Vertex *new_vertex);
}
//此时StructTypeToDAG相关信息全部建完。
(3)//uset saves all top level StructType of DAG
unordered_set<StructType *> &uset;
StructTypeDAG_->TopLevelStructType(uset);
(4)//delete all info of uset's vertexs, uset.clear()
StructTypeDAG_->DestroyTopLevelVertex(uset);