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  }