dsa算法(20)

1.3.7. StdLib遍

StdLib遍识别通用的C标准库,并为之产生图。它的处理类StdLibDataStructures派生自DataStructures。

 

546    bool

547    StdLibDataStructures::runOnModule (Module &M) {

548      //

549      // Get theresults from the local pass.

550      //

551      init (&getAnalysis<LocalDataStructures>(), true,true, false, false);

552      AllocWrappersAnalysis = &getAnalysis<AllocIdentify>();

553   

1.3.7.1. 初始化全局图

上面551行的init函数在DataStructures中定义,通过getAnalysis获取了前面对程序进行局部分析的LocalDataStructures对象

 

1477  void DataStructures::init(DataStructures* D, boolclone, bool useAuxCalls,

1478                            boolcopyGlobalAuxCalls, bool resetAux) {

1479    assert(!GraphSource && "Already init");

1480    GraphSource = D;

1481    Clone = clone;

1482    resetAuxCalls = resetAux;

1483    TD = D->TD;

1484    TypeSS = D->TypeSS;

1485    callgraph = D->callgraph;

1486    GlobalFunctionList =D->GlobalFunctionList;

1487    GlobalECs = D->getGlobalECs();

1488    GlobalsGraph = newDSGraph(D->getGlobalsGraph(), GlobalECs,*TypeSS,

1489                              copyGlobalAuxCalls? DSGraph::CloneAuxCallNodes

1490                               :DSGraph::DontCloneAuxCallNodes);

1491    if (useAuxCalls)GlobalsGraph->setUseAuxCalls();

1492 

1493    //

1494    // Tell the otherDSA pass if we're stealing its graph.

1495    //

1496    if (!clone) D->DSGraphsStolen = true;

1497  }

 

1480~1487行初始化DataStructures中的几个重要的成员,并在1488行构建自己的全局图。DSGraph构造函数中的CloneFlags参数在这里是DSGraph::DontCloneAuxCallNodes,不拷贝经过前面遍处理的函数结果。

 

110    DSGraph::DSGraph(DSGraph* G,EquivalenceClasses<const GlobalValue*>&ECs,

111                     SuperSet<Type*>&tss,

112                     unsigned CloneFlags)

113      : GlobalsGraph(0), ScalarMap(ECs),TD(G->TD), TypeSS(tss) {

114      UseAuxCalls = false;

115      cloneInto(G,CloneFlags);

116    }

 

DSGraph中的GlobalsGraph用于指向全局图,对于全局图,这个指针是NULL。接着在115行cloneInto把G图克隆进当前(空)图。在下面cloneInto定义的191行的NodeMapTy是std::map<const DSNode*, DSNodeHandle>的typedef。在204行赋值操作符右边会调用一次DSNodeHandle的构造函数,因此旧的DSNode与指向拷贝的DSNode的DSNodeHandle映射在一起。

 

188    void DSGraph::cloneInto(DSGraph* G, unsigned CloneFlags) {

189      assert(G !=this && "Cannot clone graph into itself!");

190   

191      NodeMapTy OldNodeMap;

192   

193      // Remove allocaor mod/ref bits as specified...

194      unsigned BitsToClear = ((CloneFlags &StripAllocaBit)? DSNode::AllocaNode : 0)

195        | ((CloneFlags & StripModRefBits)?(DSNode::ModifiedNode | DSNode::ReadNode) : 0)

196        | ((CloneFlags & StripIncompleteBit)?DSNode::IncompleteNode : 0);

197      BitsToClear |= DSNode::DeadNode;  // Clear deadflag...

198   

199      for(node_const_iterator I = G->node_begin(), E = G->node_end(); I != E; ++I){

200        assert(!I->isForwarding()&&

201               "Forward nodes shouldn't be innode list!");

202        DSNode *New = newDSNode(*I, this);

203        New->maskNodeTypes(~BitsToClear);

204        OldNodeMap[I] = New;

205      }

206   

207      // Rewrite thelinks in the new nodes to point into the current graph now.

208      // Note that wedon't loop over the node's list to do this. The problem is

209      // that remapinglinks can cause recursive merging to happen, which means

210      // thatnode_iterator's can get easily invalidated! Because of this, we

211      // loop over theOldNodeMap, which contains all of the new nodes as the

212      // .secondelement of the map elements.  Also notethat if we remap a node

213      // more thanonce, we won't break anything.

214      for(NodeMapTy::iterator I = OldNodeMap.begin(), E = OldNodeMap.end();

215           I != E; ++I)

216        I->second.getNode()->remapLinks(OldNodeMap);

 

199行的循环遍历并拷贝源图所有的DSNode,由于OldNodeMap的类型限定,204行在OldNodeMap中产生一个指向New的DSNodeHandle节点并与I援引的DSNode绑定。214行的循环遍历拷贝的DSNode节点(216行的getNode得到的是在202行产生的DSNode节点)。

 

1151  void DSNode::remapLinks(DSGraph::NodeMapTy&OldNodeMap) {

1152    for(LinkMapTy::iterator ii = edge_begin(), ee = edge_end();

1153         ii != ee; ++ii)

1154      if (DSNode *N = ii->second.getNode()) {

1155        DSGraph::NodeMapTy::const_iterator ONMI =OldNodeMap.find(N);

1156        if (ONMI != OldNodeMap.end()) {

1157          DSNode *ONMIN = ONMI->second.getNode();

1158          ii->second.setTo(ONMIN,ii->second.getOffset()+ONMI->second.getOffset());

1159        }

1160      }

1161  }

 

202行的拷贝包括了源节点的Links的内容,1152行的循环遍历这个Links,我们知道Links的类型是std::map<unsigned,DSNodeHandle>,作用是记录DSNode给定偏移处所指向的DSNode,因此remapLinks的作用是把Links中DSNodeHandle部分更新为指向拷贝后的DSNode节点。注意在1158行,ONMI->second.getOffset()实际上是0,它是cloneInto的202行产生的。

下面DSGraph的ScalarMap记录在一个函数中所引用的所有对象。它的ValueMap域专门记录该图引用的所有对象及其关联的DSNodeHandler,GlobalSet则记录引用的全局对象。

 

DSGraph::cloneInto(续)

 

218      // Copy thescalar map... merging all of the global nodes...

219      for(DSScalarMap::const_iterator I = G->ScalarMap.begin(),

220             E = G->ScalarMap.end(); I != E;++I) {

221        DSNodeHandle &MappedNode =OldNodeMap[I->second.getNode()];

222        DSNodeHandle &H = ScalarMap.getRawEntryRef(I->first);

223        DSNode *MappedNodeN = MappedNode.getNode();

224        H.mergeWith(DSNodeHandle(MappedNodeN,

225                                I->second.getOffset()+MappedNode.getOffset()));

226      }

 

219行是遍历源图的ValueMap,222行getRawEntryRef把V加入ValueMap与GlobalSet。它与operator[]的区别在于,如果V是GlobalValue,它不会使用V的同类集Leader来代替V。

 

103      DSNodeHandle &getRawEntryRef(constValue *V) {

104        std::pair<iterator,bool> IP =

105          ValueMap.insert(std::make_pair(V, DSNodeHandle()));

106         if (IP.second)   // Inserted thenew entry into the map.

107           if (constGlobalValue *GV = dyn_cast<GlobalValue>(V))

108             GlobalSet.insert(GV);

109         returnIP.first->second;

110      }

 

由于在105行我们产生的是一个空白的DSNodeHandle,在222行我们拿到这个节点的引用,通过224行的merge,这个DSNodeHandle指向了MappedNodeN。这样源图中ValueMap的内容就拷贝到了目标图。

 

DSGraph::cloneInto(续)

 

228      if (!(CloneFlags & DontCloneCallNodes)) {

229        // Copy thefunction calls list.

230        for(fc_iterator I = G->fc_begin(), E = G->fc_end(); I != E; ++I)

231          FunctionCalls.push_back(DSCallSite(*I, OldNodeMap));

232      }

233   

234      if (!(CloneFlags &DontCloneAuxCallNodes)) {

235        // Copy theauxiliary function calls list.

236        for(afc_iterator I = G->afc_begin(), E = G->afc_end(); I != E; ++I)

237          AuxFunctionCalls.push_back(DSCallSite(*I,OldNodeMap));

238      }

 

230行的fc_begin是图中对应函数调用的DSCallSite的迭代器,FunctionCalls是DSCallSite的std::list容器。在231行调用下面的构造函数。

 

221      template<typename MapTy>

222      DSCallSite(const DSCallSite &FromCall, MapTy &NodeMap) {

223        Site = FromCall.Site;

224        InitNH(RetVal,FromCall.RetVal, NodeMap);

225        InitNH(CalleeN, FromCall.CalleeN, NodeMap);

226        InitNH(VarArgVal, FromCall.VarArgVal,NodeMap);

227        CalleeF = FromCall.CalleeF;

228   

229        CallArgs.resize(FromCall.CallArgs.size());

230        for (unsigned i = 0, e = FromCall.CallArgs.size(); i!= e; ++i)

231          InitNH(CallArgs[i], FromCall.CallArgs[i],NodeMap);

232        MappedSites = FromCall.MappedSites;

233      }

 

InitNH的作用是从NodeMap中找到Src节点的拷贝,并使相应的DSNodeHandle指向它。同样在186行的I->second.getOffset()实际上是0。

 

179      static void InitNH(DSNodeHandle&NH, const DSNodeHandle &Src,

180                         conststd::map<const DSNode*, DSNodeHandle>&NodeMap) {

181        if (DSNode *N = Src.getNode()) {

182          std::map<constDSNode*, DSNodeHandle>::const_iterator I = NodeMap.find(N);

183          assert(I!= NodeMap.end() && "Node not in mapping!");

184   

185          DSNode *NN = I->second.getNode(); // Call getNode before getOffset()

186          NH.setTo(NN,Src.getOffset()+I->second.getOffset());

187        }

188      }

 

下面241行的retnodes_end是ReturnNodes的迭代器,ReturnNodes保存该图所代表的所有函数与返回值,它类型是std::map<const Function*, DSNodeHandle>(后面会看到,BU及TD遍能使一个函数图对应多个函数)。

 

DSGraph::cloneInto(续)

 

240      // Map the returnnode pointers over...

241      for(retnodes_iterator I = G->retnodes_begin(),

242             E = G->retnodes_end(); I != E; ++I){

243        constDSNodeHandle &Ret = I->second;

244        DSNodeHandle &MappedRet =OldNodeMap[Ret.getNode()];

245        DSNode *MappedRetN = MappedRet.getNode();

246        ReturnNodes.insert(std::make_pair(I->first,

247                                         DSNodeHandle(MappedRetN,

248                                        MappedRet.getOffset()+Ret.getOffset())));

249      }

250   

251      // Map the VAnode pointers over...

252      for(vanodes_iterator I = G->vanodes_begin(),

253             E = G->vanodes_end(); I != E; ++I){

254        constDSNodeHandle &VarArg = I->second;

255        DSNodeHandle &MappedVarArg =OldNodeMap[VarArg.getNode()];

256        DSNode *MappedVarArgN =MappedVarArg.getNode();

257        VANodes.insert(std::make_pair(I->first,

258                       DSNodeHandle(MappedVarArgN,

259                                   MappedVarArg.getOffset()+VarArg.getOffset())));

260      }

261    }

 

类似的,252行的vanodes_begin是VANodes的迭代器,VANodes保存了每个函数的可变参数,它类型也是std::map<const Function*, DSNodeHandle>。

接着,在DataStructures::init的1491行,UseAuxCalls被设置为true。

1.3.7.2. 初始化函数图

在创建(拷贝)了全局图后,进而拷贝函数图。

 

StdLibDataStructures::runOnModule(续)

 

555      // Fetch theDSGraphs for all defined functions within the module.

556      //

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

558        if (!I->isDeclaration())

559          getOrCreateGraph(&*I);

 

程序中的每个函数定义都要创建一个函数图。getOrCreateGraph定义的1294行的DSInfo就是函数图保存的地方,它的类型是std::map<const Function*,DSGraph*>,因此,1294行获取与F定义相关的函数图G。

 

1292  DSGraph* DataStructures::getOrCreateGraph(const Function* F) {

1293    assert(F&& "No function");

1294    DSGraph *&G = DSInfo[F];

1295    if (!G) {

1296      assert(F->isDeclaration() || GraphSource->hasDSGraph(*F));

1297      //Clone or Stealthe Source Graph

1298      DSGraph* BaseGraph =GraphSource->getDSGraph(*F);

1299      if (Clone) {

1300        G = new DSGraph(BaseGraph, GlobalECs, *TypeSS);

1301        if (resetAuxCalls)

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

1303      } else {

1304        G = newDSGraph(GlobalECs, GraphSource->getDataLayout(), *TypeSS);

1305        G->spliceFrom(BaseGraph);

1306        if (resetAuxCalls)

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

1308      }

1309      G->setUseAuxCalls();

1310      G->setGlobalsGraph(GlobalsGraph);

1311 

1312      // Note that thisgraph is the graph for ALL of the function in the SCC, not

1313      // just F.

1314      for(DSGraph::retnodes_iterator RI = G->retnodes_begin(),

1315           E = G->retnodes_end(); RI != E;++RI)

1316        if (RI->first != F)

1317          DSInfo[RI->first] = G;

1318    }

1319    return G;

1320  }

 

在这里1299行的Clone是true,不存在的函数图在1300行通过下面的构造函数来构建,1301行的resetAuxCalls是false,而构造函数中的参数CloneFlags是缺省值0。

 

110    DSGraph::DSGraph(DSGraph* G,EquivalenceClasses<const GlobalValue*>&ECs,

111                     SuperSet<Type*>&tss,

112                     unsigned CloneFlags)

113      : GlobalsGraph(0), ScalarMap(ECs),TD(G->TD), TypeSS(tss) {

114      UseAuxCalls = false;

115      cloneInto(G,CloneFlags);

116    }

 

这个图的UseAuxCalls在1309行被设置为true,在1310行其GlobalsGraph指向全局图。在1314行,因为该图代表的函数可能不止一个,也需要绑定这些函数。

1.3.7.3. 删除不起作用的函数

在复制了全局图与所有的函数图后,从中我们要去掉对只读且不返回指针的函数的直接调用(566行条件是找出这样的函数,它们对这里的处理不起作用),以及对没有可变参数、不返回指针、不接受指针参数的外部函数的直接调用(575及581行条件是找出这样的函数,它们也不影响这里的处理)。

 

StdLibDataStructures::runOnModule(续)

 

562      // Erase directcalls to functions that don't return a pointer and are marked

563      // with thereadnone annotation.

564      //

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

566        if (I->isDeclaration() &&I->doesNotAccessMemory() &&

567            !isa<PointerType>(I->getReturnType()))

568          eraseCallsTo(I);

569   

570      //

571      // Erase directcalls to external functions that are not varargs, do not

572      // return apointer, and do not take pointers.

573      //

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

575        if (I->isDeclaration() &&!I->isVarArg() &&

576           !isa<PointerType>(I->getReturnType())) {

577          bool hasPtr = false;

578          for(Function::arg_iterator ii = I->arg_begin(), ee = I->arg_end();

579               ii != ee;

580               ++ii)

581            if(isa<PointerType>(ii->getType())) {

582              hasPtr = true;

583              break;

584            }

585          if (!hasPtr)

586            eraseCallsTo(I);

587        }

 

eraseCallsTo查找指定函数的调用者,从中把CallInst及InvokeInst删除。注意458、466与478行,CallInst及InvokeInst都是Instruction的派生类,第一个getParent返回其所在的基本块,第二个getParent返回其所在的函数(Function)对象。

 

450    void

451    StdLibDataStructures::eraseCallsTo(Function* F) {

452      typedefstd::pair<DSGraph*,Function*> RemovalPair;

453      DenseSet<RemovalPair> ToRemove;

454      for(Value::use_iterator ii = F->use_begin(), ee = F->use_end();

455           ii != ee; ++ii)

456        if (CallInst* CI = dyn_cast<CallInst>(*ii)){

457          if (CI->getCalledValue() == F) {

458            DSGraph* Graph =getDSGraph(*CI->getParent()->getParent());

459            //deletethe call

460            DEBUG(errs() << "Removing" << F->getName().str() << " from "

461                  << CI->getParent()->getParent()->getName().str()<< "\n");

462            ToRemove.insert(std::make_pair(Graph,F));

463          }

464        }else if (InvokeInst* CI =dyn_cast<InvokeInst>(*ii)){

465          if (CI->getCalledValue() == F) {

466            DSGraph* Graph = getDSGraph(*CI->getParent()->getParent());

467            //deletethe call

468            DEBUG(errs() << "Removing" << F->getName().str() << " from "

469                  <<CI->getParent()->getParent()->getName().str() <<"\n");

470            ToRemove.insert(std::make_pair(Graph,F));

471          }

472        } else if(ConstantExpr *CE =dyn_cast<ConstantExpr>(*ii)) {

473          if(CE->isCast()) {

474            for(Value::use_iterator ci = CE->use_begin(), ce = CE->use_end();

475                 ci != ce; ++ci) {

476              if (CallInst* CI =dyn_cast<CallInst>(*ci)){

477                if(CI->getCalledValue() == CE) {

478                  DSGraph* Graph =getDSGraph(*CI->getParent()->getParent());

479                  //deletethe call

480                  DEBUG(errs() <<"Removing " << F->getName().str() << " from"

481                        <<CI->getParent()->getParent()->getName().str() <<"\n");

482                 ToRemove.insert(std::make_pair(Graph, F));

483                }

484              }

485            }

486          }

487        }

488   

489      for(DenseSet<RemovalPair>::iteratorI = ToRemove.begin(), E = ToRemove.end();

490          I != E; ++I)

491        I->first->removeFunctionCalls(*I->second);

492    }

 

在DSGraph对象里,在当前函数中出现的所有函数调用指令都保存在FunctionCalls与AuxFunctionCalls中,因此从两者中删除调用指令即可。140与150行确定这是直接调用。

 

136    void DSGraph::removeFunctionCalls(Function&F) {

137      FunctionListTy::iterator Erase =FunctionCalls.end();

138      for(FunctionListTy::iterator I = FunctionCalls.begin();

139           I != Erase; ) {

140        if (I->isDirectCall() &&I->getCalleeFunc() == &F)

141          std::swap(*I, *--Erase);

142        else

143          ++I;

144      }

145      FunctionCalls.erase(Erase,FunctionCalls.end());

146   

147      Erase = AuxFunctionCalls.end();

148      for(FunctionListTy::iterator I = AuxFunctionCalls.begin();

149           I != Erase; ) {

150        if (I->isDirectCall() &&I->getCalleeFunc() == &F)

151          std::swap(*I, *--Erase);

152        else

153          ++I;

154      }

155      AuxFunctionCalls.erase(Erase,AuxFunctionCalls.end());

156    }

你可能感兴趣的:(算法,DSA,compiler,编译器,llvm)