...

Source file src/github.com/bytedance/sonic/internal/abi/abi.go

Documentation: github.com/bytedance/sonic/internal/abi

     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/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  }

View as plain text