github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/abi/abi_legacy_amd64.go (about)

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