github.com/cloudwego/frugal@v0.1.15/internal/atm/hir/prog.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 hir
    18  
    19  import (
    20      `fmt`
    21      `strings`
    22  )
    23  
    24  type Program struct {
    25      Head *Ir
    26  }
    27  
    28  func (self Program) Free() {
    29      for p, q := self.Head, self.Head; p != nil; p = q {
    30          q = p.Ln
    31          p.Free()
    32      }
    33  }
    34  
    35  func (self Program) Disassemble() string {
    36      ret := make([]string, 0, 64)
    37      ref := make(map[*Ir]string)
    38  
    39      /* scan all the branch target */
    40      for p := self.Head; p != nil; p = p.Ln {
    41          if p.IsBranch() {
    42              if p.Op != OP_bsw {
    43                  if _, ok := ref[p.Br]; !ok {
    44                      ref[p.Br] = fmt.Sprintf("L_%d", len(ref))
    45                  }
    46              } else {
    47                  for _, lb := range p.Switch() {
    48                      if lb != nil {
    49                          if _, ok := ref[lb]; !ok {
    50                              ref[lb] = fmt.Sprintf("L_%d", len(ref))
    51                          }
    52                      }
    53                  }
    54              }
    55          }
    56      }
    57  
    58      /* dump all the instructions */
    59      for p := self.Head; p != nil; p = p.Ln {
    60          var ok bool
    61          var vv string
    62  
    63          /* check for label reference */
    64          if vv, ok = ref[p]; ok {
    65              ret = append(ret, vv + ":")
    66          }
    67  
    68          /* indent each line */
    69          for _, ln := range strings.Split(p.Disassemble(ref), "\n") {
    70              ret = append(ret, "    " + ln)
    71          }
    72      }
    73  
    74      /* join them together */
    75      return strings.Join(ret, "\n")
    76  }