您的位置:首页 > 其它

dsa算法(27完)

2015-07-24 11:56 253 查看

1.3.11. TDDataStructures与EQTDDataStructures遍

自顶向下阶段非常类似于自底向上阶段。BU阶段已经识别了调用图,因此TD阶段可以使用Tarjan的算法直接遍历调用图的SCC。它不需要像BU阶段那样“重新访问”SCC。注意到在BU阶段可能仅部分访问某些SCC,因此TD阶段负责简并这些图。

总体来说,TD阶段仅在4方面与BU阶段不同:首先,TD阶段不会把一个SCC标记为未访问:它使用由BU阶段发现并记录的调用边。其次,TD阶段以逆后序,而不是后序,访问由BU遍历得到的调用图的SCC。第三,TD遍把每个函数图内联入其调用的函数(而不是相反),并且它是直接把一个调用者的图内联入其所有的潜在的被调用者(不需要“延迟”这个内联操作,因为每个调用点的潜在被调用者是已知的)。最后的差别是,如果一个函数的所有调用者已经被分析识别出来,就把形参节点标记为完整。比如,任何外部函数不能访问的函数。类似的,全局变量可能被标记为完整,除非它们可以被外部函数访问。一个函数或全局对象是外部可见的,如果它没有内部链接性(比如,没有标记为static的C对象),或者在main的图中,该全局对象存在一个没有标记为完整的节点。

1.3.11.1. 确定外部可访问的函数

TDDataStructures作为独立的遍运行时,77行的useEQBU被设置为false,这时它只依赖于BUDataStructures的结果。但当运行EQTDDataStructures遍时,useEQBU被设置为true,则TDDataStructures依赖于EquivBUDataStructures的结果。注意在对init的调用中,倒数第2个参数是true(copyGlobalAuxCalls),在拷贝DSGraph时,还将拷贝AuxFunctionCalls的内容(它现在保存了还未解析的函数调用)。

75 bool
TDDataStructures::runOnModule(Module&M) {

76

77
init(useEQBU? &getAnalysis<EquivBUDataStructures>()

78 : &getAnalysis<BUDataStructures>(),

79 true, true, true, false);

80
// Figure outwhich functions must not mark their arguments complete because

81
// they areaccessible outside this compilation unit. Currently, these

82
// arguments arefunctions which are reachable by incomplete or external

83
// nodes in theglobals graph.

84
constDSScalarMap &GGSM = GlobalsGraph->getScalarMap();

85 DenseSet<DSNode*> Visited;

86
for(DSScalarMap::global_iterator I=GGSM.global_begin(), E=GGSM.global_end();

87 I != E; ++I) {

88 DSNode *N =GGSM.find(*I)->second.getNode();

89 if (N->isIncompleteNode() ||N->isExternalNode())

90
markReachableFunctionsExternallyAccessible(N,Visited);

91 }

92

93
// Loop overunresolved call nodes. Any functionspassed into (but not

94
// returned!) fromunresolvable call nodes may be invoked outside of the

95
// currentmodule.

96
for(DSGraph::afc_iterator I = GlobalsGraph->afc_begin(),

97 E = GlobalsGraph->afc_end(); I !=E; ++I)

98
for(unsigned arg = 0, e = I->getNumPtrArgs(); arg != e; ++arg)

99
markReachableFunctionsExternallyAccessible(I->getPtrArg(arg).getNode(),

100 Visited);

101 Visited.clear();

DSGraph中的ScalarMap保存了该函数所援引的对象,而其中的GlobalSet只保存全局对象,而ValMap则保存所有对象(实际上是Value与DSNodeHandle的对)。上面86行的循环就是遍历全局图的GlobalSet,88行的find则返回DSNodeHandle指向的ValMap中的DSNode——对象在函数图里的节点。如果这个节点是不完整或是外部的,则调用下面的函数。而96行的循环则是遍历AuxFunctionCalls,并对每个指针参数调用同样的函数。

51 void
TDDataStructures::markReachableFunctionsExternallyAccessible(DSNode*N,

52 DenseSet<DSNode*> &Visited) {

53 if (!N || Visited.count(N))
return;

54 Visited.insert(N);

55

56
// Handle thisnode

57 {

58 N->addFullFunctionSet(ExternallyCallable);

59 }

60

61
for(DSNode::edge_iterator ii = N->edge_begin(),

62 ee = N->edge_end(); ii != ee;++ii)

63 if (!ii->second.isNull()) {

64 DSNodeHandle &NH = ii->second;

65 DSNode * NN = NH.getNode();

66 NN->addFullFunctionSet(ExternallyCallable);

67
markReachableFunctionsExternallyAccessible(NN,Visited);

68 }

69 }

这里ExternallyCallable记录的是外部可调用函数。在DSA的设计中,从不完整或外部节点可访问的函数都被视为外部可访问的。另外,作为参数传递给未解析的函数的函数也可能是外部可访问的。除此之外,定义在当前编译单元中的函数,如果不是定义为内部或私有,也是外部可访问的。

TDDataStructures::runOnModule(续)

103
// Clear Aux ofGlobals Graph to be refilled in later by post-TD unresolved

104
// functions

105 GlobalsGraph->getAuxFunctionCalls().clear();

106

107
// Functionswithout internal linkage are definitely externally callable!

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

109 if (!I->isDeclaration() &&!I->hasInternalLinkage() && !I->hasPrivateLinkage())

110 ExternallyCallable.insert(I);

111

112
// Debug code toprint the functions that are externally callable

113 #if 0

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

115 if (ExternallyCallable.count(I)) {

116 errs() << "ExternallyCallable:" << I->getNameStr() << "\n";

117 }

118 #endif

1.3.11.2. 确定调用函数的后序遍历序

接下来,ComputePostOrder计算指定函数中函数调用的后序遍历次序,以这个次序在PostOrder中保存函数的DSGraph。

TDDataStructures::runOnModule(续)

120
// We want totraverse the call graph in reverse post-order. To do this, we

121
// calculate apost-order traversal, then reverse it.

122 DenseSet<DSGraph*> VisitedGraph;

123 std::vector<DSGraph*> PostOrder;

124

125 {TIME_REGION(XXX, "td:Computepostorder");

126

127
// Calculatetop-down from main...

128 if (Function *F =M.getFunction("main"))

129
ComputePostOrder(*F,VisitedGraph, PostOrder);

130

131
// Next calculatethe graphs for each unreachable function...

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

133 if (!I->isDeclaration())

134
ComputePostOrder(*I,VisitedGraph, PostOrder);

135

136 VisitedGraph.clear();
// Releasememory!

137 }

ComputePostOrder对函数的处理次序依然是先main,后其他函数。同样对于直接调用函数,直接进行递归。

187 void
TDDataStructures::ComputePostOrder(const Function &F,

188 DenseSet<DSGraph*> &Visited,

189 std::vector<DSGraph*> &PostOrder) {

190 if (F.isDeclaration())
return;

191 DSGraph* G = getOrCreateGraph(&F);

192 if (!Visited.insert(G).second)
return;

193

194
// Recursivelytraverse all of the callee graphs.

195 svset<constFunction*> Callees;

196

197
// Go through allof the callsites in this graph and find all callees

198
// Here we'retrying to capture all possible callees so that we can ensure

199
// each functionhas all possible callers inlined into it.

200
for(DSGraph::fc_iterator CI = G->fc_begin(), E = G->fc_end();

201 CI != E; ++CI) {

202
// Direct callsare easy, no reason to look at DSCallGraph

203
// or anythingto do with SCC's

204 if (CI->isDirectCall()) {

205 ComputePostOrder(*CI->getCalleeFunc(),Visited, PostOrder);

206 }

207 else {

208
// Otherwise,ask the DSCallGraph for the full set of possible

209
// calleesfor this callsite.

210
// Thisincludes all members of the SCC's of those callees,

211
// and wellas others in F's SCC, since we must assume

212
// anyindirect call might be intra-SCC.

213 callgraph.addFullFunctionSet(CI->getCallSite(),Callees);

214 }

215 }

216

217
for(svset<const Function*>::iterator I =Callees.begin(),

218 E = Callees.end(); I != E; ++I)

219 ComputePostOrder(**I, Visited, PostOrder);

220

221 PostOrder.push_back(G);

222 }

对于间接调用的函数,通过addFullFunctionSet收集候选函数。下面265行遍历callgraph的ActualCallees容器中与指定CallSite关联的函数(Function)。对于某一特定的函数,如果它属于某个调用链SCC,把这个SCC的所有成员加入Set(如果它不属于某个SCC,267行的scc_begin会返回与scc_end相同的迭代器)。对于该CallSite所在的函数(270行的F1),同样向Set加入其所在SCC的成员,如果存在这样的SCC。因为我们假定间接调用都可能是SCC的任何部分。

261 void
DSCallGraph::addFullFunctionSet(llvm::CallSiteCS,

262 svset<const llvm::Function*> &Set)
const {

263 DSCallGraph::callee_iterator csi =callee_begin(CS),

264 cse = callee_end(CS);

265
while(csi !=cse) {

266
constFunction *F = *csi;

267 Set.insert(scc_begin(F), scc_end(F));

268 ++csi;

269 }

270
constFunction *F1 = CS.getInstruction()->getParent()->getParent();

271 F1 = sccLeader(&*F1);

272 Set.insert(scc_begin(F1), scc_end(F1));

273 }

接着在TDDataStructures::ComputePostOrder的217行对这些收集到的间接被调用函数进行递归。221行就是后序遍历的标志。

1.3.11.3. 向被调用者内联调用者

现在在PostOrder中,调用链最底层的被调用函数出现在容器头部,最顶层的则出现在容器的底部,因此143行对InlineCallersIntoGraph的调用从最顶层的(被)调用函数开始。这样对调用图的访问就是逆后序的。

TDDataStructures::runOnModule(续)

139 {TIME_REGION(XXX,"td:Inline stuff");

140

141
// Visit each ofthe graphs in reverse post-order now!

142
while(!PostOrder.empty()) {

143
InlineCallersIntoGraph(PostOrder.back());

144 PostOrder.pop_back();

145 }

146 }

这个函数用到一个新的数据类型:CallerCallEdge。336~338行的注释已经解释了这个结构的作用。

335
struct CallerCallEdge {

336 DSGraph *CallerGraph;
// Thegraph of the caller function.

337
constDSCallSite *CS; // The actual call site.

338
constFunction *CalledFunction; // The actual function being called.

339

340 CallerCallEdge(DSGraph *G,
const DSCallSite *cs, constFunction *CF)

341 : CallerGraph(G), CS(cs),CalledFunction(CF) {}

342

343 bool
operator<(const CallerCallEdge &RHS)
const {

344
returnCallerGraph < RHS.CallerGraph ||

345 (CallerGraph == RHS.CallerGraph&& CS < RHS.CS);

346 }

347 };

下面231行的CallerEdges的定义是std::map<DSGraph*, std::vector<CallerCallEdge> >,它是TDDataStructures的成员。DSG如果在CallerEdges中有记录,这个记录是它的调用者添加的(参考函数的后半段),230~235行取出这个记录。使用CallerCallEdge定义的比较操作符,238行的sort以调用者图的地址排序相关的CallerCallEdge项(这样同一个调用函数用产生的CallerCallEdge项会集合在一起,便于循环处理)。

226 void
TDDataStructures::InlineCallersIntoGraph(DSGraph*DSG) {

227
// Inline callergraphs into this graph. First step, getthe list of call

228
// sites thatcall into this graph.

229 std::vector<CallerCallEdge>EdgesFromCaller;

230 std::map<DSGraph*,std::vector<CallerCallEdge> >::iterator

231 CEI = CallerEdges.find(DSG);

232 if (CEI != CallerEdges.end()) {

233 std::swap(CEI->second, EdgesFromCaller);

234 CallerEdges.erase(CEI);

235 }

236

237
// Sort thecaller sites to provide a by-caller-graph ordering.

238 std::sort(EdgesFromCaller.begin(),EdgesFromCaller.end());

239

240

241
// Mergeinformation from the globals graph into this graph. FIXME: This is

242
// stupid. Instead of us cloning information from the GGinto this graph,

243
// then havingRemoveDeadNodes clone it back, we should do all of this as a

244
// post-pass overall of the graphs. We need to takecloning out of

245
//removeDeadNodes and gut removeDeadNodes at the same time first though. :(

246 cloneGlobalsInto(DSG,DSGraph::DontCloneCallNodes |

247 DSGraph::DontCloneAuxCallNodes);

248

249 DEBUG(errs() << "Inliningcallers into '"

250 << DSG->getFunctionNames()<< "'\n");

251

252 DSG->maskIncompleteMarkers();

253
// Iterativelyinline caller graphs into this graph.

254
while(!EdgesFromCaller.empty()) {

255 DSGraph* CallerGraph =EdgesFromCaller.back().CallerGraph;

256

257
// Iteratethrough all of the call sites of this graph, cloning and merging

258
// any nodesrequired by the call.

259 ReachabilityCloner RC(DSG, CallerGraph,

260 DSGraph::DontCloneCallNodes |

261 DSGraph::DontCloneAuxCallNodes);

262

263
// Inline all callsites from this caller graph.

264
do {

265
constDSCallSite &CS = *EdgesFromCaller.back().CS;

266
constFunction &CF = *EdgesFromCaller.back().CalledFunction;

267 DEBUG(errs() << " Inlining graph into Fn '"

268 << CF.getName().str() << "'from ");

269 if(CallerGraph->getReturnNodes().empty()) {

270 DEBUG(errs() << "SYNTHESIZEDINDIRECT GRAPH");

271 } else {

272 DEBUG(errs() << "Fn '"<< CS.getCallSite().getInstruction()->

273 getParent()->getParent()->getName().str()<< "'");

274 }

275 DEBUG(errs() << ": "<< CF.getFunctionType()->getNumParams()

276 << " args\n");

277

278
// Get theformal argument and return nodes for the called function and

279
// merge themwith the cloned subgraph.

280 DSCallSite T1 =DSG->getCallSiteForArguments(CF);

281 RC.mergeCallSite(T1, CS);

282 ++NumTDInlines;

283

284 EdgesFromCaller.pop_back();

285 }
while(!EdgesFromCaller.empty() &&

286 EdgesFromCaller.back().CallerGraph== CallerGraph);

287 }

252行清除所有节点的不完整标记。顶层调用函数不会进入230~235及254~287行。其他函数则根据CallerEdges的记录,把其调用者中调用点信息简并入自己的图。接着,297行的DSG是InlineCallersIntoGraph要处理的DSGraph,retnodes_begin返回ReturnNodes的首迭代器(ReturnNodes的类型是std::map<constFunction*, DSNodeHandle>,它记录函数的返回值。在BU遍中,在向调用者内联被调用者时,被调用者的返回值将被加入调用者的这个容器)。如果这个DSGraph所代表的函数(经过了内联,所代表的函数可以是多个)之一是外部可调用的,在300行isExternallyCallable被置为true。

TDDataStructures::InlineCallersIntoGraph(续)

291
// Next, now thatthis graph is finalized, we need to recompute the

292
// incompletenessmarkers for this graph and remove unreachable nodes.

293

294
// If any of thefunctions is externally callable, treat everything in its

295
// SCC asexternally callable.

296 bool isExternallyCallable = false;

297
for(DSGraph::retnodes_iterator I = DSG->retnodes_begin(),

298 E = DSG->retnodes_end(); I != E;++I)

299 if (ExternallyCallable.count(I->first)){

300 isExternallyCallable = true;

301
break;

302 }

303

304
// Recompute theIncomplete markers. Depends on whetherargs are complete

305 unsigned IncFlags =DSGraph::IgnoreFormalArgs;

306 IncFlags |= DSGraph::IgnoreGlobals |DSGraph::MarkVAStart;

307 DSG->markIncompleteNodes(IncFlags);

308

309
// If this graphcontains functions that are externally callable, now is the time to mark

310
// theirarguments and return values as external. At this point TD is inlining all caller information,

311
// and that meansExternal callers too.

312 unsigned ExtFlags = isExternallyCallable ?

313 DSGraph::MarkFormalsExternal: DSGraph::DontMarkFormalsExternal;

314 DSG->computeExternalFlags(ExtFlags);

315 DSG->computeIntPtrFlags();

316

317 cloneIntoGlobals(DSG,DSGraph::DontCloneCallNodes |

318 DSGraph::DontCloneAuxCallNodes);

319
//

320
// Delete deadnodes. Treat globals that areunreachable as dead also.

321
//

322
// FIXME:

323
// Do not delete unreachable globals as thecomment describes. For its

324
// alignment checks on the results of loadinstructions, SAFECode must be

325
// able to find the DSNode of both the result ofthe load as well as the

326
// pointer dereferenced by the load. If we remove unreachable globals, then

327
// if the dereferenced pointer is a global, itsDSNode will not reachable

328
// from the local graph's scalar map, and chaosensues.

329
//

330
// So, for now, just remove dead nodes but leavethe globals alone.

331
//

332 DSG->removeDeadNodes(0);

因为在前面252行已经把所有节点的未完成标记去掉了,在307行重现计算这些节点的未完成标记。根据IncFlags内容,markIncompleteNodes只把AuxFunctionCalls容器内的节点、可变参数节点标记为不完整。而314行的computeExternalFlags,则根据函数是否外部可访问,把函数的指针参数、返回值、可变参数标记为外部。317行将函数图中的全局对象节点克隆、简并入全局图(此时全局图中的全局对象节点是标记为完成的)。332行的removeDeadNodes在前一版是有参数DSGraph::RemoveUnreachableGlobals的,当前版本把这个参数去掉,原因322行的注释解释了。

TDDataStructures::InlineCallersIntoGraph(续)

334
// We are donewith computing the current TD Graph! Finally, before we can

335
// finishprocessing this function, we figure out which functions it calls and

336
// records thesecall graph edges, so that we have them when we process the

337
// callee graphs.

338 if (DSG->fc_begin() == DSG->fc_end())
return;

339

340
// Loop over allthe call sites and all the callees at each call site, and add

341
// edges to theCallerEdges structure for each callee.

342
for(DSGraph::fc_iterator CI = DSG->fc_begin(), E = DSG->fc_end();

343 CI != E; ++CI) {

344

345
// Handle directcalls efficiently.

346 if (CI->isDirectCall()) {

347 if(!CI->getCalleeFunc()->isDeclaration() &&

348 !DSG->getReturnNodes().count(CI->getCalleeFunc()))

349 CallerEdges[getOrCreateGraph(CI->getCalleeFunc())]

350 .push_back(CallerCallEdge(DSG,&*CI, CI->getCalleeFunc()));

351
continue;

352 }

353

354 svset<constFunction*> AllCallees;

355 std::vector<constFunction*> Callees;

356

357
// Get the listof callees

358 callgraph.addFullFunctionSet(CI->getCallSite(),AllCallees);

359

360
// Filter allnon-declarations, and calls within this DSGraph

361
for(svset<const Function*>::iterator I =AllCallees.begin(),

362 E = AllCallees.end(); I != E; ++I) {

363
constFunction *F = *I;

364 if (!F->isDeclaration() &&getDSGraph(**I) != DSG)

365 Callees.push_back(F);

366 }

367 AllCallees.clear();

368

369
// If there isexactly one callee from this call site, remember the edge in

370
// CallerEdges.

371 if (Callees.size() == 1) {

372
constFunction * Callee = Callees[0];

373 CallerEdges[getOrCreateGraph(Callee)]

374 .push_back(CallerCallEdge(DSG,&*CI, Callee));

375 }

376 if (Callees.size() <= 1)
continue;

377

378
// Otherwise,there are multiple callees from this call site, so it must be

379
// an indirectcall. Chances are that there will beother call sites with

380
// this set oftargets. If so, we don't want to do M*Ninlining operations,

381
// so we buildup a new, private, graph that represents the calls of all

382
// calls tothis set of functions.

383

384 std::map<std::vector<const Function*>, DSGraph*>::iteratorIndCallRecI =

385 IndCallMap.lower_bound(Callees);

386

387
// If wealready have this graph, recycle it.

388 if (IndCallRecI != IndCallMap.end()&& IndCallRecI->first == Callees) {

389 DEBUG(errs() << " *** Reuse of indcall graph for "<< Callees.size()

390 << " callees!\n");

391 DSGraph * IndCallGraph =IndCallRecI->second;

392
assert(IndCallGraph->getFunctionCalls().size()== 1);

393

394
// Merge thecall into the CS already in the IndCallGraph

395 ReachabilityCloner RC(IndCallGraph, DSG,0);

396 RC.mergeCallSite(IndCallGraph->getFunctionCalls().front(),*CI);

DSGraph的fc_begin及fc_end返回容器FunctionCalls的首尾迭代器,FunctionCalls记录了在该函数中进行的函数调用。上面这段代码的目的是找出当前函数调用的函数,并使CallerEdges记录之。对于直接调用(346行条件),如果被调用的函数有定义,且不在当前函数图中,把它记录在CallerEdges里。对于间接调用,在358行首先获取所有可能的被调用函数,在364行过滤掉没有定义或者在当前函数图中调用的函数。如果被调用函数的个数只是1(371行),那么直接把它记录在CallerEdges里。而如果被调用函数的个数多于1个,而且如果这些被调用函数已经处理过了(比如,另一个调用这些函数的调用点,这样它们会被记录在IndCallMap中),那么已经存在一个内联后的图,在396行把这些函数调用简并入这个图(这样避免在InlineCallersIntoGraph开头的更耗时的内联操作)。注意392行断言检查IndCallMap的完整性是否被破坏。

1036 void
ReachabilityCloner::mergeCallSite(DSCallSite&DestCS,

1037
const DSCallSite &SrcCS) {

1038 merge(DestCS.getRetVal(),SrcCS.getRetVal());

1039 merge(DestCS.getVAVal(),SrcCS.getVAVal());

1040 unsigned MinArgs = DestCS.getNumPtrArgs();

1041 if (SrcCS.getNumPtrArgs() < MinArgs)MinArgs = SrcCS.getNumPtrArgs();

1042

1043 for (unsigneda = 0; a != MinArgs; ++a)

1044 merge(DestCS.getPtrArg(a),SrcCS.getPtrArg(a));

1045

1046 for (unsigneda = MinArgs, e = SrcCS.getNumPtrArgs(); a != e; ++a) {

1047
// If a callsite passes more params, ignore the extra params.

1048
// If thecalled function is varargs, merge the extra params, with

1049
// the varargsnode.

1050 if(DestCS.getVAVal() != NULL) {

1051 merge(DestCS.getVAVal(),SrcCS.getPtrArg(a));

1052 }

1053 }

1054

1055 for (unsigneda = MinArgs, e = DestCS.getNumPtrArgs(); a!=e; ++a) {

1056
// If a callsite passes less explicit params, than the function needs

1057
// But passesparams through a varargs node, merge those in.

1058 if(SrcCS.getVAVal() != NULL) {

1059 merge(DestCS.getPtrArg(a),SrcCS.getVAVal());

1060 }

1061 }

1062 }

对于调用点来说,可以看到就是返回值、各种参数,因此简并意味着处理返回值、指针参数以及可变参数。

接下来处理个数多于1个且尚未处理的被调用函数。这种情况下,399行首先创建一个新的DSGraph实例,注意在这个实例中FunctionCalls是空的,而且不包含任何DSNode节点(因为它的目的就是携带CallSite对象)。407行向这个DSGraph加入唯一的一个DSCallSite对象,并在410行加入IndCallMap(这是前面392行断言的依据)。最后,针对每个被调用函数,在CallerEdges中记录下IndCallGraph(携带CallSite信息的图,即代表调用函数),对应的DSCallSite(似乎不需要),被调用函数(以被调用函数图为键值)。

TDDataStructures::InlineCallersIntoGraph(续)

397 } else {

398
// Otherwise,create a new DSGraph to represent this.

399 DSGraph* IndCallGraph =
new DSGraph(DSG->getGlobalECs(),

400 DSG->getDataLayout(), *TypeSS);

401

402
// Clone overthe call into the new DSGraph

403 ReachabilityCloner RC(IndCallGraph, DSG,0);

404 DSCallSite ClonedCS = RC.cloneCallSite(*CI);

405

406
// Add thecloned CS to the graph, as if it were an original call.

407 IndCallGraph->getFunctionCalls().push_back(ClonedCS);

408

409
// Save thisgraph for use later, should we need it.

410 IndCallRecI =IndCallMap.insert(IndCallRecI,

411 std::make_pair(Callees, IndCallGraph));

412

413
//Additionally, make sure that each of the callees inlines this graph

414
// exactlyonce.

415 DSCallSite *NCS =&IndCallGraph->getFunctionCalls().front();

416
for(unsigned i = 0, e = Callees.size(); i != e; ++i) {

417 DSGraph* CalleeGraph = getDSGraph(*Callees[i]);

418 if (CalleeGraph != DSG)

419 CallerEdges[CalleeGraph].push_back(CallerCallEdge(IndCallGraph, NCS,

420 Callees[i]));

421 }

422 }

423 }

424 }

在处理了所有的函数调用后,IndCallMap,ExternallyCallable的内容不再需要,回收其中的资源。接下来重现计算全局图的各种标记,注意这里不再重现计算完整性标记,因为全局图节点的完整性计算在BUDataStructure及CompleteDataStructure遍中就完成了。同样,函数图的完整性计算在InlineCallersIntoGraph中已经完成。最后,恢复调用图。

TDDataStructures::runOnModule(续)

148
// Free theIndCallMap.

149 while(!IndCallMap.empty()) {

150
deleteIndCallMap.begin()->second;

151 IndCallMap.erase(IndCallMap.begin());

152 }

153

154 formGlobalECs();

155

156 ExternallyCallable.clear();

157 GlobalsGraph->removeTriviallyDeadNodes();

158 GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);

159 GlobalsGraph->computeIntPtrFlags();

160

161
// Make sure eachgraph has updated external information about globals

162
// in the globalsgraph.

163 VisitedGraph.clear();

164
for(Module::iterator F = M.begin(); F != M.end(); ++F) {

165 if (!(F->isDeclaration())){

166 DSGraph *Graph = getOrCreateGraph(F);

167 if (!VisitedGraph.insert(Graph).second)
continue;

168

169 cloneGlobalsInto(Graph,DSGraph::DontCloneCallNodes |

170 DSGraph::DontCloneAuxCallNodes);

171

172 Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);

173 Graph->computeIntPtrFlags();

174
// Clean upuninteresting nodes

175 Graph->removeDeadNodes(0);

176

177 }

178 }

179

180
// CBU containsthe correct call graph.

181
// Restore it, sothat subsequent passes and clients can get it.

182 restoreCorrectCallGraph();

183
return false;

184 }

至此,TDDataStructures及EQTDDataStructures遍的处理全部完成。从DSA分析的结果出发,Chris在论文中提到了其在别名分析及自动池分配(automatic pool allocation)的应用。Poolalloc对此也做了延伸及扩展。Poolalloc目前被应用到SafeCode项目中,它是这个项目的基础。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: