abi_legacy_amd64.go raw

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