-
Notifications
You must be signed in to change notification settings - Fork 16
/
func.go
112 lines (92 loc) · 2.76 KB
/
func.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright (c) 2016 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gen
import (
"gate.computer/wag/internal/gen/debug"
"gate.computer/wag/internal/gen/link"
"gate.computer/wag/internal/gen/operand"
"gate.computer/wag/internal/gen/reg"
"gate.computer/wag/internal/gen/regalloc"
"gate.computer/wag/internal/gen/storage"
"gate.computer/wag/internal/obj"
"gate.computer/wag/wa"
errors "golang.org/x/xerrors"
)
type Block struct {
Suspension bool
WeakDead bool // Like deadend state, but must not affect portable ABI.
}
type BranchTarget struct {
Label link.L
StackDepth int
ValueType wa.Type
FuncEnd bool
Block Block
}
type BranchTable struct {
Addr int32
Targets []*BranchTarget
StackDepth int // -1 indicates common depth among all targets
}
type Func struct {
Prog // Initialized by GenProgram, preserved by GenFunction
Regs regalloc.Allocator
ResultType wa.Type
LocalTypes []wa.Type
NumParams int
NumLocals int // The non-param ones
Operands []operand.O
FrameBase int // Number of (stack) operands belonging to parent blocks
NumStableOperands int
StackDepth int // The dynamic entries after locals
MaxStackDepth int
BranchTargets []*BranchTarget
BranchTables []BranchTable
AtomicCallStubs bool
}
func (f *Func) LocalOffset(index int) int32 {
// Params are in behind function link address slot
n := f.StackDepth + f.NumLocals + f.NumParams - index
if index >= f.NumParams {
// Other locals are on this side of function link address slot
n--
}
if n < 0 {
panic(errors.New("effective stack offset of local variable #%d is negative"))
}
return int32(n * obj.Word)
}
// StackValueConsumed updates the virtual stack pointer on behalf of
// MacroAssembler when it changes the physical stack pointer.
func (f *Func) StackValueConsumed() {
f.StackDepth--
if debug.Enabled {
debug.Printf("stack depth: %d (pop 1)", f.StackDepth)
}
}
// ValueBecameUnreachable keeps the state consistent when an operand will not
// be operated on (because it was popped on an unreachable code path).
func (f *Func) ValueBecameUnreachable(x operand.O) {
switch x.Storage {
case storage.Stack:
f.StackValueConsumed()
case storage.Reg:
if x.Reg() != reg.Result {
f.Regs.Free(x.Type, x.Reg())
}
}
}
func (f *Func) MapCallAddr(retAddr int32) {
f.Map.PutCallSite(uint32(retAddr), f.mapStackUsage())
f.LastCallAddr = retAddr // Needed only by arm backend.
}
func (f *Func) MapTrapAddr(retAddr int32) {
if f.DebugMap != nil {
f.DebugMap.PutTrapSite(uint32(retAddr), f.mapStackUsage())
}
}
func (f *Func) mapStackUsage() int32 {
// Add one entry for link address.
return int32((f.NumLocals + f.StackDepth + 1) * obj.Word)
}