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 }