dsa算法(8)

1.3.3.3. 添加函数节点

接下来处理模块内的函数。1461行的addrAnalysis就是AddressTakenAnalysis的实例,方法hasAddressTaken检查FI是否在addressTakenFunctions里。

 

LocalDataStructures::runOnModule(续)

 

1459      // Add Functionsto the globals graph.

1460      for(Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI){

1461        if(addrAnalysis->hasAddressTaken(FI)){

1462          GGB.mergeFunction(FI);

1463        }

1464      }

1465    }

 

216        void mergeFunction(Function*F) { getValueDest(F); }

 

如果是,mergeFunction调用getValueDest为Function创建DSNode,而getValueDest调用addFunction,这个方法立即调用addGlobal把这个Function加入DSNode的Globals。

1.3.3.4. 对函数定义的处理

在创建了所有必需的DSNode节点后,在1472行,formGlobalECs只执行了其中的buildGlobalECs函数,而eliminateUsesOfECGlobals没有执行,因为这时DSInfo是空的。其效果就是全局图中同一个DSNode对应的多个全局对象被合并为同类集,在GlobalsGraph的ScalarMap及对应的DSNode的Globals中只保留同类集的Leader。

 

LocalDataStructures::runOnModule(续)

           

1467    if (hasMagicSections.size())

1468      handleMagicSections(GlobalsGraph, M);

1469 

1470    // Next step,iterate through the nodes in the globals graph, unioning

1471    // together theglobals into equivalence classes.

1472    fomGlobalIECs();

1473 

1474    // Iterate throughthe address taken functions in the globals graph,

1475    // collecting themin a list, to be used as target for call sites that

1476    // cant beresolved.

1477    formGlobalFunctionList();

1478    GlobalsGraph->maskIncompleteMarkers();

 

在DataStructures结构中GlobalFunctionList用于保存所有全局函数。这个数据将由后续的自底向上遍(BUDataStructures)使用。这些函数来自AddressTakenAnalysis的实例。

 

1322  void DataStructures::formGlobalFunctionList(){

1323    std::vector<constFunction*> List;

1324    DSScalarMap &SN =GlobalsGraph->getScalarMap();

1325    EquivalenceClasses<const GlobalValue*> &EC = GlobalsGraph->getGlobalECs();

1326    for(DSScalarMap::global_iterator I = SN.global_begin(), E = SN.global_end(); I !=E; ++I) {

1327      EquivalenceClasses<const GlobalValue*>::iterator ECI = EC.findValue(*I);

1328      if (ECI == EC.end()) {

1329        if (constFunction *F = dyn_cast<Function>(*I))

1330          List.push_back(F);

1331      } else {

1332        for(EquivalenceClasses<constGlobalValue*>::member_iterator MI =

1333             EC.member_begin(ECI), ME =EC.member_end(); MI != ME; ++MI){

1334          if (constFunction *F = dyn_cast<Function>(*MI))

1335            List.push_back(F);

1336        }

1337      }

1338    }

1339    GlobalFunctionList.swap(List);

1340  }

 

1326行的迭代器访问所有全局对象所引用的全局对象,而1325行返回全局图所包含的同类集。因为,前面执行buildGlobalECs时DSScalarMap中只包含同类集中的Leader成员,为了确保不遗漏其他同类集成员,在1332行的循环遍历指定的同类集中的Function对象。

1.3.3.4.1. 构建函数的DSGraph

除了全局对象,每个函数定义也要伴随一个DSGraph。1481行开始的循环,为每个函数定义创建一个DSGraph。

 

LocalDataStructures::runOnModule(续)

 

1480    // Calculate all ofthe graphs...

1481    for(Module::iterator I = M.begin(), E = M.end(); I != E; ++I)

1482      if (!I->isDeclaration()) {

1483        DSGraph* G = new DSGraph(GlobalECs, getDataLayout(), *TypeSS,GlobalsGraph);

1484        GraphBuilder GGB(*I, *G, *this);

1485        G->getAuxFunctionCalls() =G->getFunctionCalls();

1486        setDSGraph(*I, G);

1487        propagateUnknownFlag(G);

1488        callgraph.insureEntry(I);

1489        G->buildCallGraph(callgraph,GlobalFunctionList, true);

1490        G->maskIncompleteMarkers();

1491        G->markIncompleteNodes(DSGraph::MarkFormalArgs

1492                              |DSGraph::IgnoreGlobals);

1493        cloneIntoGlobals(G,DSGraph::DontCloneCallNodes |

1494                         DSGraph::DontCloneAuxCallNodes|

1495                        DSGraph::StripAllocaBit);

1496        formGlobalECs();

1497        DEBUG(G->AssertGraphOK());

1498      }

 

首先通过下面的函数构造每个函数定义专用的GraphBuilder。

 

148        GraphBuilder(Function&f, DSGraph &g, LocalDataStructures& DSi)

149          : G(g), FB(&f), DS(&DSi),TD(g.getDataLayout()), VAArray(0) {

150          // Createscalar nodes for all pointer arguments...

151          for(Function::arg_iterator I = f.arg_begin(), E = f.arg_end();

152               I != E; ++I) {

153            if(isa<PointerType>(I->getType())) {

154              // WD: Whydo we set the external marker so early in the analysis?

155              //Functions we have definitions for, but are externally reachable have no external

156              // contextsthat we'd want to BU external information into (since those contexts are

157              // bydefinition ones we don't have code for). Shouldn't this just be set in TD?

158    #if 0

159              DSNode * Node = getValueDest(I).getNode();

160   

161              if (!f.hasInternalLinkage() ||!f.hasPrivateLinkage())

162                Node->setExternalMarker();

163    #else

164              getValueDest(I).getNode();

165    #endif

166   

167            }

168          }

169   

170          // Create anentry for the return, which tracks which functions are in

171          // the graph

172          g.getOrCreateReturnNodeFor(f);

173   

174          // Create anode to handle information about variable arguments

175          g.getOrCreateVANodeFor(f);

176   

177          visit(f);  // Single pass overthe function

 

DSGraph的成员ReturnNodes的类型是std::map<constFunction*, DSNodeHandle>,它用于保存当前函数的返回值对象,使用std::map是因为一个图可能代表多个函数(在后续的BU及TDD处理中可以看到有调用及被调用关系的函数图会被合并起来);成员VANodes的类型是std::map<const Function*,DSNodeHandle> ,它用于保存当前函数的可变长实参对象,使用std::map也是因为一个图可能代表多个函数。在第一次访问它们时,会创建缺省的DSNodeHandle。

 

118      RetTy visit(Instruction&I) {

119        switch(I.getOpcode()) {

120        default:llvm_unreachable("Unknown instruction type encountered!");

121          // Build theswitch statement using the Instruction.def file...

122    #define HANDLE_INST(NUM, OPCODE,CLASS) \

123        caseInstruction::OPCODE: return \

124               static_cast<SubClass*>(this)->\

125                          visit##OPCODE(static_cast<CLASS&>(I));

126    #include"llvm/IR/Instruction.def"

127        }

128      }

 

GraphBuilder的基类是InstVisitor<GraphBuilder>,InstVisitor是一个模板类,它用作指令访问者(instruction visitor)的基类。在上面124行,SubClass就是传给InstVisitor的模板实参GraphBuilder,而文件llvm/IR/Instruction.def则是根据特定的宏是否有定义,对指定类别的指令(比如内存指令,转换指令等,注意这些指令与目标机器无关,是llvm IR指令),在122行进行展开。InstVisitor已对所有的指令类别定义了visit*方法,不过这些方法都不做任何事。InstVisitor在这些visit*方法中有特别的处理,使派生类只要重载特定的方法即可,比如:

 

166    RetTyvisitReturnInst(ReturnInst &I)           { DELEGATE(TerminatorInst);}

 

30      #define DELEGATE(CLASS_TO_VISIT) \

31        return static_cast<SubClass*>(this)-> \

32                     visit##CLASS_TO_VISIT(static_cast<CLASS_TO_VISIT&>(I))

 

InstVisitor把ReturnInst,BranchInst,SwitchInst,IndirectBrInst,ResumeInst及UnreachableInst归类为TerminatorInst,派生类可只重载visitTerminatorInst来涵盖对这些指令的处理,也可以重载部分visit*方法,把余下的给visitTerminatorInst来涵盖。这极大地增加看派生类的灵活性。其他类型的指令也有类似的关系,此处省略。

GraphBuilder重载了如下的方法:

1.3.3.4.1.1. 对指令节点的处理

1.3.3.4.1.1.1. 对Φ节点的处理

Φ节点是Chris在论文中未考虑到的。Φ节点的出现在于llvmIR是SSA形式的,Φ节点是同一个变量不同版本的值的汇聚点。对于与Φ节点关联的非指针对象,Φ节点只是给出了取值的几个可能性,对象的地址不会变。不过对于指针对象,就不一样了,指针将指向几个可能的地址,这是visitPHINode要考虑的。

 

365    void GraphBuilder::visitPHINode(PHINode&PN) {

366      if (!isa<PointerType>(PN.getType())) return; // Only pointerPHIs

367   

368      DSNodeHandle &PNDest = G.getNodeForValue(&PN);

369      for(unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)

370        PNDest.mergeWith(getValueDest(PN.getIncomingValue(i)));

371    }

 

这个处理也很简单,对于与Φ节点关联的指针对象,把进入Φ节点的对象的DSNode(通过DSNodeHandle)简并,来表示指针可能引用这些对象。

1.3.3.4.1.1.2. 对select指令的处理

LlvmIR的select指令有点像表达式res = cond? val1: val2,只有在val1和val2的类型是指针时,才需要下面的处理,因为此时这两个指针及接受结果的指针(res)可能互为别名(may aliase)。

 

373    void GraphBuilder::visitSelectInst(SelectInst&SI) {

374      if (!isa<PointerType>(SI.getType()))

375        return; // Only pointer Selects

376   

377      DSNodeHandle &Dest = G. getNodeForValue(&SI);

378      DSNodeHandle S1 = getValueDest(SI.getOperand(1));

379      DSNodeHandle S2 =getValueDest(SI.getOperand(2));

380      Dest.mergeWith(S1);

381      Dest.mergeWith(S2);

382    }

 

显然,处理的方法是简并这3个指针的DSNode节点,用一个DSNode节点来代替它们。

1.3.3.4.1.1.3. 对load指令的处理

在llvm中任何内存访问都必须通过与该访问的地址段关联的指针来完成,因此,load指令的源(即第一个操作数)必须是一个指针。390行的getPointerOperand实际上就是返回第一个操作数。

 

384    void GraphBuilder::visitLoadInst(LoadInst&LI) {

385      //

386      // Create a DSNodefor the pointer dereferenced by the load. If the DSNode

387      // is NULL, donothing more (this can occur if the load is loading from a

388      // NULL pointerconstant (bugpoint can generate such code).

389      //

390      DSNodeHandle Ptr = getValueDest(LI.getPointerOperand());

391      if (Ptr.isNull()) return;// Load from null

392   

393      // Make that thenode is read from...

394      Ptr.getNode()->setReadMarker();

395   

396      // Ensure atyperecord exists...

397      Ptr.getNode()->growSizeForType(LI.getType(),Ptr.getOffset());

398   

399      if (isa<PointerType>(LI.getType()))

400        setDestTo(LI,getLink(Ptr));

401   

402      // check that it isthe inserted value

403      if(TypeInferenceOptimize)

404        if(LI.hasOneUse())

405          if(StoreInst *SI =dyn_cast<StoreInst>(*(LI.use_begin())))

406            if(SI->getOperand(0) == &LI) {

407            ++NumIgnoredInst;

408            return;

409          }

410      Ptr.getNode()->mergeTypeInfo(LI.getType(), Ptr.getOffset());

411    }

 

如果load指令的目标也是指针类型,这意味着目标与源指向同一个对象,通过400行完成DSNodeHandle形式的表示(setDestTo会进行节点简并)。在410行对目标与源的类型信息进行整合,注意整合的信息保存在源节点中。

1.3.3.4.1.1.4. 对store指令的处理

类似的,llvm中store指令的目标必须是指针类型。因为操作数是从0开始计数的,所以415行获取的是第二个操作数,它是store指令的目标。

 

413    void GraphBuilder::visitStoreInst(StoreInst&SI) {

414      Type *StoredTy =SI.getOperand(0)->getType();

415      DSNodeHandle Dest = getValueDest(SI.getOperand(1));

416      if (Dest.isNull()) return;

417   

418      // Mark that thenode is written to...

419      Dest.getNode()->setModifiedMarker();

420   

421      // Ensure atype-record exists...

422      Dest.getNode()->growSizeForType(StoredTy,Dest.getOffset());

423   

424      // Avoid adding edgesfrom null, or processing non-"pointer" stores

425      if (isa<PointerType>(StoredTy))

426        Dest.addEdgeTo(getValueDest(SI.getOperand(0)));

427   

428      if(TypeInferenceOptimize)

429        if(SI.getOperand(0)->hasOneUse())

430         if(isa<LoadInst>(SI.getOperand(0))){

431            ++NumIgnoredInst;

432            return;

433          }

434      Dest.getNode()->mergeTypeInfo(StoredTy, Dest.getOffset());

435    }

 

426行的addEdgeTo把指向Dest偏移0处的DSNode节点与源操作数的DSNode节点简并。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值