2020-01-17rm_struct總結文檔

代碼總框架:
一、第一層函數 :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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章