github.com/cloudwego/frugal@v0.1.15/internal/atm/ssa/blockiter.go (about) 1 /* 2 * Copyright 2022 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package ssa 18 19 import ( 20 `github.com/oleiade/lane` 21 ) 22 23 type BasicBlockIter struct { 24 g *CFG 25 b *BasicBlock 26 s *lane.Stack 27 v map[int]struct{} 28 } 29 30 func newBasicBlockIter(cfg *CFG) *BasicBlockIter { 31 return &BasicBlockIter { 32 g: cfg, 33 s: stacknew(cfg.Root), 34 v: map[int]struct{} { cfg.Root.Id: {} }, 35 } 36 } 37 38 func (self *BasicBlockIter) Next() bool { 39 var tail bool 40 var this *BasicBlock 41 42 /* scan until the stack is empty */ 43 for !self.s.Empty() { 44 tail = true 45 this = self.s.Head().(*BasicBlock) 46 47 /* add all the successors */ 48 for _, p := range self.g.DominatorOf[this.Id] { 49 if _, ok := self.v[p.Id]; !ok { 50 tail = false 51 self.v[p.Id] = struct{}{} 52 self.s.Push(p) 53 break 54 } 55 } 56 57 /* all the successors are visited, pop the current node */ 58 if tail { 59 self.b = self.s.Pop().(*BasicBlock) 60 return true 61 } 62 } 63 64 /* clear the basic block pointer to indicate no more blocks */ 65 self.b = nil 66 return false 67 } 68 69 func (self *BasicBlockIter) Block() *BasicBlock { 70 return self.b 71 } 72 73 func (self *BasicBlockIter) ForEach(action func(bb *BasicBlock)) { 74 for self.Next() { 75 action(self.b) 76 } 77 } 78 79 func (self *BasicBlockIter) Reversed() []*BasicBlock { 80 nb := len(self.g.Depth) 81 ret := make([]*BasicBlock, 0, nb) 82 83 /* dump all the blocks */ 84 for self.Next() { 85 ret = append(ret, self.b) 86 } 87 88 /* reverse the order */ 89 blockreverse(ret) 90 return ret 91 }