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