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  }