podman

Форк
0
282 строки · 6.6 Кб
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
    `unsafe`
23

24
    . `github.com/chenzhuoyu/iasm/x86_64`
25
)
26

27
const (
28
    PtrSize  = 8    // pointer size
29
    PtrAlign = 8    // pointer alignment
30
)
31

32
var iregOrderC = []Register{
33
    RDI, 
34
    RSI, 
35
    RDX, 
36
    RCX,
37
    R8, 
38
    R9,
39
}
40

41
var xregOrderC = []Register{
42
    XMM0,
43
    XMM1,
44
    XMM2,
45
    XMM3,
46
    XMM4,
47
    XMM5,
48
    XMM6,
49
    XMM7,
50
}
51

52
var (
53
    intType = reflect.TypeOf(0)
54
    ptrType = reflect.TypeOf(unsafe.Pointer(nil))
55
)
56

57
func (self *Frame) argv(i int) *MemoryOperand {
58
    return Ptr(RSP, int32(self.Prev() + self.desc.Args[i].Mem))
59
}
60

61
// spillv is used for growstack spill registers
62
func (self *Frame) spillv(i int) *MemoryOperand {
63
    // remain one slot for caller return pc
64
    return Ptr(RSP, PtrSize + int32(self.desc.Args[i].Mem))
65
}
66

67
func (self *Frame) retv(i int) *MemoryOperand {
68
    return Ptr(RSP, int32(self.Prev() + self.desc.Rets[i].Mem))
69
}
70

71
func (self *Frame) resv(i int) *MemoryOperand {
72
    return Ptr(RSP, int32(self.Offs() - uint32((i+1) * PtrSize)))
73
}
74

75
func (self *Frame) emitGrowStack(p *Program, entry *Label) {
76
    // spill all register arguments
77
    for i, v := range self.desc.Args {
78
        if v.InRegister {
79
            if v.IsFloat == floatKind64 {
80
                p.MOVSD(v.Reg, self.spillv(i))
81
            } else if v.IsFloat == floatKind32 {
82
                p.MOVSS(v.Reg, self.spillv(i))
83
            }else {
84
                p.MOVQ(v.Reg, self.spillv(i))
85
            }
86
        }
87
    }
88

89
    // call runtime.morestack_noctxt
90
    p.MOVQ(F_morestack_noctxt, R12)
91
    p.CALLQ(R12)
92
    // load all register arguments
93
    for i, v := range self.desc.Args {
94
        if v.InRegister {
95
            if v.IsFloat == floatKind64 {
96
                p.MOVSD(self.spillv(i), v.Reg)
97
            } else if v.IsFloat == floatKind32 {
98
                p.MOVSS(self.spillv(i), v.Reg)
99
            }else {
100
                p.MOVQ(self.spillv(i), v.Reg)
101
            }
102
        }
103
    }
104

105
    // jump back to the function entry
106
    p.JMP(entry)
107
}
108

109
func (self *Frame) GrowStackTextSize() uint32 {
110
    p := DefaultArch.CreateProgram()
111
    // spill all register arguments
112
    for i, v := range self.desc.Args {
113
        if v.InRegister {
114
            if v.IsFloat == floatKind64 {
115
                p.MOVSD(v.Reg, self.spillv(i))
116
            } else if v.IsFloat == floatKind32 {
117
                p.MOVSS(v.Reg, self.spillv(i))
118
            }else {
119
                p.MOVQ(v.Reg, self.spillv(i))
120
            }
121
        }
122
    }
123

124
    // call runtime.morestack_noctxt
125
    p.MOVQ(F_morestack_noctxt, R12)
126
    p.CALLQ(R12)
127
    // load all register arguments
128
    for i, v := range self.desc.Args {
129
        if v.InRegister {
130
            if v.IsFloat == floatKind64 {
131
                p.MOVSD(self.spillv(i), v.Reg)
132
            } else if v.IsFloat == floatKind32 {
133
                p.MOVSS(self.spillv(i), v.Reg)
134
            } else {
135
                p.MOVQ(self.spillv(i), v.Reg)
136
            }
137
        }
138
    }
139

140
    // jump back to the function entry
141
    l := CreateLabel("")
142
    p.Link(l)
143
    p.JMP(l)
144

145
    return uint32(len(p.Assemble(0)))
146
}
147

148
func (self *Frame) emitPrologue(p *Program) {
149
    p.SUBQ(self.Size(), RSP)
150
    p.MOVQ(RBP, Ptr(RSP, int32(self.Offs())))
151
    p.LEAQ(Ptr(RSP, int32(self.Offs())), RBP)
152
}
153

154
func (self *Frame) emitEpilogue(p *Program) {
155
    p.MOVQ(Ptr(RSP, int32(self.Offs())), RBP)
156
    p.ADDQ(self.Size(), RSP)
157
    p.RET()
158
}
159

160
func (self *Frame) emitReserveRegs(p *Program) {
161
    // spill reserved registers
162
    for i, r := range ReservedRegs(self.ccall) {
163
        switch r.(type) {
164
        case Register64:
165
            p.MOVQ(r, self.resv(i))
166
        case XMMRegister:
167
            p.MOVSD(r, self.resv(i))
168
        default:
169
            panic(fmt.Sprintf("unsupported register type %t to reserve", r))
170
        }
171
    }
172
}
173

174
func (self *Frame) emitSpillPtrs(p *Program) {
175
    // spill pointer argument registers
176
    for i, r := range self.desc.Args {
177
        if r.InRegister && r.IsPointer {
178
            p.MOVQ(r.Reg, self.argv(i))
179
        }
180
    }
181
}
182

183
func (self *Frame) emitClearPtrs(p *Program) {
184
    // spill pointer argument registers
185
    for i, r := range self.desc.Args {
186
        if r.InRegister && r.IsPointer {
187
            p.MOVQ(int64(0), self.argv(i))
188
        }
189
    }
190
}
191

192
func (self *Frame) emitCallC(p *Program, addr uintptr) {
193
    p.MOVQ(addr, RAX)
194
    p.CALLQ(RAX)
195
}
196

197
type floatKind uint8
198

199
const (
200
    notFloatKind floatKind = iota
201
    floatKind32
202
    floatKind64
203
)
204

205
type Parameter struct {
206
    InRegister bool
207
    IsPointer  bool
208
    IsFloat    floatKind
209
    Reg        Register
210
    Mem        uint32
211
    Type       reflect.Type
212
}
213

214
func mkIReg(vt reflect.Type, reg Register64) (p Parameter) {
215
    p.Reg = reg
216
    p.Type = vt
217
    p.InRegister = true
218
    p.IsPointer = isPointer(vt)
219
    return
220
}
221

222
func isFloat(vt reflect.Type) floatKind {
223
    switch vt.Kind() {
224
    case reflect.Float32:
225
        return floatKind32
226
    case reflect.Float64:
227
        return floatKind64
228
    default:
229
        return notFloatKind
230
    }
231
}
232

233
func mkXReg(vt reflect.Type, reg XMMRegister) (p Parameter) {
234
    p.Reg = reg
235
    p.Type = vt
236
    p.InRegister = true
237
    p.IsFloat = isFloat(vt)
238
    return
239
}
240

241
func mkStack(vt reflect.Type, mem uint32) (p Parameter) {
242
    p.Mem = mem
243
    p.Type = vt
244
    p.InRegister = false
245
    p.IsPointer = isPointer(vt)
246
    p.IsFloat = isFloat(vt)
247
    return
248
}
249

250
func (self Parameter) String() string {
251
    if self.InRegister {
252
        return fmt.Sprintf("[%%%s, Pointer(%v), Float(%v)]", self.Reg, self.IsPointer, self.IsFloat)
253
    } else {
254
        return fmt.Sprintf("[%d(FP), Pointer(%v), Float(%v)]", self.Mem, self.IsPointer, self.IsFloat)
255
    }
256
}
257

258
func CallC(addr uintptr, fr Frame, maxStack uintptr) []byte {
259
    p := DefaultArch.CreateProgram()
260

261
    stack := CreateLabel("_stack_grow")
262
    entry := CreateLabel("_entry")
263
    p.Link(entry)
264
    fr.emitStackCheck(p, stack, maxStack)
265
    fr.emitPrologue(p)
266
    fr.emitReserveRegs(p)
267
    fr.emitSpillPtrs(p)
268
    fr.emitExchangeArgs(p)
269
    fr.emitCallC(p, addr)
270
    fr.emitExchangeRets(p)
271
    fr.emitRestoreRegs(p)
272
    fr.emitEpilogue(p)
273
    p.Link(stack)
274
    fr.emitGrowStack(p, entry)
275

276
    return p.Assemble(0)
277
}
278

279

280
func (self *Frame) emitDebug(p *Program) {
281
    p.INT(3)
282
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.