github.com/cloudwego/frugal@v0.1.15/internal/atm/ssa/builder.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      `fmt`
    21      `sort`
    22  
    23      `github.com/cloudwego/frugal/internal/atm/hir`
    24  )
    25  
    26  var (
    27      _GenericRegs []hir.GenericRegister
    28      _PointerRegs []hir.PointerRegister
    29  )
    30  
    31  func init() {
    32      _GenericRegs = make([]hir.GenericRegister, 0, len(hir.GenericRegisters))
    33      _PointerRegs = make([]hir.PointerRegister, 0, len(hir.PointerRegisters))
    34  
    35      /* extract all generic registers */
    36      for i := range hir.GenericRegisters {
    37          if i != hir.Rz {
    38              _GenericRegs = append(_GenericRegs, i)
    39          }
    40      }
    41  
    42      /* extract all pointer registers */
    43      for m := range hir.PointerRegisters {
    44          if m != hir.Pn {
    45              _PointerRegs = append(_PointerRegs, m)
    46          }
    47      }
    48  
    49      /* sort by register ID */
    50      sort.Slice(_GenericRegs, func(i int, j int) bool { return _GenericRegs[i] < _GenericRegs[j] })
    51      sort.Slice(_PointerRegs, func(i int, j int) bool { return _PointerRegs[i] < _PointerRegs[j] })
    52  }
    53  
    54  type _GraphBuilder struct {
    55      p map[*hir.Ir]bool
    56      g map[*hir.Ir]*BasicBlock
    57  }
    58  
    59  func newGraphBuilder() *_GraphBuilder {
    60      return &_GraphBuilder {
    61          p: make(map[*hir.Ir]bool),
    62          g: make(map[*hir.Ir]*BasicBlock),
    63      }
    64  }
    65  
    66  func (self *_GraphBuilder) build(p hir.Program) *CFG {
    67      ret := &CFG {
    68          Depth             : make(map[int]int),
    69          DominatedBy       : make(map[int]*BasicBlock),
    70          DominatorOf       : make(map[int][]*BasicBlock),
    71          DominanceFrontier : make(map[int][]*BasicBlock),
    72      }
    73  
    74      /* create the root block */
    75      ret.Root = ret.CreateBlock()
    76      ret.Root.Ins = make([]IrNode, 0, len(_GenericRegs) + len(_PointerRegs) + N_size)
    77  
    78      /* implicit defination of all generic registers */
    79      for _, v := range _GenericRegs {
    80          ret.Root.Ins = append(ret.Root.Ins, &IrConstInt { R: Rv(v), V: 0 })
    81      }
    82  
    83      /* implicit defination of all pointer registers */
    84      for _, v := range _PointerRegs {
    85          ret.Root.Ins = append(ret.Root.Ins, &IrConstPtr { R: Rv(v), P: nil, M: Volatile })
    86      }
    87  
    88      /* implicitly define all the temporary registers */
    89      for i := 0; i < N_size; i++ {
    90          ret.Root.Ins = append(
    91              ret.Root.Ins,
    92              &IrConstInt { R: Tr(i), V: 0 },
    93              &IrConstPtr { R: Pr(i), P: nil, M: Volatile },
    94          )
    95      }
    96  
    97      /* mark all the branch targets */
    98      for v := p.Head; v != nil; v = v.Ln {
    99          if v.IsBranch() {
   100              if v.Op != hir.OP_bsw {
   101                  self.p[v.Br] = true
   102              } else {
   103                  for _, lb := range v.Switch() {
   104                      self.p[lb] = true
   105                  }
   106              }
   107          }
   108      }
   109  
   110      /* process the root block */
   111      self.g[p.Head] = ret.Root
   112      self.block(ret, p.Head, ret.Root)
   113  
   114      /* build the CFG */
   115      ret.Rebuild()
   116      return ret
   117  }
   118  
   119  func (self *_GraphBuilder) block(cfg *CFG, p *hir.Ir, bb *BasicBlock) {
   120      bb.Phi = nil
   121      bb.Term = nil
   122  
   123      /* traverse down until it hits a branch instruction */
   124      for p != nil && !p.IsBranch() && p.Op != hir.OP_ret {
   125          bb.addInstr(p)
   126          p = p.Ln
   127  
   128          /* hit a merge point, merge with existing block */
   129          if self.p[p] {
   130              bb.termBranch(self.branch(cfg, p))
   131              return
   132          }
   133      }
   134  
   135      /* basic block must terminate */
   136      if p == nil {
   137          panic(fmt.Sprintf("basic block %d does not terminate", bb.Id))
   138      }
   139  
   140      /* add terminators */
   141      switch p.Op {
   142          case hir.OP_bsw : self.termbsw(cfg, p, bb)
   143          case hir.OP_ret : bb.termReturn(p)
   144          case hir.OP_jmp : bb.termBranch(self.branch(cfg, p.Br))
   145          default         : bb.termCondition(p, self.branch(cfg, p.Br), self.branch(cfg, p.Ln))
   146      }
   147  }
   148  
   149  func (self *_GraphBuilder) branch(cfg *CFG, p *hir.Ir) *BasicBlock {
   150      var ok bool
   151      var bb *BasicBlock
   152  
   153      /* check for existing basic blocks */
   154      if bb, ok = self.g[p]; ok {
   155          return bb
   156      }
   157  
   158      /* create and process the new block */
   159      bb = cfg.CreateBlock()
   160      self.g[p] = bb
   161      self.block(cfg, p, bb)
   162      return bb
   163  }
   164  
   165  func (self *_GraphBuilder) termbsw(cfg *CFG, p *hir.Ir, bb *BasicBlock) {
   166      sw := new(IrSwitch)
   167      sw.Br = make(map[int32]*IrBranch, p.Iv)
   168      bb.Term = sw
   169  
   170      /* add every branch of the switch instruction */
   171      for i, br := range p.Switch() {
   172          if br != nil {
   173              to := self.branch(cfg, br)
   174              to.addPred(bb)
   175              sw.Br[int32(i)] = IrLikely(to)
   176          }
   177      }
   178  
   179      /* add the default branch */
   180      sw.Ln = IrUnlikely(self.branch(cfg, p.Ln))
   181      sw.Ln.To.addPred(bb)
   182  }