-
Notifications
You must be signed in to change notification settings - Fork 10
/
instructions.go
234 lines (200 loc) · 5.97 KB
/
instructions.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
package code
// Combine encodes r1 <- op(r2, r3)
func Combine(op BinOp, r1, r2, r3 Reg) Opcode {
return mkType1(op, r1, r2, r3)
}
// Transform encodes r1 <- op(r2)
func Transform(op UnOp, r1, r2 Reg) Opcode {
return mkType4a(Off, op, r1, r2)
}
// LoadConst encodes r <- Ki
func LoadConst(r Reg, i KIndex) Opcode {
return mkType3(Off, OpK, r, i)
}
// LoadClosure encodes r <- clos(Ki)
func LoadClosure(r1 Reg, i KIndex) Opcode {
return mkType3(Off, OpClosureK, r1, i)
}
// LoadInt16 encodes r <- n
func LoadInt16(r Reg, n int16) Opcode {
return mkType3(Off, OpInt16, r, Lit16(n))
}
// LoadSmallInt attempts to load a small integer (atm it has to be representable
// as an int16).
func LoadSmallInt(r Reg, n int) (Opcode, bool) {
sn := int16(n)
if int(sn) != n {
return 0, false
}
return LoadInt16(r, sn), true
}
// LoadStr0 encodes r <- ""
func LoadStr0(r Reg) Opcode {
return mkType4b(Off, OpStr0, r, 0)
}
// LoadStr1 encodes r <- "x"
func LoadStr1(r Reg, b []byte) Opcode {
return mkType4b(Off, OpStr1, r, Lit8FromStr1(b))
}
// LoadStr2 encodes r <- "xy"
func LoadStr2(r Reg, b []byte) Opcode {
return mkType3(Off, OpStr2, r, Lit16FromStr2(b))
}
// LoadShortString attempts to encode loading a short string. Returns the
// opcode and true if it did.
func LoadShortString(r Reg, b []byte) (Opcode, bool) {
// This code is commented out because it turns out that it causes many
// allocations, slowing down the runtime considerably in some cases.
//
// switch len(b) {case 0:
// return LoadStr0(r), true
// case 1:
// return LoadStr1(r, b), true
// case 2:
// return LoadStr2(r, b), true
// }
return 0, false
}
// LoadBool encodes r <- true or r <- false.
func LoadBool(r Reg, b bool) Opcode {
return mkType4b(Off, OpBool, r, Lit8FromBool(b))
}
// LoadEmptyTable encodes r <- {}
func LoadEmptyTable(r Reg) Opcode {
return mkType4b(Off, OpTable, r, 0)
}
// LoadNil encodes r <- nil
func LoadNil(r Reg) Opcode {
return mkType4b(Off, OpNil, r, 0)
}
// LoadLookup encodes r1 <- r2[r3]
func LoadLookup(r1, r2, r3 Reg) Opcode {
return mkType2(Off, r1, r2, r3)
}
// SetIndex encodes r2[r3] <- r1
func SetIndex(r1, r2, r3 Reg) Opcode {
return mkType2(On, r1, r2, r3)
}
// Push encodes push r1, r2
//
// r1 must contain a continuation.
func Push(r1, r2 Reg) Opcode {
return mkType4a(On, OpId, r1, r2)
}
// PushEtc encodes pushetc r1, ...r2
//
// r1 must contain a continuation, r2 an etc.
func PushEtc(r1, r2 Reg) Opcode {
return mkType4a(On, OpEtcId, r1, r2)
}
// Jump encodes an unconditional jump
//
// jump j
func Jump(j Offset) Opcode {
return mkType5(Off, OpJump, Reg{}, j)
}
// JumpIf encodes a conditional jump.
//
// jump j if r
func JumpIf(j Offset, r Reg) Opcode {
return mkType5(On, OpJumpIf, r, j)
}
// JumpIfNot encodes a conditional jump.
//
// jump j if not r
func JumpIfNot(j Offset, r Reg) Opcode {
return mkType5(Off, OpJumpIf, r, j)
}
// Call encodes call r
//
// r must contain a continuation that is ready to be called.
func Call(r Reg) Opcode {
return mkType5(Off, OpCall, r, Offset(0))
}
// TailCall encodes tailcall r
//
// r must contain a continuation that is ready to be called.
func TailCall(r Reg) Opcode {
return mkType5(On, OpCall, r, Offset(0))
}
// ClTrunc encodes cltrunc h
//
// It truncates the close stack to the given height. Each value on the close
// stack which is removed should either be nil or false, or be a value with a
// "__close" metamethod, in which case this metamethod is called. This opcode
// is introduced to support Lua 5.4's "to-be-closed" variables.
func ClTrunc(h uint16) Opcode {
return mkType5(Off, OpClStack, Reg{}, ClStackOffset(h))
}
// ClPush encodes clpush r
//
// r should contain either nil, false, or a value with a "__close" metamethod.
// This opcode is introduced to support Lua 5.4's "to-be-closed" variables.
func ClPush(r Reg) Opcode {
return mkType5(On, OpClStack, r, ClStackOffset(0))
}
// Upval encodes upval r1, r2
//
// r1 must contain a closure. This appends the value of r2 to the list of
// upvalues of r1.
func Upval(r1, r2 Reg) Opcode {
return mkType4a(Off, OpUpvalue, r1, r2)
}
// Cont encodes r1 <- cont(r2)
//
// r2 must contain a closure, r1 then contains a new continuation for that
// closure, whose next continuation is the cc.
func Cont(r1, r2 Reg) Opcode {
return mkType4a(Off, OpCont, r1, r2)
}
// TailCont encodes r1 <- tailcont(r2)
//
// r2 must contain a closure, r1 then contains a new continuatino for that
// closure, whose next continuation is the cc's next continuation.
func TailCont(r1, r2 Reg) Opcode {
return mkType4a(Off, OpTailCont, r1, r2)
}
// Clear encodes clear r
//
// This clears the register. If the register contains a cell, the cell is
// removed, so this is different from r <- nil
func Clear(r Reg) Opcode {
return mkType4b(Off, OpClear, r, 0)
}
// Receive encodes recv r
//
// recv r is the pendant of push.
func Receive(r Reg) Opcode {
return mkType0(Off, r)
}
// ReceiveEtc encodes recv ...r
//
// accumulates pushes into r (as an Etc)
func ReceiveEtc(r Reg) Opcode {
return mkType0(On, r)
}
// LoadEtcLookup encodes r1 <- etclookup(r2, i)
//
// loads the (i + 1)-th element of r2 (as an etc vector) into r1.
func LoadEtcLookup(r1, r2 Reg, i int) Opcode {
return mkType6(Off, r1, r2, Index8FromInt(i))
}
// FillTable encodes fill r1, i, r2
//
// This fills the table r1 with all values from r2 (as an etc vector) starting
// from index i.
func FillTable(r1, r2 Reg, i int) Opcode {
return mkType6(On, r1, r2, Index8FromInt(i))
}
// PrepForLoop makes sure rStart, rStep, rStop are all numbers and converts
// rStart and rStep to the same numeric type. If the for loop should already
// stop then rStart is set to nil
func PrepForLoop(rStart, rStop, rStep Reg) Opcode {
return mkType7(Off, rStart, rStop, rStep)
}
// AdvForLoop increments rStart by rStep, making sure that it doesn't wrap
// around if it is an integer. If it wraps around then the loop should stop. If
// the loop should stop, rStart is set to nil
func AdvForLoop(rStart, rStop, rStep Reg) Opcode {
return mkType7(On, rStart, rStop, rStep)
}