代码总框架:
一、第一层函数 :RemoveStructMain()
其中changBC是主要处理函数,函数findStruct()是用于检测BC文件是否存在structType,以后会用while循环处理。
void RemoveStruct::RemoveStructMain(){
changeBC();
if (findStruct()){
cout<<"RemoveStructMain(): exist structure value!"<<endl;
changeBC();
} else {
outs() << "RemoveStructMain(): Success! " << "\n";
}
}
二、第二层函数:changeBC()
第一个函数pretreatment()对bc进行预处理,将BC中组合语句split开,方便后续处理。
第二个函数getIRStructType()是对module中所有定义的StructTypes进行读取,并将其与其分解出的StructType都存入DAG中。
第三个函数SaveRootGlobalVar(); Traverse the module_ global list to find structure gv and save gv in structDAG
(DAG由多个vertex组成)
struct Vertex{
StructType *struct_Type_;
std::map<Value *, vector<Value *> > vertex_value_;
// vector<Value *> is the resolved values of Value
std::set<Vertex *> vertex_children_;
std::set<Vertex *> vertex_parent_;
};
第四个函数AllocaInstr(); Traverse the module_ allocaInst list to find structure allocaInst and save allocaInst in structDAG
以上全部为构建DAG为处理struct做准备。
第五个函数TopologicalSort(); 通过SaveRootGlobalVar();和 AllocaInstr();这两个函数已经把struct value都存入DAG,下一步则是分解处理。
void RemoveStruct::changeBC() {
//split instruction for serving process struct
while (pretreatment()) {};
if(findStruct()){
getIRStructType();
SaveRootGlobalVar();
AllocaInstr();
StructDAG_->printStructType();
cout<<"DAG construction completed!"<<endl;
TopologicalSort();
//DelUnuseGlobalVarAndAlloca();
}
//assert(findStruct());
//valueMapPrint();
}
三、第三层函数:TopologicalSort()
(1)遍历DAP中的vertex,找出入度为零的vertex,并将其存入队列q。
queue<StructDAG::Vertex*> q;
//q storage vertexs which's indegree are zero
StructDAG_->FindZeroIndegreeVertex(q);
(2)对每个vertex中的struct value进行分解替换处理,并将该struct value删除。
while (!q.empty()) {
StructDAG::Vertex *v = q.front();
q.pop();
//process p
//(2.1)renew the current vertex relations with others
//(2.2)process structure values in current vertex
}
(2.1)当前的vertex V入度为零,对其children vertex进行遍历,renew the current vertex relations with its children,children vertex入度为零 push至queue。最后将V的children vertex set清空。
(ps此时V上两个set清空,只有map上的 std::map<Value *, vector<Value *> > vertex_value_;)
(2.2)
firstly,对同类型StructType的vertex V中所有Value进行resolveValue,此时当前subValue已得到。
secondly,此时已经将Value分解完毕,sub_value在其children vector上,通过user对Value相关指令进行替换和修改。并将V中map上的处理完毕的Value存入list。
(其中有两次processVertexValue(iter->first);第一次是正常处理BC中原本的struct,第二次是为了处理我在处理第一次struct生成与struct相关instruction。)
thirdly,通过list删除所有的Value,对当前的V的map进行清空,对有效位的set进行clear。
(3)
函数function_map_process()为了删除oldFunction,然后对StructDAG进行clear。此时将生成最终无struct的BC。
function_map_process();
StructDAG_->printStructType();
StructDAG_->DestroyVertex();
四、第四层函数: processVertexValue()
主要处理一下五个函数,对应的五条指令都是由DAG上的struct value遍历找到的instruction。
(一)首先处理GetElementPtrInstProcess()函数。
分情况讨论:
1、当GetElementPtrInst的getOperand(0)为IsStructVal时
情况一:NumOperands为2时,assert。
情况二:NumOperands > 2时,进行GetelementptrStructProcess(instr),该函数就是将subValue代替structValue。
2、当GetElementPtrInst的getOperand(0)为IsArrayStructVal时
进行GetelementptrArrayProcess(instr, array_layers);array_layers为当前array层数。
情况一:instr->getNumOperands() < array_layers + 2,
// %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*
getelementptr +bitcast 进行BitCastInstProcess(inst);
//%3 = getelementptr inbounds [2 x %struct.str], [2 x %struct.str]* %1, i64 0, i64 0
//%4 = call fastcc i32 @sum(%struct.str* nonnull %3) #4
getelementptr +call 进行GetElementPtrInstAsCallInstProcess(call_inst, instr);
未写代码打算参考callprocess()进行嫁接
情况二:instr->getNumOperands() == array_layers + 2
// %52 = getelementptr inbounds [2 x %struct.point], [2 x %struct.point]* %global_0, i64 0, i64 1
// %53 = bitcast %struct.point* %52 to i16*
getelementptr +bitcast 进行BitCastInstProcess(inst);
//%3 = getelementptr inbounds [2 x %struct.str], [2 x %struct.str]* %1, i64 0, i64 0, i64 0
//%4 = call fastcc i32 @sum(%struct.str* nonnull %3) #4
getelementptr +call 进行GetElementPtrInstAsCallInstProcess(call_inst, instr);
未写代码打算参考callprocess()进行嫁接
//%47 = getelementptr inbounds %struct.str, %struct.str* %0, i64 0, i32 8
//%48 = getelementptr inbounds [2 x %struct.point], [2 x %struct.point]* %47, i64 0, i64 0, i32 0
进行DoubleGetElementPtrProcess()两条指令进行合并,却没有进行分解替换。
看看情况一情况二是否可以合并!!
情况三:正常情况分解。
// %6 = getelementptr inbounds [2 x [2 x %struct.str]], [2 x [2 x %struct.str]]* @global, i64 0, i64 0, i64 0, i32 0
3、未发现StructType,assert(0),情况不可能。
(二)其次处理MemcpyInstrProcess()函数。
取出需要copy的目标value memcpy_dest。memcpy比较独立。
// get IntrinsicInst op_0 memcpy_dest
Value *memcpy_dest = MemcpyDestValue(instr);
memcpy_src分情况讨论:
情况一:memcpy_src is ConstantExpr
MemcpyToConstantExpr(memcpy_dest, instr_src, instr);
情况二:memcpy_src is GetElementPtrInst
memcpyToGetElementPtrInst(memcpy_dest, getelementptr_src, instr);
情况三:memcpy_src is BitCastInst
memcpyToBitCast(memcpy_dest, bitcast_src, instr);
(三)接着处理LoadInstProcess()函数。
只有一种情况:
load的参数为ConstantExpr
ConstantExpr可以分为bitcast和GetElementPtr,但是一般bitcast在预处理split开了,load中会存在GetElementPtr。直接用GetElementPtrInstProcess(get_inst);处理一下就好。
(四)再处理BitCastInstProcess()函数。
遍历BitCastInst的user种类
情况一:BitcastNextLoadProcess(),重点。
情况二:MemcpyInstrProcess();用之前的处理函数。
情况三:StoreInstProcess(),这个就是做拼接指令的。
(五)最后处理FunctionProcess()函数。
存在于callInst中的structValue,通过callInst找到对应的Function,
llvm::CallInst *inst = llvm::dyn_cast<llvm::CallInst>(CI);
CollectFunctionList(inst, FunctionList, val);
CollectFunctionList():structValue->CallInst->Function->CallInsts
这种需要修改,修改为先用function_map_记录新旧Function,最后进行删除旧的Function。