github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/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  }