github.com/cloudwego/frugal@v0.1.15/internal/atm/hir/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 hir
    18  
    19  import (
    20      `strconv`
    21      `strings`
    22      `unsafe`
    23  
    24      `github.com/cloudwego/frugal/internal/rt`
    25  )
    26  
    27  const (
    28      _LB_jump_pc = "_jump_pc_"
    29  )
    30  
    31  type Builder struct {
    32      i     int
    33      head  *Ir
    34      tail  *Ir
    35      refs  map[string]*Ir
    36      pends map[string][]**Ir
    37  }
    38  
    39  func CreateBuilder() *Builder {
    40      return newBuilder()
    41  }
    42  
    43  func (self *Builder) add(ins *Ir) *Ir {
    44      self.push(ins)
    45      return ins
    46  }
    47  
    48  func (self *Builder) jmp(p *Ir, to string) *Ir {
    49      ok := false
    50      lr := Likely
    51      lb := strings.ReplaceAll(to, "{n}", strconv.Itoa(self.i))
    52  
    53      /* backward jumps are predicted "likely", forward "unlikely" */
    54      if p.Br, ok = self.refs[lb]; !ok {
    55          lr = Unlikely
    56          self.pends[lb] = append(self.pends[lb], &p.Br)
    57      }
    58  
    59      /* unconditional jumps are always predicted "likely" */
    60      if p.Op == OP_jmp {
    61          lr = Likely
    62      }
    63  
    64      /* add to instruction buffer */
    65      p.An = uint8(lr)
    66      return self.add(p)
    67  }
    68  
    69  func (self *Builder) tab(p *Ir, sw []string) *Ir {
    70      nb := len(sw)
    71      sb := make([]*Ir, nb)
    72  
    73      /* patch each branch */
    74      for i, to := range sw {
    75          ok := false
    76          lb := strings.ReplaceAll(to, "{n}", strconv.Itoa(self.i))
    77  
    78          /* check for backward jumps */
    79          if lb != "" {
    80              if sb[i], ok = self.refs[lb]; !ok {
    81                  self.pends[lb] = append(self.pends[lb], &sb[i])
    82              }
    83          }
    84      }
    85  
    86      /* save the switch table */
    87      p.Iv = int64(nb)
    88      p.Pr = (*rt.GoSlice)(unsafe.Pointer(&sb)).Ptr
    89      return self.add(p)
    90  }
    91  
    92  func (self *Builder) push(ins *Ir) {
    93      if self.head == nil {
    94          self.head, self.tail = ins, ins
    95      } else {
    96          self.tail.Ln, self.tail = ins, ins
    97      }
    98  }
    99  
   100  func (self *Builder) rejmp(br **Ir) {
   101      for *br != nil && (*br).Ln != nil && (*br).Op == OP_nop {
   102          *br = (*br).Ln
   103      }
   104  }
   105  
   106  func (self *Builder) At(pc int) string {
   107      return _LB_jump_pc + strconv.Itoa(pc)
   108  }
   109  
   110  func (self *Builder) Mark(pc int) {
   111      self.i++
   112      self.Label(self.At(pc))
   113  }
   114  
   115  func (self *Builder) Label(to string) {
   116      ok := false
   117      lb := strings.ReplaceAll(to, "{n}", strconv.Itoa(self.i))
   118  
   119      /* check for duplications */
   120      if _, ok = self.refs[lb]; ok {
   121          panic("label " + lb + " has already been linked")
   122      }
   123  
   124      /* get the pending links */
   125      p := self.NOP()
   126      v := self.pends[lb]
   127  
   128      /* patch all the pending jumps */
   129      for _, q := range v {
   130          *q = p
   131      }
   132  
   133      /* mark the label as resolved */
   134      self.refs[lb] = p
   135      delete(self.pends, lb)
   136  }
   137  
   138  func (self *Builder) Build() (r Program) {
   139      var n int
   140      var p *Ir
   141      var q *Ir
   142  
   143      /* check for unresolved labels */
   144      for key := range self.pends {
   145          panic("labels are not fully resolved: " + key)
   146      }
   147  
   148      /* adjust jumps to point at actual instructions */
   149      for p = self.head; p != nil; p = p.Ln {
   150          if p.IsBranch() {
   151              if p.Op != OP_bsw {
   152                  self.rejmp(&p.Br)
   153              } else {
   154                  for i := int64(0); i < p.Iv * 8; i += 8 {
   155                      self.rejmp((**Ir)(unsafe.Pointer(uintptr(p.Pr) + uintptr(i))))
   156                  }
   157              }
   158          }
   159      }
   160  
   161      /* remove NOPs at the front */
   162      for self.head != nil && self.head.Op == OP_nop {
   163          self.head = self.head.Ln
   164      }
   165  
   166      /* no instructions left, the program was composed entirely by NOPs */
   167      if self.head == nil {
   168          self.tail = nil
   169          return
   170      }
   171  
   172      /* remove all the NOPs, there should be no jumps pointing to any NOPs */
   173      for p = self.head; p != nil; p, n = p.Ln, n + 1 {
   174          for p.Ln != nil && p.Ln.Op == OP_nop {
   175              q = p.Ln
   176              p.Ln = q.Ln
   177              q.Free()
   178          }
   179      }
   180  
   181      /* the Builder's life-time ends here */
   182      r.Head = self.head
   183      freeBuilder(self)
   184      return
   185  }
   186  
   187  func (self *Builder) Append(p *Ir) (r *Ir) {
   188      self.push(p)
   189      r = self.head
   190      freeBuilder(self)
   191      return
   192  }
   193  
   194  func (self *Builder) NOP() *Ir {
   195      return self.add(newInstr(OP_nop))
   196  }
   197  
   198  func (self *Builder) IB(v int8, rx GenericRegister) *Ir {
   199      return self.ADDI(Rz, int64(v), rx)
   200  }
   201  
   202  func (self *Builder) IW(v int16, rx GenericRegister) *Ir {
   203      return self.ADDI(Rz, int64(v), rx)
   204  }
   205  
   206  func (self *Builder) IL(v int32, rx GenericRegister) *Ir {
   207      return self.ADDI(Rz, int64(v), rx)
   208  }
   209  
   210  func (self *Builder) IQ(v int64, rx GenericRegister) *Ir {
   211      return self.ADDI(Rz, v, rx)
   212  }
   213  
   214  func (self *Builder) IP(v interface{}, pd PointerRegister) *Ir {
   215      if vv := rt.UnpackEface(v); !rt.IsPtr(vv.Type) {
   216          panic("v is not a pointer")
   217      } else {
   218          return self.add(newInstr(OP_ip).pr(vv.Value).pd(pd))
   219      }
   220  }
   221  
   222  func (self *Builder) LB(ps PointerRegister, disp int64, rx GenericRegister) *Ir {
   223      return self.add(newInstr(OP_lb).ps(ps).iv(disp).rx(rx))
   224  }
   225  
   226  func (self *Builder) LW(ps PointerRegister, disp int64, rx GenericRegister) *Ir {
   227      return self.add(newInstr(OP_lw).ps(ps).iv(disp).rx(rx))
   228  }
   229  
   230  func (self *Builder) LL(ps PointerRegister, disp int64, rx GenericRegister) *Ir {
   231      return self.add(newInstr(OP_ll).ps(ps).iv(disp).rx(rx))
   232  }
   233  
   234  func (self *Builder) LQ(ps PointerRegister, disp int64, rx GenericRegister) *Ir {
   235      return self.add(newInstr(OP_lq).ps(ps).iv(disp).rx(rx))
   236  }
   237  
   238  func (self *Builder) LP(ps PointerRegister, disp int64, pd PointerRegister) *Ir {
   239      return self.add(newInstr(OP_lp).ps(ps).iv(disp).pd(pd))
   240  }
   241  
   242  func (self *Builder) SB(rx GenericRegister, pd PointerRegister, disp int64) *Ir {
   243      return self.add(newInstr(OP_sb).rx(rx).pd(pd).iv(disp))
   244  }
   245  
   246  func (self *Builder) SW(rx GenericRegister, pd PointerRegister, disp int64) *Ir {
   247      return self.add(newInstr(OP_sw).rx(rx).pd(pd).iv(disp))
   248  }
   249  
   250  func (self *Builder) SL(rx GenericRegister, pd PointerRegister, disp int64) *Ir {
   251      return self.add(newInstr(OP_sl).rx(rx).pd(pd).iv(disp))
   252  }
   253  
   254  func (self *Builder) SQ(rx GenericRegister, pd PointerRegister, disp int64) *Ir {
   255      return self.add(newInstr(OP_sq).rx(rx).pd(pd).iv(disp))
   256  }
   257  
   258  func (self *Builder) SP(ps PointerRegister, pd PointerRegister, disp int64) *Ir {
   259      return self.add(newInstr(OP_sp).ps(ps).pd(pd).iv(disp))
   260  }
   261  
   262  func (self *Builder) MOV(rx GenericRegister, ry GenericRegister) *Ir {
   263      return self.ADD(rx, Rz, ry)
   264  }
   265  
   266  func (self *Builder) MOVP(ps PointerRegister, pd PointerRegister) *Ir {
   267      return self.ADDP(ps, Rz, pd)
   268  }
   269  
   270  func (self *Builder) LDAQ(id int, rx GenericRegister) *Ir {
   271      return self.add(newInstr(OP_ldaq).iv(int64(id)).rx(rx))
   272  }
   273  
   274  func (self *Builder) LDAP(id int, pd PointerRegister) *Ir {
   275      return self.add(newInstr(OP_ldap).iv(int64(id)).pd(pd))
   276  }
   277  
   278  func (self *Builder) ADDP(ps PointerRegister, rx GenericRegister, pd PointerRegister) *Ir {
   279      return self.add(newInstr(OP_addp).ps(ps).rx(rx).pd(pd))
   280  }
   281  
   282  func (self *Builder) SUBP(ps PointerRegister, rx GenericRegister, pd PointerRegister) *Ir {
   283      return self.add(newInstr(OP_subp).ps(ps).rx(rx).pd(pd))
   284  }
   285  
   286  func (self *Builder) ADDPI(ps PointerRegister, im int64, pd PointerRegister) *Ir {
   287      return self.add(newInstr(OP_addpi).ps(ps).iv(im).pd(pd))
   288  }
   289  
   290  func (self *Builder) SUBPI(ps PointerRegister, im int64, pd PointerRegister) *Ir {
   291      return self.ADDPI(ps, -im, pd)
   292  }
   293  
   294  func (self *Builder) ADD(rx GenericRegister, ry GenericRegister, rz GenericRegister) *Ir {
   295      return self.add(newInstr(OP_add).rx(rx).ry(ry).rz(rz))
   296  }
   297  
   298  func (self *Builder) SUB(rx GenericRegister, ry GenericRegister, rz GenericRegister) *Ir {
   299      return self.add(newInstr(OP_sub).rx(rx).ry(ry).rz(rz))
   300  }
   301  
   302  func (self *Builder) BTS(rx GenericRegister, ry GenericRegister, rz GenericRegister) *Ir {
   303      return self.add(newInstr(OP_bts).rx(rx).ry(ry).rz(rz))
   304  }
   305  
   306  func (self *Builder) ADDI(rx GenericRegister, im int64, ry GenericRegister) *Ir {
   307      return self.add(newInstr(OP_addi).rx(rx).iv(im).ry(ry))
   308  }
   309  
   310  func (self *Builder) SUBI(rx GenericRegister, im int64, ry GenericRegister) *Ir {
   311      return self.ADDI(rx, -im, ry)
   312  }
   313  
   314  func (self *Builder) MULI(rx GenericRegister, im int64, ry GenericRegister) *Ir {
   315      return self.add(newInstr(OP_muli).rx(rx).iv(im).ry(ry))
   316  }
   317  
   318  func (self *Builder) ANDI(rx GenericRegister, im int64, ry GenericRegister) *Ir {
   319      return self.add(newInstr(OP_andi).rx(rx).iv(im).ry(ry))
   320  }
   321  
   322  func (self *Builder) XORI(rx GenericRegister, im int64, ry GenericRegister) *Ir {
   323      return self.add(newInstr(OP_xori).rx(rx).iv(im).ry(ry))
   324  }
   325  
   326  func (self *Builder) SHRI(rx GenericRegister, im int64, ry GenericRegister) *Ir {
   327      return self.add(newInstr(OP_shri).rx(rx).iv(im).ry(ry))
   328  }
   329  
   330  func (self *Builder) BSI(rx GenericRegister, im int64, ry GenericRegister) *Ir {
   331      return self.add(newInstr(OP_bsi).rx(rx).iv(im).ry(ry))
   332  }
   333  
   334  func (self *Builder) SWAPW(rx GenericRegister, ry GenericRegister) *Ir {
   335      return self.add(newInstr(OP_swapw).rx(rx).ry(ry))
   336  }
   337  
   338  func (self *Builder) SWAPL(rx GenericRegister, ry GenericRegister) *Ir {
   339      return self.add(newInstr(OP_swapl).rx(rx).ry(ry))
   340  }
   341  
   342  func (self *Builder) SWAPQ(rx GenericRegister, ry GenericRegister) *Ir {
   343      return self.add(newInstr(OP_swapq).rx(rx).ry(ry))
   344  }
   345  
   346  func (self *Builder) SXLQ(rx GenericRegister, ry GenericRegister) *Ir {
   347      return self.add(newInstr(OP_sxlq).rx(rx).ry(ry))
   348  }
   349  
   350  func (self *Builder) BEQ(rx GenericRegister, ry GenericRegister, to string) *Ir {
   351      return self.jmp(newInstr(OP_beq).rx(rx).ry(ry), to)
   352  }
   353  
   354  func (self *Builder) BNE(rx GenericRegister, ry GenericRegister, to string) *Ir {
   355      return self.jmp(newInstr(OP_bne).rx(rx).ry(ry), to)
   356  }
   357  
   358  func (self *Builder) BLT(rx GenericRegister, ry GenericRegister, to string) *Ir {
   359      return self.jmp(newInstr(OP_blt).rx(rx).ry(ry), to)
   360  }
   361  
   362  func (self *Builder) BLTU(rx GenericRegister, ry GenericRegister, to string) *Ir {
   363      return self.jmp(newInstr(OP_bltu).rx(rx).ry(ry), to)
   364  }
   365  
   366  func (self *Builder) BGEU(rx GenericRegister, ry GenericRegister, to string) *Ir {
   367      return self.jmp(newInstr(OP_bgeu).rx(rx).ry(ry), to)
   368  }
   369  
   370  func (self *Builder) BSW(rx GenericRegister, sw []string) *Ir {
   371      return self.tab(newInstr(OP_bsw).rx(rx), sw)
   372  }
   373  
   374  func (self *Builder) BEQP(ps PointerRegister, pd PointerRegister, to string) *Ir {
   375      return self.jmp(newInstr(OP_beqp).ps(ps).pd(pd), to)
   376  }
   377  
   378  func (self *Builder) BNEP(ps PointerRegister, pd PointerRegister, to string) *Ir {
   379      return self.jmp(newInstr(OP_bnep).ps(ps).pd(pd), to)
   380  }
   381  
   382  func (self *Builder) JMP(to string) *Ir {
   383      return self.jmp(newInstr(OP_jmp), to)
   384  }
   385  
   386  func (self *Builder) BZERO(nb int64, pd PointerRegister) *Ir {
   387      return self.add(newInstr(OP_bzero).iv(nb).pd(pd))
   388  }
   389  
   390  func (self *Builder) BCOPY(ps PointerRegister, rx GenericRegister, pd PointerRegister) *Ir {
   391      return self.add(newInstr(OP_bcopy).ps(ps).rx(rx).pd(pd))
   392  }
   393  
   394  func (self *Builder) CCALL(fn *CallHandle) *Ir {
   395      return self.add(newInstr(OP_ccall).iv(int64(fn.Id)))
   396  }
   397  
   398  func (self *Builder) GCALL(fn *CallHandle) *Ir {
   399      return self.add(newInstr(OP_gcall).iv(int64(fn.Id)))
   400  }
   401  
   402  func (self *Builder) ICALL(vt PointerRegister, vp PointerRegister, mt *CallHandle) *Ir {
   403      return self.add(newInstr(OP_icall).ps(vt).pd(vp).iv(int64(mt.Id)))
   404  }
   405  
   406  func (self *Builder) RET() *Ir {
   407      return self.add(newInstr(OP_ret))
   408  }
   409  
   410  func (self *Builder) BREAK() *Ir {
   411      return self.add(newInstr(OP_break))
   412  }