github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/abi/abi.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 abi 18 19 import ( 20 "fmt" 21 "reflect" 22 "sort" 23 "strings" 24 25 "github.com/goshafaq/sonic/internal/rt" 26 ) 27 28 type FunctionLayout struct { 29 FP uint32 30 Args []Parameter 31 Rets []Parameter 32 } 33 34 func (self FunctionLayout) String() string { 35 return self.formatFn() 36 } 37 38 func (self FunctionLayout) ArgSize() uint32 { 39 size := uintptr(0) 40 for _, arg := range self.Args { 41 size += arg.Type.Size() 42 } 43 return uint32(size) 44 } 45 46 type slot struct { 47 p bool 48 m uint32 49 } 50 51 func (self FunctionLayout) StackMap() *rt.StackMap { 52 var st []slot 53 var mb rt.StackMapBuilder 54 55 /* add arguments */ 56 for _, v := range self.Args { 57 st = append(st, slot{ 58 m: v.Mem, 59 p: v.IsPointer, 60 }) 61 } 62 63 /* add stack-passed return values */ 64 for _, v := range self.Rets { 65 if !v.InRegister { 66 st = append(st, slot{ 67 m: v.Mem, 68 p: v.IsPointer, 69 }) 70 } 71 } 72 73 /* sort by memory offset */ 74 sort.Slice(st, func(i int, j int) bool { 75 return st[i].m < st[j].m 76 }) 77 78 /* add the bits */ 79 for _, v := range st { 80 mb.AddField(v.p) 81 } 82 83 /* build the stack map */ 84 return mb.Build() 85 } 86 87 func (self FunctionLayout) formatFn() string { 88 fp := self.FP 89 return fmt.Sprintf("\n%#04x\nRets:\n%s\nArgs:\n%s", fp, self.formatSeq(self.Rets, &fp), self.formatSeq(self.Args, &fp)) 90 } 91 92 func (self FunctionLayout) formatSeq(v []Parameter, fp *uint32) string { 93 nb := len(v) 94 mm := make([]string, 0, len(v)) 95 96 /* convert each part */ 97 for i := nb - 1; i >= 0; i-- { 98 *fp -= PtrSize 99 mm = append(mm, fmt.Sprintf("%#04x %s", *fp, v[i].String())) 100 } 101 102 /* join them together */ 103 return strings.Join(mm, "\n") 104 } 105 106 type Frame struct { 107 desc *FunctionLayout 108 locals []bool 109 ccall bool 110 } 111 112 func NewFrame(desc *FunctionLayout, locals []bool, ccall bool) Frame { 113 fr := Frame{} 114 fr.desc = desc 115 fr.locals = locals 116 fr.ccall = ccall 117 return fr 118 } 119 120 func (self *Frame) String() string { 121 out := self.desc.String() 122 123 off := -8 124 out += fmt.Sprintf("\n%#4x [Return PC]", off) 125 off -= 8 126 out += fmt.Sprintf("\n%#4x [RBP]", off) 127 off -= 8 128 129 for _, v := range ReservedRegs(self.ccall) { 130 out += fmt.Sprintf("\n%#4x [%v]", off, v) 131 off -= PtrSize 132 } 133 134 for _, b := range self.locals { 135 out += fmt.Sprintf("\n%#4x [%v]", off, b) 136 off -= PtrSize 137 } 138 139 return out 140 } 141 142 func (self *Frame) Prev() uint32 { 143 return self.Size() + PtrSize 144 } 145 146 func (self *Frame) Size() uint32 { 147 return uint32(self.Offs() + PtrSize) 148 } 149 150 func (self *Frame) Offs() uint32 { 151 return uint32(len(ReservedRegs(self.ccall))*PtrSize + len(self.locals)*PtrSize) 152 } 153 154 func (self *Frame) ArgPtrs() *rt.StackMap { 155 return self.desc.StackMap() 156 } 157 158 func (self *Frame) LocalPtrs() *rt.StackMap { 159 var m rt.StackMapBuilder 160 for _, b := range self.locals { 161 m.AddFields(len(ReservedRegs(self.ccall)), b) 162 } 163 return m.Build() 164 } 165 166 func alignUp(n uint32, a int) uint32 { 167 return (uint32(n) + uint32(a) - 1) &^ (uint32(a) - 1) 168 } 169 170 func isPointer(vt reflect.Type) bool { 171 switch vt.Kind() { 172 case reflect.Bool: 173 fallthrough 174 case reflect.Int: 175 fallthrough 176 case reflect.Int8: 177 fallthrough 178 case reflect.Int16: 179 fallthrough 180 case reflect.Int32: 181 fallthrough 182 case reflect.Int64: 183 fallthrough 184 case reflect.Uint: 185 fallthrough 186 case reflect.Uint8: 187 fallthrough 188 case reflect.Uint16: 189 fallthrough 190 case reflect.Uint32: 191 fallthrough 192 case reflect.Uint64: 193 fallthrough 194 case reflect.Float32: 195 fallthrough 196 case reflect.Float64: 197 fallthrough 198 case reflect.Uintptr: 199 return false 200 case reflect.Chan: 201 fallthrough 202 case reflect.Func: 203 fallthrough 204 case reflect.Map: 205 fallthrough 206 case reflect.Ptr: 207 fallthrough 208 case reflect.UnsafePointer: 209 return true 210 case reflect.Complex64: 211 fallthrough 212 case reflect.Complex128: 213 fallthrough 214 case reflect.Array: 215 fallthrough 216 case reflect.Struct: 217 panic("abi: unsupported types") 218 default: 219 panic("abi: invalid value type") 220 } 221 }