1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "cg_cfg.h"
17 #if TARGAARCH64
18 #include "aarch64_insn.h"
19 #endif
20 #if TARGX86_64
21 #include "x64_cgfunc.h"
22 #include "cg.h"
23 #endif
24
25 namespace maplebe {
BuildCFG()26 void CGCFG::BuildCFG()
27 {
28 if (cgFunc->HasBuiltCfg()) {
29 return;
30 }
31 /*
32 * Second Pass:
33 * Link preds/succs in the BBs
34 */
35 BB *firstBB = cgFunc->GetFirstBB();
36 for (BB *curBB = firstBB; curBB != nullptr; curBB = curBB->GetNext()) {
37 BB::BBKind kind = curBB->GetKind();
38 switch (kind) {
39 case BB::kBBIf: {
40 BB *fallthruBB = curBB->GetNext();
41 curBB->PushBackSuccs(*fallthruBB);
42 fallthruBB->PushBackPreds(*curBB);
43 Insn *branchInsn = curBB->GetLastMachineInsn();
44 CHECK_FATAL(branchInsn != nullptr, "machine instruction must be exist in ifBB");
45 DEBUG_ASSERT(branchInsn->IsCondBranch(), "must be a conditional branch generated from an intrinsic");
46 /* Assume the last non-null operand is the branch target */
47 uint32 opSz = branchInsn->GetOperandSize();
48 DEBUG_ASSERT(opSz >= 1, "lastOpndIndex's opnd is greater than 1");
49 Operand &lastOpnd = branchInsn->GetOperand(opSz - 1u);
50 DEBUG_ASSERT(lastOpnd.IsLabelOpnd(), "label Operand must be exist in branch insn");
51 auto &labelOpnd = static_cast<LabelOperand &>(lastOpnd);
52 BB *brToBB = cgFunc->GetBBFromLab2BBMap(labelOpnd.GetLabelIndex());
53 if (fallthruBB->GetId() != brToBB->GetId()) {
54 curBB->PushBackSuccs(*brToBB);
55 brToBB->PushBackPreds(*curBB);
56 }
57 break;
58 }
59 case BB::kBBGoto: {
60 Insn *insn = curBB->GetLastMachineInsn();
61 if (insn == nullptr) {
62 curBB->SetKind(BB::kBBFallthru);
63 continue;
64 }
65 CHECK_FATAL(insn != nullptr, "machine insn must be exist in gotoBB");
66 DEBUG_ASSERT(insn->IsUnCondBranch(), "insn must be a unconditional branch insn");
67 LabelIdx labelIdx = static_cast<LabelOperand &>(insn->GetOperand(0)).GetLabelIndex();
68 BB *gotoBB = cgFunc->GetBBFromLab2BBMap(labelIdx);
69 CHECK_FATAL(gotoBB != nullptr, "gotoBB is null");
70 curBB->PushBackSuccs(*gotoBB);
71 gotoBB->PushBackPreds(*curBB);
72 break;
73 }
74 case BB::kBBRangeGoto: {
75 std::set<BB *, BBIdCmp> bbs;
76 for (auto labelIdx : curBB->GetRangeGotoLabelVec()) {
77 BB *gotoBB = cgFunc->GetBBFromLab2BBMap(labelIdx);
78 bbs.insert(gotoBB);
79 }
80 for (auto gotoBB : bbs) {
81 curBB->PushBackSuccs(*gotoBB);
82 gotoBB->PushBackPreds(*curBB);
83 }
84 break;
85 }
86 case BB::kBBFallthru: {
87 BB *fallthruBB = curBB->GetNext();
88 if (fallthruBB != nullptr) {
89 curBB->PushBackSuccs(*fallthruBB);
90 fallthruBB->PushBackPreds(*curBB);
91 }
92 break;
93 }
94 default:
95 break;
96 } /* end switch */
97 }
98 FindAndMarkUnreachable(*cgFunc);
99 cgFunc->SetHasBuiltCfg(true);
100 }
101
CheckCFG()102 void CGCFG::CheckCFG()
103 {
104 FOR_ALL_BB(bb, cgFunc)
105 {
106 for (BB *sucBB : bb->GetSuccs()) {
107 bool found = false;
108 for (BB *sucPred : sucBB->GetPreds()) {
109 if (sucPred == bb) {
110 if (!found) {
111 found = true;
112 } else {
113 LogInfo::MapleLogger()
114 << "dup pred " << sucPred->GetId() << " for sucBB " << sucBB->GetId() << "\n";
115 CHECK_FATAL_FALSE("CG_CFG check failed !");
116 }
117 }
118 }
119 if (!found) {
120 LogInfo::MapleLogger() << "non pred for sucBB " << sucBB->GetId() << " for BB " << bb->GetId() << "\n";
121 CHECK_FATAL_FALSE("CG_CFG check failed !");
122 }
123 }
124 }
125 FOR_ALL_BB(bb, cgFunc)
126 {
127 for (BB *predBB : bb->GetPreds()) {
128 bool found = false;
129 for (BB *predSucc : predBB->GetSuccs()) {
130 if (predSucc == bb) {
131 if (!found) {
132 found = true;
133 } else {
134 LogInfo::MapleLogger()
135 << "dup succ " << predSucc->GetId() << " for predBB " << predBB->GetId() << "\n";
136 CHECK_FATAL_FALSE("CG_CFG check failed !");
137 }
138 }
139 }
140 if (!found) {
141 LogInfo::MapleLogger() << "non succ for predBB " << predBB->GetId() << " for BB " << bb->GetId()
142 << "\n";
143 CHECK_FATAL_FALSE("CG_CFG check failed !");
144 }
145 }
146 }
147 }
148
149 InsnVisitor *CGCFG::insnVisitor;
150
InitInsnVisitor(CGFunc & func) const151 void CGCFG::InitInsnVisitor(CGFunc &func) const
152 {
153 insnVisitor = func.NewInsnModifier();
154 }
155
156 /*
157 * return true if:
158 * mergee has only one predecessor which is merger,
159 * or mergee has other comments only predecessors & merger is soloGoto
160 * mergee can't have cfi instruction when postcfgo.
161 */
BBJudge(const BB & first,const BB & second) const162 bool CGCFG::BBJudge(const BB &first, const BB &second) const
163 {
164 if (first.GetKind() == BB::kBBReturn || second.GetKind() == BB::kBBReturn) {
165 return false;
166 }
167 if (&first == &second) {
168 return false;
169 }
170 if (second.GetPreds().size() == 1 && second.GetPreds().front() == &first) {
171 return true;
172 }
173 for (BB *bb : second.GetPreds()) {
174 if (bb != &first && !AreCommentAllPreds(*bb)) {
175 return false;
176 }
177 }
178 return first.IsSoloGoto();
179 }
180
181 /*
182 * Check if a given BB mergee can be merged into BB merger.
183 * Returns true if:
184 * 1. mergee has only one predecessor which is merger, or mergee has
185 * other comments only predecessors.
186 * 2. merge has only one successor which is mergee.
187 * 3. mergee can't have cfi instruction when postcfgo.
188 */
CanMerge(const BB & merger,const BB & mergee) const189 bool CGCFG::CanMerge(const BB &merger, const BB &mergee) const
190 {
191 if (!BBJudge(merger, mergee)) {
192 return false;
193 }
194 if (mergee.GetFirstInsn() != nullptr && mergee.GetFirstInsn()->IsCfiInsn()) {
195 return false;
196 }
197 return (merger.GetSuccs().size() == 1) && (merger.GetSuccs().front() == &mergee);
198 }
199
200 /* Check if the given BB contains only comments and all its predecessors are comments */
AreCommentAllPreds(const BB & bb)201 bool CGCFG::AreCommentAllPreds(const BB &bb)
202 {
203 if (!bb.IsCommentBB()) {
204 return false;
205 }
206 for (BB *pred : bb.GetPreds()) {
207 if (!AreCommentAllPreds(*pred)) {
208 return false;
209 }
210 }
211 return true;
212 }
213
214 /* Merge sucBB into curBB. */
MergeBB(BB & merger,BB & mergee,CGFunc & func)215 void CGCFG::MergeBB(BB &merger, BB &mergee, CGFunc &func)
216 {
217 BB *prevLast = mergee.GetPrev();
218 MergeBB(merger, mergee);
219 if (func.GetLastBB()->GetId() == mergee.GetId()) {
220 func.SetLastBB(*prevLast);
221 }
222 if (mergee.GetKind() == BB::kBBReturn) {
223 auto retIt = func.GetExitBBsVec().begin();
224 while (retIt != func.GetExitBBsVec().end()) {
225 if (*retIt == &mergee) {
226 (void)func.EraseExitBBsVec(retIt);
227 break;
228 } else {
229 ++retIt;
230 }
231 }
232 func.PushBackExitBBsVec(merger);
233 }
234 if (mergee.GetKind() == BB::kBBNoReturn) {
235 auto noRetIt = func.GetNoRetCallBBVec().begin();
236 while (noRetIt != func.GetNoRetCallBBVec().end()) {
237 if (*noRetIt == &mergee) {
238 (void)func.EraseNoReturnCallBB(noRetIt);
239 break;
240 } else {
241 ++noRetIt;
242 }
243 }
244 func.PushBackNoReturnCallBBsVec(merger);
245 }
246 if (mergee.GetKind() == BB::kBBRangeGoto) {
247 func.AddEmitSt(merger.GetId(), *func.GetEmitSt(mergee.GetId()));
248 func.DeleteEmitSt(mergee.GetId());
249 }
250 }
251
MergeBB(BB & merger,BB & mergee)252 void CGCFG::MergeBB(BB &merger, BB &mergee)
253 {
254 if (merger.GetKind() == BB::kBBGoto && merger.GetLastMachineInsn() != nullptr) {
255 if (!merger.GetLastMachineInsn()->IsBranch()) {
256 CHECK_FATAL(false, "unexpected insn kind");
257 }
258 merger.RemoveInsn(*merger.GetLastMachineInsn());
259 }
260 merger.AppendBBInsns(mergee);
261 if (mergee.GetPrev() != nullptr) {
262 mergee.GetPrev()->SetNext(mergee.GetNext());
263 }
264 if (mergee.GetNext() != nullptr) {
265 mergee.GetNext()->SetPrev(mergee.GetPrev());
266 }
267 merger.RemoveSuccs(mergee);
268 for (BB *bb : mergee.GetSuccs()) {
269 bb->RemovePreds(mergee);
270 bb->PushBackPreds(merger);
271 merger.PushBackSuccs(*bb);
272 }
273 merger.SetKind(mergee.GetKind());
274 mergee.SetNext(nullptr);
275 mergee.SetPrev(nullptr);
276 mergee.ClearPreds();
277 mergee.ClearSuccs();
278 mergee.SetFirstInsn(nullptr);
279 mergee.SetLastInsn(nullptr);
280 }
281
282 /*
283 * Find all reachable BBs by dfs in cgfunc and mark their field<unreachable> false, then all other bbs should be
284 * unreachable.
285 */
FindAndMarkUnreachable(CGFunc & func)286 void CGCFG::FindAndMarkUnreachable(CGFunc &func)
287 {
288 BB *firstBB = func.GetFirstBB();
289 std::stack<BB *> toBeAnalyzedBBs;
290 toBeAnalyzedBBs.push(firstBB);
291 std::unordered_set<uint32> instackBBs;
292
293 BB *bb = firstBB;
294 /* set all bb's unreacable to true */
295 while (bb != nullptr) {
296 /* Check if bb is the first or the last BB of the function */
297 if (InSwitchTable(bb->GetLabIdx(), func) || bb == func.GetFirstBB() || bb == func.GetLastBB()) {
298 toBeAnalyzedBBs.push(bb);
299 } else if (bb->IsLabelTaken() == false) {
300 bb->SetUnreachable(true);
301 }
302 bb = bb->GetNext();
303 }
304
305 /* do a dfs to see which bbs are reachable */
306 while (!toBeAnalyzedBBs.empty()) {
307 bb = toBeAnalyzedBBs.top();
308 toBeAnalyzedBBs.pop();
309 (void)instackBBs.insert(bb->GetId());
310
311 bb->SetUnreachable(false);
312
313 for (BB *succBB : bb->GetSuccs()) {
314 if (instackBBs.count(succBB->GetId()) == 0) {
315 toBeAnalyzedBBs.push(succBB);
316 (void)instackBBs.insert(succBB->GetId());
317 }
318 }
319 }
320 FOR_ALL_BB(tmpBB, &func)
321 {
322 for (MapleList<BB *>::iterator predIt = tmpBB->GetPredsBegin(); predIt != tmpBB->GetPredsEnd(); ++predIt) {
323 if ((*predIt)->IsUnreachable()) {
324 tmpBB->ErasePreds(predIt);
325 }
326 }
327 }
328 }
329
330 /*
331 * Theoretically, every time you remove from a bb's preds, you should consider invoking this method.
332 *
333 * @param bb
334 * @param func
335 */
FlushUnReachableStatusAndRemoveRelations(BB & bb,const CGFunc & func) const336 void CGCFG::FlushUnReachableStatusAndRemoveRelations(BB &bb, const CGFunc &func) const
337 {
338 /* Check if bb is the first or the last BB of the function */
339 bool isFirstBBInfunc = (&bb == func.GetFirstBB());
340 bool isLastBBInfunc = (&bb == func.GetLastBB());
341 if (InSwitchTable(bb.GetLabIdx(), func) || isFirstBBInfunc || isLastBBInfunc) {
342 return;
343 }
344 std::stack<BB *> toBeAnalyzedBBs;
345 toBeAnalyzedBBs.push(&bb);
346 std::set<uint32> instackBBs;
347 BB *it = nullptr;
348 while (!toBeAnalyzedBBs.empty()) {
349 it = toBeAnalyzedBBs.top();
350 (void)instackBBs.insert(it->GetId());
351 toBeAnalyzedBBs.pop();
352 /* Check if bb is the first or the last BB of the function */
353 isFirstBBInfunc = (it == func.GetFirstBB());
354 isLastBBInfunc = (it == func.GetLastBB());
355 bool needFlush = !isFirstBBInfunc && !isLastBBInfunc && it->GetPreds().empty() &&
356 !InSwitchTable(it->GetLabIdx(), *cgFunc) && !cgFunc->IsExitBB(*it) &&
357 (it->IsLabelTaken() == false);
358 if (!needFlush) {
359 continue;
360 }
361 it->SetUnreachable(true);
362 it->SetFirstInsn(nullptr);
363 it->SetLastInsn(nullptr);
364 for (BB *succ : it->GetSuccs()) {
365 if (instackBBs.count(succ->GetId()) == 0) {
366 toBeAnalyzedBBs.push(succ);
367 (void)instackBBs.insert(succ->GetId());
368 }
369 succ->RemovePreds(*it);
370 }
371 it->ClearSuccs();
372 }
373 }
374
RemoveBB(BB & curBB,bool isGotoIf) const375 void CGCFG::RemoveBB(BB &curBB, bool isGotoIf) const
376 {
377 if (!curBB.IsUnreachable()) {
378 BB *sucBB = CGCFG::GetTargetSuc(curBB, false, isGotoIf);
379 if (sucBB != nullptr) {
380 sucBB->RemovePreds(curBB);
381 }
382 BB *fallthruSuc = nullptr;
383 if (isGotoIf) {
384 for (BB *succ : curBB.GetSuccs()) {
385 if (succ == sucBB) {
386 continue;
387 }
388 fallthruSuc = succ;
389 break;
390 }
391 DEBUG_ASSERT(fallthruSuc == curBB.GetNext(), "fallthru succ should be its next bb.");
392 if (fallthruSuc != nullptr) {
393 fallthruSuc->RemovePreds(curBB);
394 }
395 }
396
397 for (BB *preBB : curBB.GetPreds()) {
398 /*
399 * If curBB is the target of its predecessor, change
400 * the jump target.
401 */
402 if (&curBB == GetTargetSuc(*preBB, true, isGotoIf)) {
403 LabelIdx targetLabel;
404 if (curBB.GetNext()->GetLabIdx() == 0) {
405 targetLabel = insnVisitor->GetCGFunc()->CreateLabel();
406 curBB.GetNext()->SetLabIdx(targetLabel);
407 cgFunc->SetLab2BBMap(targetLabel, *curBB.GetNext());
408 } else {
409 targetLabel = curBB.GetNext()->GetLabIdx();
410 }
411 insnVisitor->ModifyJumpTarget(targetLabel, *preBB);
412 }
413 if (fallthruSuc != nullptr && !fallthruSuc->IsPredecessor(*preBB)) {
414 preBB->PushBackSuccs(*fallthruSuc);
415 fallthruSuc->PushBackPreds(*preBB);
416 }
417 if (sucBB != nullptr && !sucBB->IsPredecessor(*preBB)) {
418 preBB->PushBackSuccs(*sucBB);
419 sucBB->PushBackPreds(*preBB);
420 }
421 preBB->RemoveSuccs(curBB);
422 }
423 }
424
425 if (curBB.GetNext() != nullptr) {
426 cgFunc->GetCommonExitBB()->RemovePreds(curBB);
427 curBB.GetNext()->RemovePreds(curBB);
428 curBB.GetNext()->SetPrev(curBB.GetPrev());
429 } else {
430 cgFunc->SetLastBB(*curBB.GetPrev());
431 }
432 if (curBB.GetPrev() != nullptr) {
433 curBB.GetPrev()->SetNext(curBB.GetNext());
434 } else {
435 cgFunc->SetFirstBB(*curBB.GetNext());
436 }
437 cgFunc->ClearBBInVec(curBB.GetId());
438 }
439
UpdateCommonExitBBInfo()440 void CGCFG::UpdateCommonExitBBInfo()
441 {
442 BB *commonExitBB = cgFunc->GetCommonExitBB();
443 ASSERT_NOT_NULL(commonExitBB);
444 commonExitBB->ClearPreds();
445 for (BB *exitBB : cgFunc->GetExitBBsVec()) {
446 if (!exitBB->IsUnreachable()) {
447 commonExitBB->PushBackPreds(*exitBB);
448 }
449 }
450 for (BB *noRetBB : cgFunc->GetNoRetCallBBVec()) {
451 if (!noRetBB->IsUnreachable()) {
452 commonExitBB->PushBackPreds(*noRetBB);
453 }
454 }
455 WontExitAnalysis();
456 }
457
GetTargetSuc(BB & curBB,bool branchOnly,bool isGotoIf)458 BB *CGCFG::GetTargetSuc(BB &curBB, bool branchOnly, bool isGotoIf)
459 {
460 switch (curBB.GetKind()) {
461 case BB::kBBGoto:
462 case BB::kBBIf: {
463 const Insn *origLastInsn = curBB.GetLastMachineInsn();
464 ASSERT_NOT_NULL(origLastInsn);
465 if (isGotoIf && (curBB.GetPrev() != nullptr) &&
466 (curBB.GetKind() == BB::kBBGoto || curBB.GetKind() == BB::kBBIf) &&
467 (curBB.GetPrev()->GetKind() == BB::kBBGoto || curBB.GetPrev()->GetKind() == BB::kBBIf)) {
468 origLastInsn = curBB.GetPrev()->GetLastMachineInsn();
469 }
470 ASSERT_NOT_NULL(origLastInsn);
471 LabelIdx label = insnVisitor->GetJumpLabel(*origLastInsn);
472 for (BB *bb : curBB.GetSuccs()) {
473 if (bb->GetLabIdx() == label) {
474 return bb;
475 }
476 }
477 break;
478 }
479 case BB::kBBFallthru: {
480 return (branchOnly ? nullptr : curBB.GetNext());
481 }
482 default:
483 return nullptr;
484 }
485 return nullptr;
486 }
487
InSwitchTable(LabelIdx label,const CGFunc & func)488 bool CGCFG::InSwitchTable(LabelIdx label, const CGFunc &func)
489 {
490 if (label == 0) {
491 return false;
492 }
493 return func.InSwitchTable(label);
494 }
495
496 /*
497 * analyse the CFG to find the BBs that are not reachable from function entries
498 * and delete them
499 */
UnreachCodeAnalysis() const500 void CGCFG::UnreachCodeAnalysis() const
501 {
502 BB *firstBB = cgFunc->GetFirstBB();
503 std::forward_list<BB *> toBeAnalyzedBBs;
504 toBeAnalyzedBBs.push_front(firstBB);
505 std::set<BB *, BBIdCmp> unreachBBs;
506
507 BB *bb = firstBB;
508 /* set all bb's unreacable to true */
509 while (bb != nullptr) {
510 /* Check if bb is the firstBB/cleanupBB/returnBB/lastBB of the function */
511 if (InSwitchTable(bb->GetLabIdx(), *cgFunc) || bb == cgFunc->GetFirstBB() ||
512 bb == cgFunc->GetLastBB() || bb->GetKind() == BB::kBBReturn) {
513 toBeAnalyzedBBs.push_front(bb);
514 } else {
515 (void)unreachBBs.insert(bb);
516 }
517 if (bb->IsLabelTaken() == false) {
518 bb->SetUnreachable(true);
519 }
520 bb = bb->GetNext();
521 }
522
523 /* do a dfs to see which bbs are reachable */
524 while (!toBeAnalyzedBBs.empty()) {
525 bb = toBeAnalyzedBBs.front();
526 toBeAnalyzedBBs.pop_front();
527 if (!bb->IsUnreachable()) {
528 continue;
529 }
530 bb->SetUnreachable(false);
531 for (BB *succBB : bb->GetSuccs()) {
532 toBeAnalyzedBBs.push_front(succBB);
533 unreachBBs.erase(succBB);
534 }
535 }
536
537 /* remove unreachable bb */
538 std::set<BB *, BBIdCmp>::iterator it;
539 for (it = unreachBBs.begin(); it != unreachBBs.end(); it++) {
540 BB *unreachBB = *it;
541 DEBUG_ASSERT(unreachBB != nullptr, "unreachBB must not be nullptr");
542 for (auto exitBB = cgFunc->GetExitBBsVec().begin(); exitBB != cgFunc->GetExitBBsVec().end(); ++exitBB) {
543 if (*exitBB == unreachBB) {
544 cgFunc->GetExitBBsVec().erase(exitBB);
545 break;
546 }
547 }
548 unreachBB->GetPrev()->SetNext(unreachBB->GetNext());
549 cgFunc->GetCommonExitBB()->RemovePreds(*unreachBB);
550 if (unreachBB->GetNext()) {
551 unreachBB->GetNext()->SetPrev(unreachBB->GetPrev());
552 }
553
554 for (BB *sucBB : unreachBB->GetSuccs()) {
555 sucBB->RemovePreds(*unreachBB);
556 }
557
558 unreachBB->ClearSuccs();
559
560 cgFunc->ClearBBInVec(unreachBB->GetId());
561 }
562 }
563
FindWillExitBBs(BB * bb,std::set<BB *,BBIdCmp> * visitedBBs)564 void CGCFG::FindWillExitBBs(BB *bb, std::set<BB *, BBIdCmp> *visitedBBs)
565 {
566 std::queue<BB *> allBBs;
567 allBBs.push(bb);
568 while (!allBBs.empty()) {
569 BB *curBB = allBBs.front();
570 allBBs.pop();
571 if (visitedBBs->count(curBB) != 0) {
572 continue;
573 }
574 visitedBBs->insert(curBB);
575 for (auto *predBB : curBB->GetPreds()) {
576 allBBs.push(predBB);
577 }
578 }
579 }
580
581 /*
582 * analyse the CFG to find the BBs that will not reach any function exit; these
583 * are BBs inside infinite loops; mark their wontExit flag and create
584 * artificial edges from them to commonExitBB
585 */
WontExitAnalysis()586 void CGCFG::WontExitAnalysis()
587 {
588 std::set<BB *, BBIdCmp> visitedBBs;
589 FindWillExitBBs(cgFunc->GetCommonExitBB(), &visitedBBs);
590 BB *bb = cgFunc->GetFirstBB();
591 while (bb != nullptr) {
592 if (visitedBBs.count(bb) == 0) {
593 bb->SetWontExit(true);
594 if (bb->GetKind() == BB::kBBGoto) {
595 // make this bb a predecessor of commonExitBB
596 cgFunc->GetCommonExitBB()->PushBackPreds(*bb);
597 }
598 }
599 bb = bb->GetNext();
600 }
601 }
602
GetAnalysisDependence(AnalysisDep & aDep) const603 void CgHandleCFG::GetAnalysisDependence(AnalysisDep &aDep) const
604 {
605 aDep.SetPreservedAll();
606 }
607
PhaseRun(maplebe::CGFunc & f)608 bool CgHandleCFG::PhaseRun(maplebe::CGFunc &f)
609 {
610 CGCFG *cfg = f.GetMemoryPool()->New<CGCFG>(f);
611 f.SetTheCFG(cfg);
612 /* build control flow graph */
613 f.GetTheCFG()->BuildCFG();
614 f.HandleFuncCfg(cfg);
615
616 /* analysis unreachable code */
617 f.GetTheCFG()->UnreachCodeAnalysis();
618 f.EraseUnreachableStackMapInsns();
619 return false;
620 }
621 MAPLE_ANALYSIS_PHASE_REGISTER(CgHandleCFG, handlecfg)
622
623 } /* namespace maplebe */
624