...

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

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

     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          : return sp + 8, append(p, mkStack(reflect.TypeOf(false), sp))
    37          case reflect.Int           : return sp + 8, append(p, mkStack(intType, sp))
    38          case reflect.Int8          : return sp + 8, append(p, mkStack(reflect.TypeOf(int8(0)), sp))
    39          case reflect.Int16         : return sp + 8, append(p, mkStack(reflect.TypeOf(int16(0)), sp))
    40          case reflect.Int32         : return sp + 8, append(p, mkStack(reflect.TypeOf(int32(0)), sp))
    41          case reflect.Int64         : return sp + 8, append(p, mkStack(reflect.TypeOf(int64(0)), sp))
    42          case reflect.Uint          : return sp + 8, append(p, mkStack(reflect.TypeOf(uint(0)), sp))
    43          case reflect.Uint8         : return sp + 8, append(p, mkStack(reflect.TypeOf(uint8(0)), sp))
    44          case reflect.Uint16        : return sp + 8, append(p, mkStack(reflect.TypeOf(uint16(0)), sp))
    45          case reflect.Uint32        : return sp + 8, append(p, mkStack(reflect.TypeOf(uint32(0)), sp))
    46          case reflect.Uint64        : return sp + 8, append(p, mkStack(reflect.TypeOf(uint64(0)), sp))
    47          case reflect.Uintptr       : return sp + 8, append(p, mkStack(reflect.TypeOf(uintptr(0)), sp))
    48          case reflect.Float32       : return sp + 8, append(p, mkStack(reflect.TypeOf(float32(0)), sp))
    49          case reflect.Float64       : return sp + 8, append(p, mkStack(reflect.TypeOf(float64(0)), sp))
    50          case reflect.Complex64     : panic("abi: go116: not implemented: complex64")
    51          case reflect.Complex128    : panic("abi: go116: not implemented: complex128")
    52          case reflect.Array         : panic("abi: go116: not implemented: arrays")
    53          case reflect.Chan          : return sp +  8, append(p, mkStack(reflect.TypeOf((chan int)(nil)), sp))
    54          case reflect.Func          : return sp +  8, append(p, mkStack(reflect.TypeOf((func())(nil)), sp))
    55          case reflect.Map           : return sp +  8, append(p, mkStack(reflect.TypeOf((map[int]int)(nil)), sp))
    56          case reflect.Ptr           : return sp +  8, append(p, mkStack(reflect.TypeOf((*int)(nil)), sp))
    57          case reflect.UnsafePointer : return sp +  8, append(p, mkStack(ptrType, sp))
    58          case reflect.Interface     : return sp + 16, append(p, mkStack(ptrType, sp), mkStack(ptrType, sp + 8))
    59          case reflect.Slice         : return sp + 24, append(p, mkStack(ptrType, sp), mkStack(intType, sp + 8), mkStack(intType, sp + 16))
    60          case reflect.String        : return sp + 16, append(p, mkStack(ptrType, sp), mkStack(intType, sp + 8))
    61          case reflect.Struct        : panic("abi: go116: not implemented: structs")
    62          default                    : panic("abi: invalid value type")
    63      }
    64  }
    65  
    66  func NewFunctionLayout(ft reflect.Type) FunctionLayout {
    67      var sp uint32
    68      var fn FunctionLayout
    69  
    70      /* assign every arguments */
    71      for i := 0; i < ft.NumIn(); i++ {
    72          sp, fn.Args = salloc(fn.Args, sp, ft.In(i))
    73      }
    74  
    75      /* assign every return value */
    76      for i := 0; i < ft.NumOut(); i++ {
    77          sp, fn.Rets = salloc(fn.Rets, sp, ft.Out(i))
    78      }
    79  
    80      /* update function ID and stack pointer */
    81      fn.FP = sp
    82      return fn
    83  }
    84  
    85  func (self *Frame) emitExchangeArgs(p *Program) {
    86      iregArgs, xregArgs := 0, 0
    87      for _, v := range self.desc.Args {
    88          if v.IsFloat != notFloatKind {
    89              xregArgs += 1
    90          } else {
    91              iregArgs += 1
    92          }
    93      }
    94  
    95      if iregArgs > len(iregOrderC) {
    96          panic("too many arguments, only support at most 6 integer arguments now")
    97      }
    98      if xregArgs > len(xregOrderC) {
    99          panic("too many arguments, only support at most 8 float arguments now")
   100      }
   101  
   102      ic, xc := iregArgs, xregArgs
   103      for i := 0; i < len(self.desc.Args); i++ {
   104          arg := self.desc.Args[i]
   105          if arg.IsFloat == floatKind64 {
   106              p.MOVSD(self.argv(i), xregOrderC[xregArgs - xc])
   107              xc -= 1 
   108          } else if arg.IsFloat == floatKind32 {
   109              p.MOVSS(self.argv(i), xregOrderC[xregArgs - xc])
   110              xc -= 1 
   111          } else {
   112              p.MOVQ(self.argv(i), iregOrderC[iregArgs - ic])
   113              ic -= 1
   114          }
   115      }
   116  }
   117  
   118  func (self *Frame) emitStackCheck(p *Program, to *Label, maxStack uintptr) {
   119      // get the current goroutine
   120      switch runtime.GOOS {
   121          case "linux"  : p.MOVQ(Abs(-8), R14).FS()
   122          case "darwin" : p.MOVQ(Abs(0x30), R14).GS()
   123          case "windows": break // windows always stores G pointer at R14 
   124          default       : panic("unsupported operating system")
   125      }
   126      
   127      // check the stack guard
   128      p.LEAQ(Ptr(RSP, -int32(self.Size() + uint32(maxStack))), RAX)
   129      p.CMPQ(Ptr(R14, _G_stackguard0), RAX)
   130      p.JBE(to)
   131  }
   132  
   133  func (self *Frame) StackCheckTextSize() uint32 {
   134      p := DefaultArch.CreateProgram()
   135  
   136      // get the current goroutine
   137      switch runtime.GOOS {
   138          case "linux"  : p.MOVQ(Abs(-8), R14).FS()
   139          case "darwin" : p.MOVQ(Abs(0x30), R14).GS()
   140          case "windows": break // windows always stores G pointer at R14 
   141          default       : panic("unsupported operating system")
   142      }
   143      
   144      // check the stack guard
   145      p.LEAQ(Ptr(RSP, -int32(self.Size())), RAX)
   146      p.CMPQ(Ptr(R14, _G_stackguard0), RAX)
   147      l := CreateLabel("")
   148      p.Link(l)
   149      p.JBE(l)
   150  
   151      return uint32(len(p.Assemble(0)))
   152  }
   153  
   154  func (self *Frame) emitExchangeRets(p *Program) {
   155      if len(self.desc.Rets) > 1 {
   156          panic("too many results, only support one result now")
   157      }    
   158      // store result
   159      if len(self.desc.Rets) ==1 {
   160          if self.desc.Rets[0].IsFloat == floatKind64 {
   161              p.MOVSD(xregOrderC[0], self.retv(0))
   162          } else if self.desc.Rets[0].IsFloat == floatKind32 {
   163              p.MOVSS(xregOrderC[0], self.retv(0))
   164          } else {
   165              p.MOVQ(RAX, self.retv(0))
   166          }
   167      }
   168  }
   169  
   170  func (self *Frame) emitRestoreRegs(p *Program) {
   171      // load reserved registers
   172      for i, r := range ReservedRegs(self.ccall) {
   173          switch r.(type) {
   174          case Register64:
   175              p.MOVQ(self.resv(i), r)
   176          case XMMRegister:
   177              p.MOVSD(self.resv(i), r)
   178          default:
   179              panic(fmt.Sprintf("unsupported register type %t to reserve", r))
   180          }
   181      }
   182  }

View as plain text