github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/abi/abi_legacy_amd64.go (about) 1 //go:build !go1.17 2 // +build !go1.17 3 4 /* 5 * Copyright 2022 ByteDance Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 package abi 21 22 import ( 23 "fmt" 24 "reflect" 25 "runtime" 26 27 . "github.com/chenzhuoyu/iasm/x86_64" 28 ) 29 30 func ReservedRegs(callc bool) []Register { 31 return nil 32 } 33 34 func salloc(p []Parameter, sp uint32, vt reflect.Type) (uint32, []Parameter) { 35 switch vt.Kind() { 36 case reflect.Bool: 37 return sp + 8, append(p, mkStack(reflect.TypeOf(false), sp)) 38 case reflect.Int: 39 return sp + 8, append(p, mkStack(intType, sp)) 40 case reflect.Int8: 41 return sp + 8, append(p, mkStack(reflect.TypeOf(int8(0)), sp)) 42 case reflect.Int16: 43 return sp + 8, append(p, mkStack(reflect.TypeOf(int16(0)), sp)) 44 case reflect.Int32: 45 return sp + 8, append(p, mkStack(reflect.TypeOf(int32(0)), sp)) 46 case reflect.Int64: 47 return sp + 8, append(p, mkStack(reflect.TypeOf(int64(0)), sp)) 48 case reflect.Uint: 49 return sp + 8, append(p, mkStack(reflect.TypeOf(uint(0)), sp)) 50 case reflect.Uint8: 51 return sp + 8, append(p, mkStack(reflect.TypeOf(uint8(0)), sp)) 52 case reflect.Uint16: 53 return sp + 8, append(p, mkStack(reflect.TypeOf(uint16(0)), sp)) 54 case reflect.Uint32: 55 return sp + 8, append(p, mkStack(reflect.TypeOf(uint32(0)), sp)) 56 case reflect.Uint64: 57 return sp + 8, append(p, mkStack(reflect.TypeOf(uint64(0)), sp)) 58 case reflect.Uintptr: 59 return sp + 8, append(p, mkStack(reflect.TypeOf(uintptr(0)), sp)) 60 case reflect.Float32: 61 return sp + 8, append(p, mkStack(reflect.TypeOf(float32(0)), sp)) 62 case reflect.Float64: 63 return sp + 8, append(p, mkStack(reflect.TypeOf(float64(0)), sp)) 64 case reflect.Complex64: 65 panic("abi: go116: not implemented: complex64") 66 case reflect.Complex128: 67 panic("abi: go116: not implemented: complex128") 68 case reflect.Array: 69 panic("abi: go116: not implemented: arrays") 70 case reflect.Chan: 71 return sp + 8, append(p, mkStack(reflect.TypeOf((chan int)(nil)), sp)) 72 case reflect.Func: 73 return sp + 8, append(p, mkStack(reflect.TypeOf((func())(nil)), sp)) 74 case reflect.Map: 75 return sp + 8, append(p, mkStack(reflect.TypeOf((map[int]int)(nil)), sp)) 76 case reflect.Ptr: 77 return sp + 8, append(p, mkStack(reflect.TypeOf((*int)(nil)), sp)) 78 case reflect.UnsafePointer: 79 return sp + 8, append(p, mkStack(ptrType, sp)) 80 case reflect.Interface: 81 return sp + 16, append(p, mkStack(ptrType, sp), mkStack(ptrType, sp+8)) 82 case reflect.Slice: 83 return sp + 24, append(p, mkStack(ptrType, sp), mkStack(intType, sp+8), mkStack(intType, sp+16)) 84 case reflect.String: 85 return sp + 16, append(p, mkStack(ptrType, sp), mkStack(intType, sp+8)) 86 case reflect.Struct: 87 panic("abi: go116: not implemented: structs") 88 default: 89 panic("abi: invalid value type") 90 } 91 } 92 93 func NewFunctionLayout(ft reflect.Type) FunctionLayout { 94 var sp uint32 95 var fn FunctionLayout 96 97 /* assign every arguments */ 98 for i := 0; i < ft.NumIn(); i++ { 99 sp, fn.Args = salloc(fn.Args, sp, ft.In(i)) 100 } 101 102 /* assign every return value */ 103 for i := 0; i < ft.NumOut(); i++ { 104 sp, fn.Rets = salloc(fn.Rets, sp, ft.Out(i)) 105 } 106 107 /* update function ID and stack pointer */ 108 fn.FP = sp 109 return fn 110 } 111 112 func (self *Frame) emitExchangeArgs(p *Program) { 113 iregArgs, xregArgs := 0, 0 114 for _, v := range self.desc.Args { 115 if v.IsFloat != notFloatKind { 116 xregArgs += 1 117 } else { 118 iregArgs += 1 119 } 120 } 121 122 if iregArgs > len(iregOrderC) { 123 panic("too many arguments, only support at most 6 integer arguments now") 124 } 125 if xregArgs > len(xregOrderC) { 126 panic("too many arguments, only support at most 8 float arguments now") 127 } 128 129 ic, xc := iregArgs, xregArgs 130 for i := 0; i < len(self.desc.Args); i++ { 131 arg := self.desc.Args[i] 132 if arg.IsFloat == floatKind64 { 133 p.MOVSD(self.argv(i), xregOrderC[xregArgs-xc]) 134 xc -= 1 135 } else if arg.IsFloat == floatKind32 { 136 p.MOVSS(self.argv(i), xregOrderC[xregArgs-xc]) 137 xc -= 1 138 } else { 139 p.MOVQ(self.argv(i), iregOrderC[iregArgs-ic]) 140 ic -= 1 141 } 142 } 143 } 144 145 func (self *Frame) emitStackCheck(p *Program, to *Label, maxStack uintptr) { 146 // get the current goroutine 147 switch runtime.GOOS { 148 case "linux": 149 p.MOVQ(Abs(-8), R14).FS() 150 case "darwin": 151 p.MOVQ(Abs(0x30), R14).GS() 152 case "windows": 153 break // windows always stores G pointer at R14 154 default: 155 panic("unsupported operating system") 156 } 157 158 // check the stack guard 159 p.LEAQ(Ptr(RSP, -int32(self.Size()+uint32(maxStack))), RAX) 160 p.CMPQ(Ptr(R14, _G_stackguard0), RAX) 161 p.JBE(to) 162 } 163 164 func (self *Frame) StackCheckTextSize() uint32 { 165 p := DefaultArch.CreateProgram() 166 167 // get the current goroutine 168 switch runtime.GOOS { 169 case "linux": 170 p.MOVQ(Abs(-8), R14).FS() 171 case "darwin": 172 p.MOVQ(Abs(0x30), R14).GS() 173 case "windows": 174 break // windows always stores G pointer at R14 175 default: 176 panic("unsupported operating system") 177 } 178 179 // check the stack guard 180 p.LEAQ(Ptr(RSP, -int32(self.Size())), RAX) 181 p.CMPQ(Ptr(R14, _G_stackguard0), RAX) 182 l := CreateLabel("") 183 p.Link(l) 184 p.JBE(l) 185 186 return uint32(len(p.Assemble(0))) 187 } 188 189 func (self *Frame) emitExchangeRets(p *Program) { 190 if len(self.desc.Rets) > 1 { 191 panic("too many results, only support one result now") 192 } 193 // store result 194 if len(self.desc.Rets) == 1 { 195 if self.desc.Rets[0].IsFloat == floatKind64 { 196 p.MOVSD(xregOrderC[0], self.retv(0)) 197 } else if self.desc.Rets[0].IsFloat == floatKind32 { 198 p.MOVSS(xregOrderC[0], self.retv(0)) 199 } else { 200 p.MOVQ(RAX, self.retv(0)) 201 } 202 } 203 } 204 205 func (self *Frame) emitRestoreRegs(p *Program) { 206 // load reserved registers 207 for i, r := range ReservedRegs(self.ccall) { 208 switch r.(type) { 209 case Register64: 210 p.MOVQ(self.resv(i), r) 211 case XMMRegister: 212 p.MOVSD(self.resv(i), r) 213 default: 214 panic(fmt.Sprintf("unsupported register type %t to reserve", r)) 215 } 216 } 217 }