github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/jit/backend.go (about)

     1  /*
     2   * Copyright 2021 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 jit
    18  
    19  import (
    20      `fmt`
    21      `sync`
    22      _ `unsafe`
    23  
    24      `github.com/twitchyliquid64/golang-asm/asm/arch`
    25      `github.com/twitchyliquid64/golang-asm/obj`
    26      `github.com/twitchyliquid64/golang-asm/objabi`
    27  )
    28  
    29  type Backend struct {
    30      Ctxt *obj.Link
    31      Arch *arch.Arch
    32      Head *obj.Prog
    33      Tail *obj.Prog
    34      Prog []*obj.Prog
    35  }
    36  
    37  var (
    38      _progPool sync.Pool
    39  )
    40  
    41  //go:nosplit
    42  //go:linkname throw runtime.throw
    43  func throw(_ string)
    44  
    45  func newProg() *obj.Prog {
    46      if val := _progPool.Get(); val == nil {
    47          return new(obj.Prog)
    48      } else {
    49          return remProg(val.(*obj.Prog))
    50      }
    51  }
    52  
    53  func remProg(p *obj.Prog) *obj.Prog {
    54      *p = obj.Prog{}
    55      return p
    56  }
    57  
    58  func newBackend(name string) (ret *Backend) {
    59      ret      = new(Backend)
    60      ret.Arch = arch.Set(name)
    61      ret.Ctxt = newLinkContext(ret.Arch.LinkArch)
    62      ret.Arch.Init(ret.Ctxt)
    63      return
    64  }
    65  
    66  func newLinkContext(arch *obj.LinkArch) (ret *obj.Link) {
    67      ret          = obj.Linknew(arch)
    68      ret.Headtype = objabi.Hlinux
    69      ret.DiagFunc = diagLinkContext
    70      return
    71  }
    72  
    73  func diagLinkContext(str string, args ...interface{}) {
    74      throw(fmt.Sprintf(str, args...))
    75  }
    76  
    77  func (self *Backend) New() (ret *obj.Prog) {
    78      ret = newProg()
    79      ret.Ctxt = self.Ctxt
    80      self.Prog = append(self.Prog, ret)
    81      return
    82  }
    83  
    84  func (self *Backend) Append(p *obj.Prog) {
    85      if self.Head == nil {
    86          self.Head = p
    87          self.Tail = p
    88      } else {
    89          self.Tail.Link = p
    90          self.Tail = p
    91      }
    92  }
    93  
    94  func (self *Backend) Release() {
    95      self.Arch = nil
    96      self.Ctxt = nil
    97  
    98      /* return all the progs into pool */
    99      for _, p := range self.Prog {
   100          _progPool.Put(p)
   101      }
   102  
   103      /* clear all the references */
   104      self.Head = nil
   105      self.Tail = nil
   106      self.Prog = nil
   107  }
   108  
   109  func (self *Backend) Assemble() []byte {
   110      var sym obj.LSym
   111      var fnv obj.FuncInfo
   112  
   113      /* construct the function */
   114      sym.Func = &fnv
   115      fnv.Text = self.Head
   116  
   117      /* call the assembler */
   118      self.Arch.Assemble(self.Ctxt, &sym, self.New)
   119      return sym.P
   120  }