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
上面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。
在创建(拷贝)了全局图后,进而拷贝函数图。
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行,因为该图代表的函数可能不止一个,也需要绑定这些函数。
在复制了全局图与所有的函数图后,从中我们要去掉对只读且不返回指针的函数的直接调用(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 }