abi.go raw

   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/bytedance/sonic/loader/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          : fallthrough
 173          case reflect.Int           : fallthrough
 174          case reflect.Int8          : fallthrough
 175          case reflect.Int16         : fallthrough
 176          case reflect.Int32         : fallthrough
 177          case reflect.Int64         : fallthrough
 178          case reflect.Uint          : fallthrough
 179          case reflect.Uint8         : fallthrough
 180          case reflect.Uint16        : fallthrough
 181          case reflect.Uint32        : fallthrough
 182          case reflect.Uint64        : fallthrough
 183          case reflect.Float32       : fallthrough
 184          case reflect.Float64       : fallthrough
 185          case reflect.Uintptr       : return false
 186          case reflect.Chan          : fallthrough
 187          case reflect.Func          : fallthrough
 188          case reflect.Map           : fallthrough
 189          case reflect.Ptr           : fallthrough
 190          case reflect.UnsafePointer : return true
 191          case reflect.Complex64     : fallthrough
 192          case reflect.Complex128    : fallthrough
 193          case reflect.Array         : fallthrough
 194          case reflect.Struct        : panic("abi: unsupported types")
 195          default                    : panic("abi: invalid value type")
 196      }
 197  }