| @@ -1,1876 +1,1880 @@ | | | @@ -1,1876 +1,1880 @@ |
1 | /* $NetBSD: lcode.c,v 1.12 2023/04/16 20:46:17 nikita Exp $ */ | | 1 | /* $NetBSD: lcode.c,v 1.13 2023/04/17 19:19:00 nikita Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | ** Id: lcode.c | | 4 | ** Id: lcode.c |
5 | ** Code generator for Lua | | 5 | ** Code generator for Lua |
6 | ** See Copyright Notice in lua.h | | 6 | ** See Copyright Notice in lua.h |
7 | */ | | 7 | */ |
8 | | | 8 | |
9 | #define lcode_c | | 9 | #define lcode_c |
10 | #define LUA_CORE | | 10 | #define LUA_CORE |
11 | | | 11 | |
12 | #include "lprefix.h" | | 12 | #include "lprefix.h" |
13 | | | 13 | |
14 | | | 14 | |
15 | #ifndef _KERNEL | | 15 | #ifndef _KERNEL |
16 | #include <float.h> | | 16 | #include <float.h> |
17 | #include <limits.h> | | 17 | #include <limits.h> |
18 | #include <math.h> | | 18 | #include <math.h> |
19 | #include <stdlib.h> | | 19 | #include <stdlib.h> |
20 | #endif /* _KERNEL */ | | 20 | #endif /* _KERNEL */ |
21 | | | 21 | |
22 | #include "lua.h" | | 22 | #include "lua.h" |
23 | | | 23 | |
24 | #include "lcode.h" | | 24 | #include "lcode.h" |
25 | #include "ldebug.h" | | 25 | #include "ldebug.h" |
26 | #include "ldo.h" | | 26 | #include "ldo.h" |
27 | #include "lgc.h" | | 27 | #include "lgc.h" |
28 | #include "llex.h" | | 28 | #include "llex.h" |
29 | #include "lmem.h" | | 29 | #include "lmem.h" |
30 | #include "lobject.h" | | 30 | #include "lobject.h" |
31 | #include "lopcodes.h" | | 31 | #include "lopcodes.h" |
32 | #include "lparser.h" | | 32 | #include "lparser.h" |
33 | #include "lstring.h" | | 33 | #include "lstring.h" |
34 | #include "ltable.h" | | 34 | #include "ltable.h" |
35 | #include "lvm.h" | | 35 | #include "lvm.h" |
36 | | | 36 | |
37 | | | 37 | |
38 | /* Maximum number of registers in a Lua function (must fit in 8 bits) */ | | 38 | /* Maximum number of registers in a Lua function (must fit in 8 bits) */ |
39 | #define MAXREGS 255 | | 39 | #define MAXREGS 255 |
40 | | | 40 | |
41 | | | 41 | |
42 | #define hasjumps(e) ((e)->t != (e)->f) | | 42 | #define hasjumps(e) ((e)->t != (e)->f) |
43 | | | 43 | |
44 | | | 44 | |
45 | static int codesJ (FuncState *fs, OpCode o, int sj, int k); | | 45 | static int codesJ (FuncState *fs, OpCode o, int sj, int k); |
46 | | | 46 | |
47 | | | 47 | |
48 | | | 48 | |
49 | /* semantic error */ | | 49 | /* semantic error */ |
50 | l_noret luaK_semerror (LexState *ls, const char *msg) { | | 50 | l_noret luaK_semerror (LexState *ls, const char *msg) { |
51 | ls->t.token = 0; /* remove "near <token>" from final message */ | | 51 | ls->t.token = 0; /* remove "near <token>" from final message */ |
52 | luaX_syntaxerror(ls, msg); | | 52 | luaX_syntaxerror(ls, msg); |
53 | } | | 53 | } |
54 | | | 54 | |
55 | | | 55 | |
56 | /* | | 56 | /* |
57 | ** If expression is a numeric constant, fills 'v' with its value | | 57 | ** If expression is a numeric constant, fills 'v' with its value |
58 | ** and returns 1. Otherwise, returns 0. | | 58 | ** and returns 1. Otherwise, returns 0. |
59 | */ | | 59 | */ |
60 | static int tonumeral (const expdesc *e, TValue *v) { | | 60 | static int tonumeral (const expdesc *e, TValue *v) { |
61 | if (hasjumps(e)) | | 61 | if (hasjumps(e)) |
62 | return 0; /* not a numeral */ | | 62 | return 0; /* not a numeral */ |
63 | switch (e->k) { | | 63 | switch (e->k) { |
64 | case VKINT: | | 64 | case VKINT: |
65 | if (v) setivalue(v, e->u.ival); | | 65 | if (v) setivalue(v, e->u.ival); |
66 | return 1; | | 66 | return 1; |
67 | #ifndef _KERNEL | | 67 | #ifndef _KERNEL |
68 | case VKFLT: | | 68 | case VKFLT: |
69 | if (v) setfltvalue(v, e->u.nval); | | 69 | if (v) setfltvalue(v, e->u.nval); |
70 | return 1; | | 70 | return 1; |
71 | #endif /* _KERNEL */ | | 71 | #endif /* _KERNEL */ |
72 | default: return 0; | | 72 | default: return 0; |
73 | } | | 73 | } |
74 | } | | 74 | } |
75 | | | 75 | |
76 | | | 76 | |
77 | /* | | 77 | /* |
78 | ** Get the constant value from a constant expression | | 78 | ** Get the constant value from a constant expression |
79 | */ | | 79 | */ |
80 | static TValue *const2val (FuncState *fs, const expdesc *e) { | | 80 | static TValue *const2val (FuncState *fs, const expdesc *e) { |
81 | lua_assert(e->k == VCONST); | | 81 | lua_assert(e->k == VCONST); |
82 | return &fs->ls->dyd->actvar.arr[e->u.info].k; | | 82 | return &fs->ls->dyd->actvar.arr[e->u.info].k; |
83 | } | | 83 | } |
84 | | | 84 | |
85 | | | 85 | |
86 | /* | | 86 | /* |
87 | ** If expression is a constant, fills 'v' with its value | | 87 | ** If expression is a constant, fills 'v' with its value |
88 | ** and returns 1. Otherwise, returns 0. | | 88 | ** and returns 1. Otherwise, returns 0. |
89 | */ | | 89 | */ |
90 | int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v) { | | 90 | int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v) { |
91 | if (hasjumps(e)) | | 91 | if (hasjumps(e)) |
92 | return 0; /* not a constant */ | | 92 | return 0; /* not a constant */ |
93 | switch (e->k) { | | 93 | switch (e->k) { |
94 | case VFALSE: | | 94 | case VFALSE: |
95 | setbfvalue(v); | | 95 | setbfvalue(v); |
96 | return 1; | | 96 | return 1; |
97 | case VTRUE: | | 97 | case VTRUE: |
98 | setbtvalue(v); | | 98 | setbtvalue(v); |
99 | return 1; | | 99 | return 1; |
100 | case VNIL: | | 100 | case VNIL: |
101 | setnilvalue(v); | | 101 | setnilvalue(v); |
102 | return 1; | | 102 | return 1; |
103 | case VKSTR: { | | 103 | case VKSTR: { |
104 | setsvalue(fs->ls->L, v, e->u.strval); | | 104 | setsvalue(fs->ls->L, v, e->u.strval); |
105 | return 1; | | 105 | return 1; |
106 | } | | 106 | } |
107 | case VCONST: { | | 107 | case VCONST: { |
108 | setobj(fs->ls->L, v, const2val(fs, e)); | | 108 | setobj(fs->ls->L, v, const2val(fs, e)); |
109 | return 1; | | 109 | return 1; |
110 | } | | 110 | } |
111 | default: return tonumeral(e, v); | | 111 | default: return tonumeral(e, v); |
112 | } | | 112 | } |
113 | } | | 113 | } |
114 | | | 114 | |
115 | | | 115 | |
116 | /* | | 116 | /* |
117 | ** Return the previous instruction of the current code. If there | | 117 | ** Return the previous instruction of the current code. If there |
118 | ** may be a jump target between the current instruction and the | | 118 | ** may be a jump target between the current instruction and the |
119 | ** previous one, return an invalid instruction (to avoid wrong | | 119 | ** previous one, return an invalid instruction (to avoid wrong |
120 | ** optimizations). | | 120 | ** optimizations). |
121 | */ | | 121 | */ |
122 | static Instruction *previousinstruction (FuncState *fs) { | | 122 | static Instruction *previousinstruction (FuncState *fs) { |
123 | static const Instruction invalidinstruction = ~(Instruction)0; | | 123 | static const Instruction invalidinstruction = ~(Instruction)0; |
124 | if (fs->pc > fs->lasttarget) | | 124 | if (fs->pc > fs->lasttarget) |
125 | return &fs->f->code[fs->pc - 1]; /* previous instruction */ | | 125 | return &fs->f->code[fs->pc - 1]; /* previous instruction */ |
126 | else | | 126 | else |
127 | return cast(Instruction*, &invalidinstruction); | | 127 | return cast(Instruction*, &invalidinstruction); |
128 | } | | 128 | } |
129 | | | 129 | |
130 | | | 130 | |
131 | /* | | 131 | /* |
132 | ** Create a OP_LOADNIL instruction, but try to optimize: if the previous | | 132 | ** Create a OP_LOADNIL instruction, but try to optimize: if the previous |
133 | ** instruction is also OP_LOADNIL and ranges are compatible, adjust | | 133 | ** instruction is also OP_LOADNIL and ranges are compatible, adjust |
134 | ** range of previous instruction instead of emitting a new one. (For | | 134 | ** range of previous instruction instead of emitting a new one. (For |
135 | ** instance, 'local a; local b' will generate a single opcode.) | | 135 | ** instance, 'local a; local b' will generate a single opcode.) |
136 | */ | | 136 | */ |
137 | void luaK_nil (FuncState *fs, int from, int n) { | | 137 | void luaK_nil (FuncState *fs, int from, int n) { |
138 | int l = from + n - 1; /* last register to set nil */ | | 138 | int l = from + n - 1; /* last register to set nil */ |
139 | Instruction *previous = previousinstruction(fs); | | 139 | Instruction *previous = previousinstruction(fs); |
140 | if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ | | 140 | if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ |
141 | int pfrom = GETARG_A(*previous); /* get previous range */ | | 141 | int pfrom = GETARG_A(*previous); /* get previous range */ |
142 | int pl = pfrom + GETARG_B(*previous); | | 142 | int pl = pfrom + GETARG_B(*previous); |
143 | if ((pfrom <= from && from <= pl + 1) || | | 143 | if ((pfrom <= from && from <= pl + 1) || |
144 | (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ | | 144 | (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ |
145 | if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ | | 145 | if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ |
146 | if (pl > l) l = pl; /* l = max(l, pl) */ | | 146 | if (pl > l) l = pl; /* l = max(l, pl) */ |
147 | SETARG_A(*previous, from); | | 147 | SETARG_A(*previous, from); |
148 | SETARG_B(*previous, l - from); | | 148 | SETARG_B(*previous, l - from); |
149 | return; | | 149 | return; |
150 | } /* else go through */ | | 150 | } /* else go through */ |
151 | } | | 151 | } |
152 | luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ | | 152 | luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ |
153 | } | | 153 | } |
154 | | | 154 | |
155 | | | 155 | |
156 | /* | | 156 | /* |
157 | ** Gets the destination address of a jump instruction. Used to traverse | | 157 | ** Gets the destination address of a jump instruction. Used to traverse |
158 | ** a list of jumps. | | 158 | ** a list of jumps. |
159 | */ | | 159 | */ |
160 | static int getjump (FuncState *fs, int pc) { | | 160 | static int getjump (FuncState *fs, int pc) { |
161 | int offset = GETARG_sJ(fs->f->code[pc]); | | 161 | int offset = GETARG_sJ(fs->f->code[pc]); |
162 | if (offset == NO_JUMP) /* point to itself represents end of list */ | | 162 | if (offset == NO_JUMP) /* point to itself represents end of list */ |
163 | return NO_JUMP; /* end of list */ | | 163 | return NO_JUMP; /* end of list */ |
164 | else | | 164 | else |
165 | return (pc+1)+offset; /* turn offset into absolute position */ | | 165 | return (pc+1)+offset; /* turn offset into absolute position */ |
166 | } | | 166 | } |
167 | | | 167 | |
168 | | | 168 | |
169 | /* | | 169 | /* |
170 | ** Fix jump instruction at position 'pc' to jump to 'dest'. | | 170 | ** Fix jump instruction at position 'pc' to jump to 'dest'. |
171 | ** (Jump addresses are relative in Lua) | | 171 | ** (Jump addresses are relative in Lua) |
172 | */ | | 172 | */ |
173 | static void fixjump (FuncState *fs, int pc, int dest) { | | 173 | static void fixjump (FuncState *fs, int pc, int dest) { |
174 | Instruction *jmp = &fs->f->code[pc]; | | 174 | Instruction *jmp = &fs->f->code[pc]; |
175 | int offset = dest - (pc + 1); | | 175 | int offset = dest - (pc + 1); |
176 | lua_assert(dest != NO_JUMP); | | 176 | lua_assert(dest != NO_JUMP); |
177 | if (!(-OFFSET_sJ <= offset && offset <= MAXARG_sJ - OFFSET_sJ)) | | 177 | if (!(-OFFSET_sJ <= offset && offset <= MAXARG_sJ - OFFSET_sJ)) |
178 | luaX_syntaxerror(fs->ls, "control structure too long"); | | 178 | luaX_syntaxerror(fs->ls, "control structure too long"); |
179 | lua_assert(GET_OPCODE(*jmp) == OP_JMP); | | 179 | lua_assert(GET_OPCODE(*jmp) == OP_JMP); |
180 | SETARG_sJ(*jmp, offset); | | 180 | SETARG_sJ(*jmp, offset); |
181 | } | | 181 | } |
182 | | | 182 | |
183 | | | 183 | |
184 | /* | | 184 | /* |
185 | ** Concatenate jump-list 'l2' into jump-list 'l1' | | 185 | ** Concatenate jump-list 'l2' into jump-list 'l1' |
186 | */ | | 186 | */ |
187 | void luaK_concat (FuncState *fs, int *l1, int l2) { | | 187 | void luaK_concat (FuncState *fs, int *l1, int l2) { |
188 | if (l2 == NO_JUMP) return; /* nothing to concatenate? */ | | 188 | if (l2 == NO_JUMP) return; /* nothing to concatenate? */ |
189 | else if (*l1 == NO_JUMP) /* no original list? */ | | 189 | else if (*l1 == NO_JUMP) /* no original list? */ |
190 | *l1 = l2; /* 'l1' points to 'l2' */ | | 190 | *l1 = l2; /* 'l1' points to 'l2' */ |
191 | else { | | 191 | else { |
192 | int list = *l1; | | 192 | int list = *l1; |
193 | int next; | | 193 | int next; |
194 | while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ | | 194 | while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ |
195 | list = next; | | 195 | list = next; |
196 | fixjump(fs, list, l2); /* last element links to 'l2' */ | | 196 | fixjump(fs, list, l2); /* last element links to 'l2' */ |
197 | } | | 197 | } |
198 | } | | 198 | } |
199 | | | 199 | |
200 | | | 200 | |
201 | /* | | 201 | /* |
202 | ** Create a jump instruction and return its position, so its destination | | 202 | ** Create a jump instruction and return its position, so its destination |
203 | ** can be fixed later (with 'fixjump'). | | 203 | ** can be fixed later (with 'fixjump'). |
204 | */ | | 204 | */ |
205 | int luaK_jump (FuncState *fs) { | | 205 | int luaK_jump (FuncState *fs) { |
206 | return codesJ(fs, OP_JMP, NO_JUMP, 0); | | 206 | return codesJ(fs, OP_JMP, NO_JUMP, 0); |
207 | } | | 207 | } |
208 | | | 208 | |
209 | | | 209 | |
210 | /* | | 210 | /* |
211 | ** Code a 'return' instruction | | 211 | ** Code a 'return' instruction |
212 | */ | | 212 | */ |
213 | void luaK_ret (FuncState *fs, int first, int nret) { | | 213 | void luaK_ret (FuncState *fs, int first, int nret) { |
214 | OpCode op; | | 214 | OpCode op; |
215 | switch (nret) { | | 215 | switch (nret) { |
216 | case 0: op = OP_RETURN0; break; | | 216 | case 0: op = OP_RETURN0; break; |
217 | case 1: op = OP_RETURN1; break; | | 217 | case 1: op = OP_RETURN1; break; |
218 | default: op = OP_RETURN; break; | | 218 | default: op = OP_RETURN; break; |
219 | } | | 219 | } |
220 | luaK_codeABC(fs, op, first, nret + 1, 0); | | 220 | luaK_codeABC(fs, op, first, nret + 1, 0); |
221 | } | | 221 | } |
222 | | | 222 | |
223 | | | 223 | |
224 | /* | | 224 | /* |
225 | ** Code a "conditional jump", that is, a test or comparison opcode | | 225 | ** Code a "conditional jump", that is, a test or comparison opcode |
226 | ** followed by a jump. Return jump position. | | 226 | ** followed by a jump. Return jump position. |
227 | */ | | 227 | */ |
228 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) { | | 228 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) { |
229 | luaK_codeABCk(fs, op, A, B, C, k); | | 229 | luaK_codeABCk(fs, op, A, B, C, k); |
230 | return luaK_jump(fs); | | 230 | return luaK_jump(fs); |
231 | } | | 231 | } |
232 | | | 232 | |
233 | | | 233 | |
234 | /* | | 234 | /* |
235 | ** returns current 'pc' and marks it as a jump target (to avoid wrong | | 235 | ** returns current 'pc' and marks it as a jump target (to avoid wrong |
236 | ** optimizations with consecutive instructions not in the same basic block). | | 236 | ** optimizations with consecutive instructions not in the same basic block). |
237 | */ | | 237 | */ |
238 | int luaK_getlabel (FuncState *fs) { | | 238 | int luaK_getlabel (FuncState *fs) { |
239 | fs->lasttarget = fs->pc; | | 239 | fs->lasttarget = fs->pc; |
240 | return fs->pc; | | 240 | return fs->pc; |
241 | } | | 241 | } |
242 | | | 242 | |
243 | | | 243 | |
244 | /* | | 244 | /* |
245 | ** Returns the position of the instruction "controlling" a given | | 245 | ** Returns the position of the instruction "controlling" a given |
246 | ** jump (that is, its condition), or the jump itself if it is | | 246 | ** jump (that is, its condition), or the jump itself if it is |
247 | ** unconditional. | | 247 | ** unconditional. |
248 | */ | | 248 | */ |
249 | static Instruction *getjumpcontrol (FuncState *fs, int pc) { | | 249 | static Instruction *getjumpcontrol (FuncState *fs, int pc) { |
250 | Instruction *pi = &fs->f->code[pc]; | | 250 | Instruction *pi = &fs->f->code[pc]; |
251 | if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) | | 251 | if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) |
252 | return pi-1; | | 252 | return pi-1; |
253 | else | | 253 | else |
254 | return pi; | | 254 | return pi; |
255 | } | | 255 | } |
256 | | | 256 | |
257 | | | 257 | |
258 | /* | | 258 | /* |
259 | ** Patch destination register for a TESTSET instruction. | | 259 | ** Patch destination register for a TESTSET instruction. |
260 | ** If instruction in position 'node' is not a TESTSET, return 0 ("fails"). | | 260 | ** If instruction in position 'node' is not a TESTSET, return 0 ("fails"). |
261 | ** Otherwise, if 'reg' is not 'NO_REG', set it as the destination | | 261 | ** Otherwise, if 'reg' is not 'NO_REG', set it as the destination |
262 | ** register. Otherwise, change instruction to a simple 'TEST' (produces | | 262 | ** register. Otherwise, change instruction to a simple 'TEST' (produces |
263 | ** no register value) | | 263 | ** no register value) |
264 | */ | | 264 | */ |
265 | static int patchtestreg (FuncState *fs, int node, int reg) { | | 265 | static int patchtestreg (FuncState *fs, int node, int reg) { |
266 | Instruction *i = getjumpcontrol(fs, node); | | 266 | Instruction *i = getjumpcontrol(fs, node); |
267 | if (GET_OPCODE(*i) != OP_TESTSET) | | 267 | if (GET_OPCODE(*i) != OP_TESTSET) |
268 | return 0; /* cannot patch other instructions */ | | 268 | return 0; /* cannot patch other instructions */ |
269 | if (reg != NO_REG && reg != GETARG_B(*i)) | | 269 | if (reg != NO_REG && reg != GETARG_B(*i)) |
270 | SETARG_A(*i, reg); | | 270 | SETARG_A(*i, reg); |
271 | else { | | 271 | else { |
272 | /* no register to put value or register already has the value; | | 272 | /* no register to put value or register already has the value; |
273 | change instruction to simple test */ | | 273 | change instruction to simple test */ |
274 | *i = CREATE_ABCk(OP_TEST, GETARG_B(*i), 0, 0, GETARG_k(*i)); | | 274 | *i = CREATE_ABCk(OP_TEST, GETARG_B(*i), 0, 0, GETARG_k(*i)); |
275 | } | | 275 | } |
276 | return 1; | | 276 | return 1; |
277 | } | | 277 | } |
278 | | | 278 | |
279 | | | 279 | |
280 | /* | | 280 | /* |
281 | ** Traverse a list of tests ensuring no one produces a value | | 281 | ** Traverse a list of tests ensuring no one produces a value |
282 | */ | | 282 | */ |
283 | static void removevalues (FuncState *fs, int list) { | | 283 | static void removevalues (FuncState *fs, int list) { |
284 | for (; list != NO_JUMP; list = getjump(fs, list)) | | 284 | for (; list != NO_JUMP; list = getjump(fs, list)) |
285 | patchtestreg(fs, list, NO_REG); | | 285 | patchtestreg(fs, list, NO_REG); |
286 | } | | 286 | } |
287 | | | 287 | |
288 | | | 288 | |
289 | /* | | 289 | /* |
290 | ** Traverse a list of tests, patching their destination address and | | 290 | ** Traverse a list of tests, patching their destination address and |
291 | ** registers: tests producing values jump to 'vtarget' (and put their | | 291 | ** registers: tests producing values jump to 'vtarget' (and put their |
292 | ** values in 'reg'), other tests jump to 'dtarget'. | | 292 | ** values in 'reg'), other tests jump to 'dtarget'. |
293 | */ | | 293 | */ |
294 | static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, | | 294 | static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, |
295 | int dtarget) { | | 295 | int dtarget) { |
296 | while (list != NO_JUMP) { | | 296 | while (list != NO_JUMP) { |
297 | int next = getjump(fs, list); | | 297 | int next = getjump(fs, list); |
298 | if (patchtestreg(fs, list, reg)) | | 298 | if (patchtestreg(fs, list, reg)) |
299 | fixjump(fs, list, vtarget); | | 299 | fixjump(fs, list, vtarget); |
300 | else | | 300 | else |
301 | fixjump(fs, list, dtarget); /* jump to default target */ | | 301 | fixjump(fs, list, dtarget); /* jump to default target */ |
302 | list = next; | | 302 | list = next; |
303 | } | | 303 | } |
304 | } | | 304 | } |
305 | | | 305 | |
306 | | | 306 | |
307 | /* | | 307 | /* |
308 | ** Path all jumps in 'list' to jump to 'target'. | | 308 | ** Path all jumps in 'list' to jump to 'target'. |
309 | ** (The assert means that we cannot fix a jump to a forward address | | 309 | ** (The assert means that we cannot fix a jump to a forward address |
310 | ** because we only know addresses once code is generated.) | | 310 | ** because we only know addresses once code is generated.) |
311 | */ | | 311 | */ |
312 | void luaK_patchlist (FuncState *fs, int list, int target) { | | 312 | void luaK_patchlist (FuncState *fs, int list, int target) { |
313 | lua_assert(target <= fs->pc); | | 313 | lua_assert(target <= fs->pc); |
314 | patchlistaux(fs, list, target, NO_REG, target); | | 314 | patchlistaux(fs, list, target, NO_REG, target); |
315 | } | | 315 | } |
316 | | | 316 | |
317 | | | 317 | |
318 | void luaK_patchtohere (FuncState *fs, int list) { | | 318 | void luaK_patchtohere (FuncState *fs, int list) { |
319 | int hr = luaK_getlabel(fs); /* mark "here" as a jump target */ | | 319 | int hr = luaK_getlabel(fs); /* mark "here" as a jump target */ |
320 | luaK_patchlist(fs, list, hr); | | 320 | luaK_patchlist(fs, list, hr); |
321 | } | | 321 | } |
322 | | | 322 | |
323 | | | 323 | |
324 | /* limit for difference between lines in relative line info. */ | | 324 | /* limit for difference between lines in relative line info. */ |
325 | #define LIMLINEDIFF 0x80 | | 325 | #define LIMLINEDIFF 0x80 |
326 | | | 326 | |
327 | | | 327 | |
328 | /* | | 328 | /* |
329 | ** Save line info for a new instruction. If difference from last line | | 329 | ** Save line info for a new instruction. If difference from last line |
330 | ** does not fit in a byte, of after that many instructions, save a new | | 330 | ** does not fit in a byte, of after that many instructions, save a new |
331 | ** absolute line info; (in that case, the special value 'ABSLINEINFO' | | 331 | ** absolute line info; (in that case, the special value 'ABSLINEINFO' |
332 | ** in 'lineinfo' signals the existence of this absolute information.) | | 332 | ** in 'lineinfo' signals the existence of this absolute information.) |
333 | ** Otherwise, store the difference from last line in 'lineinfo'. | | 333 | ** Otherwise, store the difference from last line in 'lineinfo'. |
334 | */ | | 334 | */ |
335 | static void savelineinfo (FuncState *fs, Proto *f, int line) { | | 335 | static void savelineinfo (FuncState *fs, Proto *f, int line) { |
336 | int linedif = line - fs->previousline; | | 336 | int linedif = line - fs->previousline; |
337 | int pc = fs->pc - 1; /* last instruction coded */ | | 337 | int pc = fs->pc - 1; /* last instruction coded */ |
338 | if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ >= MAXIWTHABS) { | | 338 | if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ >= MAXIWTHABS) { |
339 | luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo, | | 339 | luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo, |
340 | f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines"); | | 340 | f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines"); |
341 | f->abslineinfo[fs->nabslineinfo].pc = pc; | | 341 | f->abslineinfo[fs->nabslineinfo].pc = pc; |
342 | f->abslineinfo[fs->nabslineinfo++].line = line; | | 342 | f->abslineinfo[fs->nabslineinfo++].line = line; |
343 | linedif = ABSLINEINFO; /* signal that there is absolute information */ | | 343 | linedif = ABSLINEINFO; /* signal that there is absolute information */ |
344 | fs->iwthabs = 1; /* restart counter */ | | 344 | fs->iwthabs = 1; /* restart counter */ |
345 | } | | 345 | } |
346 | luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte, | | 346 | luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte, |
347 | MAX_INT, "opcodes"); | | 347 | MAX_INT, "opcodes"); |
348 | f->lineinfo[pc] = linedif; | | 348 | f->lineinfo[pc] = linedif; |
349 | fs->previousline = line; /* last line saved */ | | 349 | fs->previousline = line; /* last line saved */ |
350 | } | | 350 | } |
351 | | | 351 | |
352 | | | 352 | |
353 | /* | | 353 | /* |
354 | ** Remove line information from the last instruction. | | 354 | ** Remove line information from the last instruction. |
355 | ** If line information for that instruction is absolute, set 'iwthabs' | | 355 | ** If line information for that instruction is absolute, set 'iwthabs' |
356 | ** above its max to force the new (replacing) instruction to have | | 356 | ** above its max to force the new (replacing) instruction to have |
357 | ** absolute line info, too. | | 357 | ** absolute line info, too. |
358 | */ | | 358 | */ |
359 | static void removelastlineinfo (FuncState *fs) { | | 359 | static void removelastlineinfo (FuncState *fs) { |
360 | Proto *f = fs->f; | | 360 | Proto *f = fs->f; |
361 | int pc = fs->pc - 1; /* last instruction coded */ | | 361 | int pc = fs->pc - 1; /* last instruction coded */ |
362 | if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ | | 362 | if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ |
363 | fs->previousline -= f->lineinfo[pc]; /* correct last line saved */ | | 363 | fs->previousline -= f->lineinfo[pc]; /* correct last line saved */ |
364 | fs->iwthabs--; /* undo previous increment */ | | 364 | fs->iwthabs--; /* undo previous increment */ |
365 | } | | 365 | } |
366 | else { /* absolute line information */ | | 366 | else { /* absolute line information */ |
367 | lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc); | | 367 | lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc); |
368 | fs->nabslineinfo--; /* remove it */ | | 368 | fs->nabslineinfo--; /* remove it */ |
369 | fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ | | 369 | fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ |
370 | } | | 370 | } |
371 | } | | 371 | } |
372 | | | 372 | |
373 | | | 373 | |
374 | /* | | 374 | /* |
375 | ** Remove the last instruction created, correcting line information | | 375 | ** Remove the last instruction created, correcting line information |
376 | ** accordingly. | | 376 | ** accordingly. |
377 | */ | | 377 | */ |
378 | static void removelastinstruction (FuncState *fs) { | | 378 | static void removelastinstruction (FuncState *fs) { |
379 | removelastlineinfo(fs); | | 379 | removelastlineinfo(fs); |
380 | fs->pc--; | | 380 | fs->pc--; |
381 | } | | 381 | } |
382 | | | 382 | |
383 | | | 383 | |
384 | /* | | 384 | /* |
385 | ** Emit instruction 'i', checking for array sizes and saving also its | | 385 | ** Emit instruction 'i', checking for array sizes and saving also its |
386 | ** line information. Return 'i' position. | | 386 | ** line information. Return 'i' position. |
387 | */ | | 387 | */ |
388 | int luaK_code (FuncState *fs, Instruction i) { | | 388 | int luaK_code (FuncState *fs, Instruction i) { |
389 | Proto *f = fs->f; | | 389 | Proto *f = fs->f; |
390 | /* put new instruction in code array */ | | 390 | /* put new instruction in code array */ |
391 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, | | 391 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, |
392 | MAX_INT, "opcodes"); | | 392 | MAX_INT, "opcodes"); |
393 | f->code[fs->pc++] = i; | | 393 | f->code[fs->pc++] = i; |
394 | savelineinfo(fs, f, fs->ls->lastline); | | 394 | savelineinfo(fs, f, fs->ls->lastline); |
395 | return fs->pc - 1; /* index of new instruction */ | | 395 | return fs->pc - 1; /* index of new instruction */ |
396 | } | | 396 | } |
397 | | | 397 | |
398 | | | 398 | |
399 | /* | | 399 | /* |
400 | ** Format and emit an 'iABC' instruction. (Assertions check consistency | | 400 | ** Format and emit an 'iABC' instruction. (Assertions check consistency |
401 | ** of parameters versus opcode.) | | 401 | ** of parameters versus opcode.) |
402 | */ | | 402 | */ |
403 | int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) { | | 403 | int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) { |
404 | lua_assert(getOpMode(o) == iABC); | | 404 | lua_assert(getOpMode(o) == iABC); |
405 | lua_assert(a <= MAXARG_A && b <= MAXARG_B && | | 405 | lua_assert(a <= MAXARG_A && b <= MAXARG_B && |
406 | c <= MAXARG_C && (k & ~1) == 0); | | 406 | c <= MAXARG_C && (k & ~1) == 0); |
407 | return luaK_code(fs, CREATE_ABCk(o, a, b, c, k)); | | 407 | return luaK_code(fs, CREATE_ABCk(o, a, b, c, k)); |
408 | } | | 408 | } |
409 | | | 409 | |
410 | | | 410 | |
411 | /* | | 411 | /* |
412 | ** Format and emit an 'iABx' instruction. | | 412 | ** Format and emit an 'iABx' instruction. |
413 | */ | | 413 | */ |
414 | int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { | | 414 | int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { |
415 | lua_assert(getOpMode(o) == iABx); | | 415 | lua_assert(getOpMode(o) == iABx); |
416 | lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); | | 416 | lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); |
417 | return luaK_code(fs, CREATE_ABx(o, a, bc)); | | 417 | return luaK_code(fs, CREATE_ABx(o, a, bc)); |
418 | } | | 418 | } |
419 | | | 419 | |
420 | | | 420 | |
421 | /* | | 421 | /* |
422 | ** Format and emit an 'iAsBx' instruction. | | 422 | ** Format and emit an 'iAsBx' instruction. |
423 | */ | | 423 | */ |
424 | int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) { | | 424 | int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) { |
425 | unsigned int b = bc + OFFSET_sBx; | | 425 | unsigned int b = bc + OFFSET_sBx; |
426 | lua_assert(getOpMode(o) == iAsBx); | | 426 | lua_assert(getOpMode(o) == iAsBx); |
427 | lua_assert(a <= MAXARG_A && b <= MAXARG_Bx); | | 427 | lua_assert(a <= MAXARG_A && b <= MAXARG_Bx); |
428 | return luaK_code(fs, CREATE_ABx(o, a, b)); | | 428 | return luaK_code(fs, CREATE_ABx(o, a, b)); |
429 | } | | 429 | } |
430 | | | 430 | |
431 | | | 431 | |
432 | /* | | 432 | /* |
433 | ** Format and emit an 'isJ' instruction. | | 433 | ** Format and emit an 'isJ' instruction. |
434 | */ | | 434 | */ |
435 | static int codesJ (FuncState *fs, OpCode o, int sj, int k) { | | 435 | static int codesJ (FuncState *fs, OpCode o, int sj, int k) { |
436 | unsigned int j = sj + OFFSET_sJ; | | 436 | unsigned int j = sj + OFFSET_sJ; |
437 | lua_assert(getOpMode(o) == isJ); | | 437 | lua_assert(getOpMode(o) == isJ); |
438 | lua_assert(j <= MAXARG_sJ && (k & ~1) == 0); | | 438 | lua_assert(j <= MAXARG_sJ && (k & ~1) == 0); |
439 | return luaK_code(fs, CREATE_sJ(o, j, k)); | | 439 | return luaK_code(fs, CREATE_sJ(o, j, k)); |
440 | } | | 440 | } |
441 | | | 441 | |
442 | | | 442 | |
443 | /* | | 443 | /* |
444 | ** Emit an "extra argument" instruction (format 'iAx') | | 444 | ** Emit an "extra argument" instruction (format 'iAx') |
445 | */ | | 445 | */ |
446 | static int codeextraarg (FuncState *fs, int a) { | | 446 | static int codeextraarg (FuncState *fs, int a) { |
447 | lua_assert(a <= MAXARG_Ax); | | 447 | lua_assert(a <= MAXARG_Ax); |
448 | return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); | | 448 | return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); |
449 | } | | 449 | } |
450 | | | 450 | |
451 | | | 451 | |
452 | /* | | 452 | /* |
453 | ** Emit a "load constant" instruction, using either 'OP_LOADK' | | 453 | ** Emit a "load constant" instruction, using either 'OP_LOADK' |
454 | ** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX' | | 454 | ** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX' |
455 | ** instruction with "extra argument". | | 455 | ** instruction with "extra argument". |
456 | */ | | 456 | */ |
457 | static int luaK_codek (FuncState *fs, int reg, int k) { | | 457 | static int luaK_codek (FuncState *fs, int reg, int k) { |
458 | if (k <= MAXARG_Bx) | | 458 | if (k <= MAXARG_Bx) |
459 | return luaK_codeABx(fs, OP_LOADK, reg, k); | | 459 | return luaK_codeABx(fs, OP_LOADK, reg, k); |
460 | else { | | 460 | else { |
461 | int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); | | 461 | int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); |
462 | codeextraarg(fs, k); | | 462 | codeextraarg(fs, k); |
463 | return p; | | 463 | return p; |
464 | } | | 464 | } |
465 | } | | 465 | } |
466 | | | 466 | |
467 | | | 467 | |
468 | /* | | 468 | /* |
469 | ** Check register-stack level, keeping track of its maximum size | | 469 | ** Check register-stack level, keeping track of its maximum size |
470 | ** in field 'maxstacksize' | | 470 | ** in field 'maxstacksize' |
471 | */ | | 471 | */ |
472 | void luaK_checkstack (FuncState *fs, int n) { | | 472 | void luaK_checkstack (FuncState *fs, int n) { |
473 | int newstack = fs->freereg + n; | | 473 | int newstack = fs->freereg + n; |
474 | if (newstack > fs->f->maxstacksize) { | | 474 | if (newstack > fs->f->maxstacksize) { |
475 | if (newstack >= MAXREGS) | | 475 | if (newstack >= MAXREGS) |
476 | luaX_syntaxerror(fs->ls, | | 476 | luaX_syntaxerror(fs->ls, |
477 | "function or expression needs too many registers"); | | 477 | "function or expression needs too many registers"); |
478 | fs->f->maxstacksize = cast_byte(newstack); | | 478 | fs->f->maxstacksize = cast_byte(newstack); |
479 | } | | 479 | } |
480 | } | | 480 | } |
481 | | | 481 | |
482 | | | 482 | |
483 | /* | | 483 | /* |
484 | ** Reserve 'n' registers in register stack | | 484 | ** Reserve 'n' registers in register stack |
485 | */ | | 485 | */ |
486 | void luaK_reserveregs (FuncState *fs, int n) { | | 486 | void luaK_reserveregs (FuncState *fs, int n) { |
487 | luaK_checkstack(fs, n); | | 487 | luaK_checkstack(fs, n); |
488 | fs->freereg += n; | | 488 | fs->freereg += n; |
489 | } | | 489 | } |
490 | | | 490 | |
491 | | | 491 | |
492 | /* | | 492 | /* |
493 | ** Free register 'reg', if it is neither a constant index nor | | 493 | ** Free register 'reg', if it is neither a constant index nor |
494 | ** a local variable. | | 494 | ** a local variable. |
495 | ) | | 495 | ) |
496 | */ | | 496 | */ |
497 | static void freereg (FuncState *fs, int reg) { | | 497 | static void freereg (FuncState *fs, int reg) { |
498 | if (reg >= luaY_nvarstack(fs)) { | | 498 | if (reg >= luaY_nvarstack(fs)) { |
499 | fs->freereg--; | | 499 | fs->freereg--; |
500 | lua_assert(reg == fs->freereg); | | 500 | lua_assert(reg == fs->freereg); |
501 | } | | 501 | } |
502 | } | | 502 | } |
503 | | | 503 | |
504 | | | 504 | |
505 | /* | | 505 | /* |
506 | ** Free two registers in proper order | | 506 | ** Free two registers in proper order |
507 | */ | | 507 | */ |
508 | static void freeregs (FuncState *fs, int r1, int r2) { | | 508 | static void freeregs (FuncState *fs, int r1, int r2) { |
509 | if (r1 > r2) { | | 509 | if (r1 > r2) { |
510 | freereg(fs, r1); | | 510 | freereg(fs, r1); |
511 | freereg(fs, r2); | | 511 | freereg(fs, r2); |
512 | } | | 512 | } |
513 | else { | | 513 | else { |
514 | freereg(fs, r2); | | 514 | freereg(fs, r2); |
515 | freereg(fs, r1); | | 515 | freereg(fs, r1); |
516 | } | | 516 | } |
517 | } | | 517 | } |
518 | | | 518 | |
519 | | | 519 | |
520 | /* | | 520 | /* |
521 | ** Free register used by expression 'e' (if any) | | 521 | ** Free register used by expression 'e' (if any) |
522 | */ | | 522 | */ |
523 | static void freeexp (FuncState *fs, expdesc *e) { | | 523 | static void freeexp (FuncState *fs, expdesc *e) { |
524 | if (e->k == VNONRELOC) | | 524 | if (e->k == VNONRELOC) |
525 | freereg(fs, e->u.info); | | 525 | freereg(fs, e->u.info); |
526 | } | | 526 | } |
527 | | | 527 | |
528 | | | 528 | |
529 | /* | | 529 | /* |
530 | ** Free registers used by expressions 'e1' and 'e2' (if any) in proper | | 530 | ** Free registers used by expressions 'e1' and 'e2' (if any) in proper |
531 | ** order. | | 531 | ** order. |
532 | */ | | 532 | */ |
533 | static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { | | 533 | static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { |
534 | int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; | | 534 | int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; |
535 | int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; | | 535 | int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; |
536 | freeregs(fs, r1, r2); | | 536 | freeregs(fs, r1, r2); |
537 | } | | 537 | } |
538 | | | 538 | |
539 | | | 539 | |
540 | /* | | 540 | /* |
541 | ** Add constant 'v' to prototype's list of constants (field 'k'). | | 541 | ** Add constant 'v' to prototype's list of constants (field 'k'). |
542 | ** Use scanner's table to cache position of constants in constant list | | 542 | ** Use scanner's table to cache position of constants in constant list |
543 | ** and try to reuse constants. Because some values should not be used | | 543 | ** and try to reuse constants. Because some values should not be used |
544 | ** as keys (nil cannot be a key, integer keys can collapse with float | | 544 | ** as keys (nil cannot be a key, integer keys can collapse with float |
545 | ** keys), the caller must provide a useful 'key' for indexing the cache. | | 545 | ** keys), the caller must provide a useful 'key' for indexing the cache. |
546 | ** Note that all functions share the same table, so entering or exiting | | 546 | ** Note that all functions share the same table, so entering or exiting |
547 | ** a function can make some indices wrong. | | 547 | ** a function can make some indices wrong. |
548 | */ | | 548 | */ |
549 | static int addk (FuncState *fs, TValue *key, TValue *v) { | | 549 | static int addk (FuncState *fs, TValue *key, TValue *v) { |
550 | TValue val; | | 550 | TValue val; |
551 | lua_State *L = fs->ls->L; | | 551 | lua_State *L = fs->ls->L; |
552 | Proto *f = fs->f; | | 552 | Proto *f = fs->f; |
553 | const TValue *idx = luaH_get(fs->ls->h, key); /* query scanner table */ | | 553 | const TValue *idx = luaH_get(fs->ls->h, key); /* query scanner table */ |
554 | int k, oldsize; | | 554 | int k, oldsize; |
555 | if (ttisinteger(idx)) { /* is there an index there? */ | | 555 | if (ttisinteger(idx)) { /* is there an index there? */ |
556 | k = cast_int(ivalue(idx)); | | 556 | k = cast_int(ivalue(idx)); |
557 | /* correct value? (warning: must distinguish floats from integers!) */ | | 557 | /* correct value? (warning: must distinguish floats from integers!) */ |
558 | if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && | | 558 | if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && |
559 | luaV_rawequalobj(&f->k[k], v)) | | 559 | luaV_rawequalobj(&f->k[k], v)) |
560 | return k; /* reuse index */ | | 560 | return k; /* reuse index */ |
561 | } | | 561 | } |
562 | /* constant not found; create a new entry */ | | 562 | /* constant not found; create a new entry */ |
563 | oldsize = f->sizek; | | 563 | oldsize = f->sizek; |
564 | k = fs->nk; | | 564 | k = fs->nk; |
565 | /* numerical value does not need GC barrier; | | 565 | /* numerical value does not need GC barrier; |
566 | table has no metatable, so it does not need to invalidate cache */ | | 566 | table has no metatable, so it does not need to invalidate cache */ |
567 | setivalue(&val, k); | | 567 | setivalue(&val, k); |
568 | luaH_finishset(L, fs->ls->h, key, idx, &val); | | 568 | luaH_finishset(L, fs->ls->h, key, idx, &val); |
569 | luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); | | 569 | luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); |
570 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | | 570 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); |
571 | setobj(L, &f->k[k], v); | | 571 | setobj(L, &f->k[k], v); |
572 | fs->nk++; | | 572 | fs->nk++; |
573 | luaC_barrier(L, f, v); | | 573 | luaC_barrier(L, f, v); |
574 | return k; | | 574 | return k; |
575 | } | | 575 | } |
576 | | | 576 | |
577 | | | 577 | |
578 | /* | | 578 | /* |
579 | ** Add a string to list of constants and return its index. | | 579 | ** Add a string to list of constants and return its index. |
580 | */ | | 580 | */ |
581 | static int stringK (FuncState *fs, TString *s) { | | 581 | static int stringK (FuncState *fs, TString *s) { |
582 | TValue o; | | 582 | TValue o; |
583 | setsvalue(fs->ls->L, &o, s); | | 583 | setsvalue(fs->ls->L, &o, s); |
584 | return addk(fs, &o, &o); /* use string itself as key */ | | 584 | return addk(fs, &o, &o); /* use string itself as key */ |
585 | } | | 585 | } |
586 | | | 586 | |
587 | | | 587 | |
588 | /* | | 588 | /* |
589 | ** Add an integer to list of constants and return its index. | | 589 | ** Add an integer to list of constants and return its index. |
590 | */ | | 590 | */ |
591 | static int luaK_intK (FuncState *fs, lua_Integer n) { | | 591 | static int luaK_intK (FuncState *fs, lua_Integer n) { |
592 | TValue o; | | 592 | TValue o; |
593 | setivalue(&o, n); | | 593 | setivalue(&o, n); |
594 | return addk(fs, &o, &o); /* use integer itself as key */ | | 594 | return addk(fs, &o, &o); /* use integer itself as key */ |
595 | } | | 595 | } |
596 | | | 596 | |
597 | | | 597 | |
598 | #ifndef _KERNEL | | 598 | #ifndef _KERNEL |
599 | /* | | 599 | /* |
600 | ** Add a float to list of constants and return its index. Floats | | 600 | ** Add a float to list of constants and return its index. Floats |
601 | ** with integral values need a different key, to avoid collision | | 601 | ** with integral values need a different key, to avoid collision |
602 | ** with actual integers. To that, we add to the number its smaller | | 602 | ** with actual integers. To that, we add to the number its smaller |
603 | ** power-of-two fraction that is still significant in its scale. | | 603 | ** power-of-two fraction that is still significant in its scale. |
604 | ** For doubles, that would be 1/2^52. | | 604 | ** For doubles, that would be 1/2^52. |
605 | ** (This method is not bulletproof: there may be another float | | 605 | ** (This method is not bulletproof: there may be another float |
606 | ** with that value, and for floats larger than 2^53 the result is | | 606 | ** with that value, and for floats larger than 2^53 the result is |
607 | ** still an integer. At worst, this only wastes an entry with | | 607 | ** still an integer. At worst, this only wastes an entry with |
608 | ** a duplicate.) | | 608 | ** a duplicate.) |
609 | */ | | 609 | */ |
610 | static int luaK_numberK (FuncState *fs, lua_Number r) { | | 610 | static int luaK_numberK (FuncState *fs, lua_Number r) { |
611 | TValue o; | | 611 | TValue o; |
612 | lua_Integer ik; | | 612 | lua_Integer ik; |
613 | setfltvalue(&o, r); | | 613 | setfltvalue(&o, r); |
614 | if (!luaV_flttointeger(r, &ik, F2Ieq)) /* not an integral value? */ | | 614 | if (!luaV_flttointeger(r, &ik, F2Ieq)) /* not an integral value? */ |
615 | return addk(fs, &o, &o); /* use number itself as key */ | | 615 | return addk(fs, &o, &o); /* use number itself as key */ |
616 | else { /* must build an alternative key */ | | 616 | else { /* must build an alternative key */ |
617 | const int nbm = l_floatatt(MANT_DIG); | | 617 | const int nbm = l_floatatt(MANT_DIG); |
618 | const lua_Number q = l_mathop(ldexp)(l_mathop(1.0), -nbm + 1); | | 618 | const lua_Number q = l_mathop(ldexp)(l_mathop(1.0), -nbm + 1); |
619 | const lua_Number k = (ik == 0) ? q : r + r*q; /* new key */ | | 619 | const lua_Number k = (ik == 0) ? q : r + r*q; /* new key */ |
620 | TValue kv; | | 620 | TValue kv; |
621 | setfltvalue(&kv, k); | | 621 | setfltvalue(&kv, k); |
622 | /* result is not an integral value, unless value is too large */ | | 622 | /* result is not an integral value, unless value is too large */ |
623 | lua_assert(!luaV_flttointeger(k, &ik, F2Ieq) || | | 623 | lua_assert(!luaV_flttointeger(k, &ik, F2Ieq) || |
624 | l_mathop(fabs)(r) >= l_mathop(1e6)); | | 624 | l_mathop(fabs)(r) >= l_mathop(1e6)); |
625 | return addk(fs, &kv, &o); | | 625 | return addk(fs, &kv, &o); |
626 | } | | 626 | } |
627 | } | | 627 | } |
628 | #endif /* _KERNEL */ | | 628 | #endif /* _KERNEL */ |
629 | | | 629 | |
630 | | | 630 | |
631 | /* | | 631 | /* |
632 | ** Add a false to list of constants and return its index. | | 632 | ** Add a false to list of constants and return its index. |
633 | */ | | 633 | */ |
634 | static int boolF (FuncState *fs) { | | 634 | static int boolF (FuncState *fs) { |
635 | TValue o; | | 635 | TValue o; |
636 | setbfvalue(&o); | | 636 | setbfvalue(&o); |
637 | return addk(fs, &o, &o); /* use boolean itself as key */ | | 637 | return addk(fs, &o, &o); /* use boolean itself as key */ |
638 | } | | 638 | } |
639 | | | 639 | |
640 | | | 640 | |
641 | /* | | 641 | /* |
642 | ** Add a true to list of constants and return its index. | | 642 | ** Add a true to list of constants and return its index. |
643 | */ | | 643 | */ |
644 | static int boolT (FuncState *fs) { | | 644 | static int boolT (FuncState *fs) { |
645 | TValue o; | | 645 | TValue o; |
646 | setbtvalue(&o); | | 646 | setbtvalue(&o); |
647 | return addk(fs, &o, &o); /* use boolean itself as key */ | | 647 | return addk(fs, &o, &o); /* use boolean itself as key */ |
648 | } | | 648 | } |
649 | | | 649 | |
650 | | | 650 | |
651 | /* | | 651 | /* |
652 | ** Add nil to list of constants and return its index. | | 652 | ** Add nil to list of constants and return its index. |
653 | */ | | 653 | */ |
654 | static int nilK (FuncState *fs) { | | 654 | static int nilK (FuncState *fs) { |
655 | TValue k, v; | | 655 | TValue k, v; |
656 | setnilvalue(&v); | | 656 | setnilvalue(&v); |
657 | /* cannot use nil as key; instead use table itself to represent nil */ | | 657 | /* cannot use nil as key; instead use table itself to represent nil */ |
658 | sethvalue(fs->ls->L, &k, fs->ls->h); | | 658 | sethvalue(fs->ls->L, &k, fs->ls->h); |
659 | return addk(fs, &k, &v); | | 659 | return addk(fs, &k, &v); |
660 | } | | 660 | } |
661 | | | 661 | |
662 | | | 662 | |
663 | /* | | 663 | /* |
664 | ** Check whether 'i' can be stored in an 'sC' operand. Equivalent to | | 664 | ** Check whether 'i' can be stored in an 'sC' operand. Equivalent to |
665 | ** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of | | 665 | ** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of |
666 | ** overflows in the hidden addition inside 'int2sC'. | | 666 | ** overflows in the hidden addition inside 'int2sC'. |
667 | */ | | 667 | */ |
668 | static int fitsC (lua_Integer i) { | | 668 | static int fitsC (lua_Integer i) { |
669 | return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C)); | | 669 | return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C)); |
670 | } | | 670 | } |
671 | | | 671 | |
672 | | | 672 | |
673 | /* | | 673 | /* |
674 | ** Check whether 'i' can be stored in an 'sBx' operand. | | 674 | ** Check whether 'i' can be stored in an 'sBx' operand. |
675 | */ | | 675 | */ |
676 | static int fitsBx (lua_Integer i) { | | 676 | static int fitsBx (lua_Integer i) { |
677 | return (-OFFSET_sBx <= i && i <= MAXARG_Bx - OFFSET_sBx); | | 677 | return (-OFFSET_sBx <= i && i <= MAXARG_Bx - OFFSET_sBx); |
678 | } | | 678 | } |
679 | | | 679 | |
680 | | | 680 | |
681 | void luaK_int (FuncState *fs, int reg, lua_Integer i) { | | 681 | void luaK_int (FuncState *fs, int reg, lua_Integer i) { |
682 | if (fitsBx(i)) | | 682 | if (fitsBx(i)) |
683 | luaK_codeAsBx(fs, OP_LOADI, reg, cast_int(i)); | | 683 | luaK_codeAsBx(fs, OP_LOADI, reg, cast_int(i)); |
684 | else | | 684 | else |
685 | luaK_codek(fs, reg, luaK_intK(fs, i)); | | 685 | luaK_codek(fs, reg, luaK_intK(fs, i)); |
686 | } | | 686 | } |
687 | | | 687 | |
688 | | | 688 | |
689 | #ifndef _KERNEL | | 689 | #ifndef _KERNEL |
690 | static void luaK_float (FuncState *fs, int reg, lua_Number f) { | | 690 | static void luaK_float (FuncState *fs, int reg, lua_Number f) { |
691 | lua_Integer fi; | | 691 | lua_Integer fi; |
692 | if (luaV_flttointeger(f, &fi, F2Ieq) && fitsBx(fi)) | | 692 | if (luaV_flttointeger(f, &fi, F2Ieq) && fitsBx(fi)) |
693 | luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); | | 693 | luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); |
694 | else | | 694 | else |
695 | luaK_codek(fs, reg, luaK_numberK(fs, f)); | | 695 | luaK_codek(fs, reg, luaK_numberK(fs, f)); |
696 | } | | 696 | } |
697 | #endif /* _KERNEL */ | | 697 | #endif /* _KERNEL */ |
698 | | | 698 | |
699 | | | 699 | |
700 | /* | | 700 | /* |
701 | ** Convert a constant in 'v' into an expression description 'e' | | 701 | ** Convert a constant in 'v' into an expression description 'e' |
702 | */ | | 702 | */ |
703 | static void const2exp (TValue *v, expdesc *e) { | | 703 | static void const2exp (TValue *v, expdesc *e) { |
704 | switch (ttypetag(v)) { | | 704 | switch (ttypetag(v)) { |
705 | case LUA_VNUMINT: | | 705 | case LUA_VNUMINT: |
706 | e->k = VKINT; e->u.ival = ivalue(v); | | 706 | e->k = VKINT; e->u.ival = ivalue(v); |
707 | break; | | 707 | break; |
708 | #ifndef _KERNEL | | 708 | #ifndef _KERNEL |
709 | case LUA_VNUMFLT: | | 709 | case LUA_VNUMFLT: |
710 | e->k = VKFLT; e->u.nval = fltvalue(v); | | 710 | e->k = VKFLT; e->u.nval = fltvalue(v); |
711 | break; | | 711 | break; |
712 | #endif /* _KERNEL */ | | 712 | #endif /* _KERNEL */ |
713 | case LUA_VFALSE: | | 713 | case LUA_VFALSE: |
714 | e->k = VFALSE; | | 714 | e->k = VFALSE; |
715 | break; | | 715 | break; |
716 | case LUA_VTRUE: | | 716 | case LUA_VTRUE: |
717 | e->k = VTRUE; | | 717 | e->k = VTRUE; |
718 | break; | | 718 | break; |
719 | case LUA_VNIL: | | 719 | case LUA_VNIL: |
720 | e->k = VNIL; | | 720 | e->k = VNIL; |
721 | break; | | 721 | break; |
722 | case LUA_VSHRSTR: case LUA_VLNGSTR: | | 722 | case LUA_VSHRSTR: case LUA_VLNGSTR: |
723 | e->k = VKSTR; e->u.strval = tsvalue(v); | | 723 | e->k = VKSTR; e->u.strval = tsvalue(v); |
724 | break; | | 724 | break; |
725 | default: lua_assert(0); | | 725 | default: lua_assert(0); |
726 | } | | 726 | } |
727 | } | | 727 | } |
728 | | | 728 | |
729 | | | 729 | |
730 | /* | | 730 | /* |
731 | ** Fix an expression to return the number of results 'nresults'. | | 731 | ** Fix an expression to return the number of results 'nresults'. |
732 | ** 'e' must be a multi-ret expression (function call or vararg). | | 732 | ** 'e' must be a multi-ret expression (function call or vararg). |
733 | */ | | 733 | */ |
734 | void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { | | 734 | void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { |
735 | Instruction *pc = &getinstruction(fs, e); | | 735 | Instruction *pc = &getinstruction(fs, e); |
736 | if (e->k == VCALL) /* expression is an open function call? */ | | 736 | if (e->k == VCALL) /* expression is an open function call? */ |
737 | SETARG_C(*pc, nresults + 1); | | 737 | SETARG_C(*pc, nresults + 1); |
738 | else { | | 738 | else { |
739 | lua_assert(e->k == VVARARG); | | 739 | lua_assert(e->k == VVARARG); |
740 | SETARG_C(*pc, nresults + 1); | | 740 | SETARG_C(*pc, nresults + 1); |
741 | SETARG_A(*pc, fs->freereg); | | 741 | SETARG_A(*pc, fs->freereg); |
742 | luaK_reserveregs(fs, 1); | | 742 | luaK_reserveregs(fs, 1); |
743 | } | | 743 | } |
744 | } | | 744 | } |
745 | | | 745 | |
746 | | | 746 | |
747 | /* | | 747 | /* |
748 | ** Convert a VKSTR to a VK | | 748 | ** Convert a VKSTR to a VK |
749 | */ | | 749 | */ |
750 | static void str2K (FuncState *fs, expdesc *e) { | | 750 | static void str2K (FuncState *fs, expdesc *e) { |
751 | lua_assert(e->k == VKSTR); | | 751 | lua_assert(e->k == VKSTR); |
752 | e->u.info = stringK(fs, e->u.strval); | | 752 | e->u.info = stringK(fs, e->u.strval); |
753 | e->k = VK; | | 753 | e->k = VK; |
754 | } | | 754 | } |
755 | | | 755 | |
756 | | | 756 | |
757 | /* | | 757 | /* |
758 | ** Fix an expression to return one result. | | 758 | ** Fix an expression to return one result. |
759 | ** If expression is not a multi-ret expression (function call or | | 759 | ** If expression is not a multi-ret expression (function call or |
760 | ** vararg), it already returns one result, so nothing needs to be done. | | 760 | ** vararg), it already returns one result, so nothing needs to be done. |
761 | ** Function calls become VNONRELOC expressions (as its result comes | | 761 | ** Function calls become VNONRELOC expressions (as its result comes |
762 | ** fixed in the base register of the call), while vararg expressions | | 762 | ** fixed in the base register of the call), while vararg expressions |
763 | ** become VRELOC (as OP_VARARG puts its results where it wants). | | 763 | ** become VRELOC (as OP_VARARG puts its results where it wants). |
764 | ** (Calls are created returning one result, so that does not need | | 764 | ** (Calls are created returning one result, so that does not need |
765 | ** to be fixed.) | | 765 | ** to be fixed.) |
766 | */ | | 766 | */ |
767 | void luaK_setoneret (FuncState *fs, expdesc *e) { | | 767 | void luaK_setoneret (FuncState *fs, expdesc *e) { |
768 | if (e->k == VCALL) { /* expression is an open function call? */ | | 768 | if (e->k == VCALL) { /* expression is an open function call? */ |
769 | /* already returns 1 value */ | | 769 | /* already returns 1 value */ |
770 | lua_assert(GETARG_C(getinstruction(fs, e)) == 2); | | 770 | lua_assert(GETARG_C(getinstruction(fs, e)) == 2); |
771 | e->k = VNONRELOC; /* result has fixed position */ | | 771 | e->k = VNONRELOC; /* result has fixed position */ |
772 | e->u.info = GETARG_A(getinstruction(fs, e)); | | 772 | e->u.info = GETARG_A(getinstruction(fs, e)); |
773 | } | | 773 | } |
774 | else if (e->k == VVARARG) { | | 774 | else if (e->k == VVARARG) { |
775 | SETARG_C(getinstruction(fs, e), 2); | | 775 | SETARG_C(getinstruction(fs, e), 2); |
776 | e->k = VRELOC; /* can relocate its simple result */ | | 776 | e->k = VRELOC; /* can relocate its simple result */ |
777 | } | | 777 | } |
778 | } | | 778 | } |
779 | | | 779 | |
780 | | | 780 | |
781 | /* | | 781 | /* |
782 | ** Ensure that expression 'e' is not a variable (nor a <const>). | | 782 | ** Ensure that expression 'e' is not a variable (nor a <const>). |
783 | ** (Expression still may have jump lists.) | | 783 | ** (Expression still may have jump lists.) |
784 | */ | | 784 | */ |
785 | void luaK_dischargevars (FuncState *fs, expdesc *e) { | | 785 | void luaK_dischargevars (FuncState *fs, expdesc *e) { |
786 | switch (e->k) { | | 786 | switch (e->k) { |
787 | case VCONST: { | | 787 | case VCONST: { |
788 | const2exp(const2val(fs, e), e); | | 788 | const2exp(const2val(fs, e), e); |
789 | break; | | 789 | break; |
790 | } | | 790 | } |
791 | case VLOCAL: { /* already in a register */ | | 791 | case VLOCAL: { /* already in a register */ |
792 | e->u.info = e->u.var.ridx; | | 792 | e->u.info = e->u.var.ridx; |
793 | e->k = VNONRELOC; /* becomes a non-relocatable value */ | | 793 | e->k = VNONRELOC; /* becomes a non-relocatable value */ |
794 | break; | | 794 | break; |
795 | } | | 795 | } |
796 | case VUPVAL: { /* move value to some (pending) register */ | | 796 | case VUPVAL: { /* move value to some (pending) register */ |
797 | e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); | | 797 | e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); |
798 | e->k = VRELOC; | | 798 | e->k = VRELOC; |
799 | break; | | 799 | break; |
800 | } | | 800 | } |
801 | case VINDEXUP: { | | 801 | case VINDEXUP: { |
802 | e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx); | | 802 | e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx); |
803 | e->k = VRELOC; | | 803 | e->k = VRELOC; |
804 | break; | | 804 | break; |
805 | } | | 805 | } |
806 | case VINDEXI: { | | 806 | case VINDEXI: { |
807 | freereg(fs, e->u.ind.t); | | 807 | freereg(fs, e->u.ind.t); |
808 | e->u.info = luaK_codeABC(fs, OP_GETI, 0, e->u.ind.t, e->u.ind.idx); | | 808 | e->u.info = luaK_codeABC(fs, OP_GETI, 0, e->u.ind.t, e->u.ind.idx); |
809 | e->k = VRELOC; | | 809 | e->k = VRELOC; |
810 | break; | | 810 | break; |
811 | } | | 811 | } |
812 | case VINDEXSTR: { | | 812 | case VINDEXSTR: { |
813 | freereg(fs, e->u.ind.t); | | 813 | freereg(fs, e->u.ind.t); |
814 | e->u.info = luaK_codeABC(fs, OP_GETFIELD, 0, e->u.ind.t, e->u.ind.idx); | | 814 | e->u.info = luaK_codeABC(fs, OP_GETFIELD, 0, e->u.ind.t, e->u.ind.idx); |
815 | e->k = VRELOC; | | 815 | e->k = VRELOC; |
816 | break; | | 816 | break; |
817 | } | | 817 | } |
818 | case VINDEXED: { | | 818 | case VINDEXED: { |
819 | freeregs(fs, e->u.ind.t, e->u.ind.idx); | | 819 | freeregs(fs, e->u.ind.t, e->u.ind.idx); |
820 | e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx); | | 820 | e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx); |
821 | e->k = VRELOC; | | 821 | e->k = VRELOC; |
822 | break; | | 822 | break; |
823 | } | | 823 | } |
824 | case VVARARG: case VCALL: { | | 824 | case VVARARG: case VCALL: { |
825 | luaK_setoneret(fs, e); | | 825 | luaK_setoneret(fs, e); |
826 | break; | | 826 | break; |
827 | } | | 827 | } |
828 | default: break; /* there is one value available (somewhere) */ | | 828 | default: break; /* there is one value available (somewhere) */ |
829 | } | | 829 | } |
830 | } | | 830 | } |
831 | | | 831 | |
832 | | | 832 | |
833 | /* | | 833 | /* |
834 | ** Ensure expression value is in register 'reg', making 'e' a | | 834 | ** Ensure expression value is in register 'reg', making 'e' a |
835 | ** non-relocatable expression. | | 835 | ** non-relocatable expression. |
836 | ** (Expression still may have jump lists.) | | 836 | ** (Expression still may have jump lists.) |
837 | */ | | 837 | */ |
838 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | | 838 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { |
839 | luaK_dischargevars(fs, e); | | 839 | luaK_dischargevars(fs, e); |
840 | switch (e->k) { | | 840 | switch (e->k) { |
841 | case VNIL: { | | 841 | case VNIL: { |
842 | luaK_nil(fs, reg, 1); | | 842 | luaK_nil(fs, reg, 1); |
843 | break; | | 843 | break; |
844 | } | | 844 | } |
845 | case VFALSE: { | | 845 | case VFALSE: { |
846 | luaK_codeABC(fs, OP_LOADFALSE, reg, 0, 0); | | 846 | luaK_codeABC(fs, OP_LOADFALSE, reg, 0, 0); |
847 | break; | | 847 | break; |
848 | } | | 848 | } |
849 | case VTRUE: { | | 849 | case VTRUE: { |
850 | luaK_codeABC(fs, OP_LOADTRUE, reg, 0, 0); | | 850 | luaK_codeABC(fs, OP_LOADTRUE, reg, 0, 0); |
851 | break; | | 851 | break; |
852 | } | | 852 | } |
853 | case VKSTR: { | | 853 | case VKSTR: { |
854 | str2K(fs, e); | | 854 | str2K(fs, e); |
855 | } /* FALLTHROUGH */ | | 855 | } /* FALLTHROUGH */ |
856 | case VK: { | | 856 | case VK: { |
857 | luaK_codek(fs, reg, e->u.info); | | 857 | luaK_codek(fs, reg, e->u.info); |
858 | break; | | 858 | break; |
859 | } | | 859 | } |
860 | #ifndef _KERNEL | | 860 | #ifndef _KERNEL |
861 | case VKFLT: { | | 861 | case VKFLT: { |
862 | luaK_float(fs, reg, e->u.nval); | | 862 | luaK_float(fs, reg, e->u.nval); |
863 | break; | | 863 | break; |
864 | } | | 864 | } |
865 | #endif /* _KERNEL */ | | 865 | #endif /* _KERNEL */ |
866 | case VKINT: { | | 866 | case VKINT: { |
867 | luaK_int(fs, reg, e->u.ival); | | 867 | luaK_int(fs, reg, e->u.ival); |
868 | break; | | 868 | break; |
869 | } | | 869 | } |
870 | case VRELOC: { | | 870 | case VRELOC: { |
871 | Instruction *pc = &getinstruction(fs, e); | | 871 | Instruction *pc = &getinstruction(fs, e); |
872 | SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ | | 872 | SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ |
873 | break; | | 873 | break; |
874 | } | | 874 | } |
875 | case VNONRELOC: { | | 875 | case VNONRELOC: { |
876 | if (reg != e->u.info) | | 876 | if (reg != e->u.info) |
877 | luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); | | 877 | luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); |
878 | break; | | 878 | break; |
879 | } | | 879 | } |
880 | default: { | | 880 | default: { |
881 | lua_assert(e->k == VJMP); | | 881 | lua_assert(e->k == VJMP); |
882 | return; /* nothing to do... */ | | 882 | return; /* nothing to do... */ |
883 | } | | 883 | } |
884 | } | | 884 | } |
885 | e->u.info = reg; | | 885 | e->u.info = reg; |
886 | e->k = VNONRELOC; | | 886 | e->k = VNONRELOC; |
887 | } | | 887 | } |
888 | | | 888 | |
889 | | | 889 | |
890 | /* | | 890 | /* |
891 | ** Ensure expression value is in a register, making 'e' a | | 891 | ** Ensure expression value is in a register, making 'e' a |
892 | ** non-relocatable expression. | | 892 | ** non-relocatable expression. |
893 | ** (Expression still may have jump lists.) | | 893 | ** (Expression still may have jump lists.) |
894 | */ | | 894 | */ |
895 | static void discharge2anyreg (FuncState *fs, expdesc *e) { | | 895 | static void discharge2anyreg (FuncState *fs, expdesc *e) { |
896 | if (e->k != VNONRELOC) { /* no fixed register yet? */ | | 896 | if (e->k != VNONRELOC) { /* no fixed register yet? */ |
897 | luaK_reserveregs(fs, 1); /* get a register */ | | 897 | luaK_reserveregs(fs, 1); /* get a register */ |
898 | discharge2reg(fs, e, fs->freereg-1); /* put value there */ | | 898 | discharge2reg(fs, e, fs->freereg-1); /* put value there */ |
899 | } | | 899 | } |
900 | } | | 900 | } |
901 | | | 901 | |
902 | | | 902 | |
903 | static int code_loadbool (FuncState *fs, int A, OpCode op) { | | 903 | static int code_loadbool (FuncState *fs, int A, OpCode op) { |
904 | luaK_getlabel(fs); /* those instructions may be jump targets */ | | 904 | luaK_getlabel(fs); /* those instructions may be jump targets */ |
905 | return luaK_codeABC(fs, op, A, 0, 0); | | 905 | return luaK_codeABC(fs, op, A, 0, 0); |
906 | } | | 906 | } |
907 | | | 907 | |
908 | | | 908 | |
909 | /* | | 909 | /* |
910 | ** check whether list has any jump that do not produce a value | | 910 | ** check whether list has any jump that do not produce a value |
911 | ** or produce an inverted value | | 911 | ** or produce an inverted value |
912 | */ | | 912 | */ |
913 | static int need_value (FuncState *fs, int list) { | | 913 | static int need_value (FuncState *fs, int list) { |
914 | for (; list != NO_JUMP; list = getjump(fs, list)) { | | 914 | for (; list != NO_JUMP; list = getjump(fs, list)) { |
915 | Instruction i = *getjumpcontrol(fs, list); | | 915 | Instruction i = *getjumpcontrol(fs, list); |
916 | if (GET_OPCODE(i) != OP_TESTSET) return 1; | | 916 | if (GET_OPCODE(i) != OP_TESTSET) return 1; |
917 | } | | 917 | } |
918 | return 0; /* not found */ | | 918 | return 0; /* not found */ |
919 | } | | 919 | } |
920 | | | 920 | |
921 | | | 921 | |
922 | /* | | 922 | /* |
923 | ** Ensures final expression result (which includes results from its | | 923 | ** Ensures final expression result (which includes results from its |
924 | ** jump lists) is in register 'reg'. | | 924 | ** jump lists) is in register 'reg'. |
925 | ** If expression has jumps, need to patch these jumps either to | | 925 | ** If expression has jumps, need to patch these jumps either to |
926 | ** its final position or to "load" instructions (for those tests | | 926 | ** its final position or to "load" instructions (for those tests |
927 | ** that do not produce values). | | 927 | ** that do not produce values). |
928 | */ | | 928 | */ |
929 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { | | 929 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { |
930 | discharge2reg(fs, e, reg); | | 930 | discharge2reg(fs, e, reg); |
931 | if (e->k == VJMP) /* expression itself is a test? */ | | 931 | if (e->k == VJMP) /* expression itself is a test? */ |
932 | luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ | | 932 | luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ |
933 | if (hasjumps(e)) { | | 933 | if (hasjumps(e)) { |
934 | int final; /* position after whole expression */ | | 934 | int final; /* position after whole expression */ |
935 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ | | 935 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
936 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ | | 936 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ |
937 | if (need_value(fs, e->t) || need_value(fs, e->f)) { | | 937 | if (need_value(fs, e->t) || need_value(fs, e->f)) { |
938 | int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); | | 938 | int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); |
939 | p_f = code_loadbool(fs, reg, OP_LFALSESKIP); /* skip next inst. */ | | 939 | p_f = code_loadbool(fs, reg, OP_LFALSESKIP); /* skip next inst. */ |
940 | p_t = code_loadbool(fs, reg, OP_LOADTRUE); | | 940 | p_t = code_loadbool(fs, reg, OP_LOADTRUE); |
941 | /* jump around these booleans if 'e' is not a test */ | | 941 | /* jump around these booleans if 'e' is not a test */ |
942 | luaK_patchtohere(fs, fj); | | 942 | luaK_patchtohere(fs, fj); |
943 | } | | 943 | } |
944 | final = luaK_getlabel(fs); | | 944 | final = luaK_getlabel(fs); |
945 | patchlistaux(fs, e->f, final, reg, p_f); | | 945 | patchlistaux(fs, e->f, final, reg, p_f); |
946 | patchlistaux(fs, e->t, final, reg, p_t); | | 946 | patchlistaux(fs, e->t, final, reg, p_t); |
947 | } | | 947 | } |
948 | e->f = e->t = NO_JUMP; | | 948 | e->f = e->t = NO_JUMP; |
949 | e->u.info = reg; | | 949 | e->u.info = reg; |
950 | e->k = VNONRELOC; | | 950 | e->k = VNONRELOC; |
951 | } | | 951 | } |
952 | | | 952 | |
953 | | | 953 | |
954 | /* | | 954 | /* |
955 | ** Ensures final expression result is in next available register. | | 955 | ** Ensures final expression result is in next available register. |
956 | */ | | 956 | */ |
957 | void luaK_exp2nextreg (FuncState *fs, expdesc *e) { | | 957 | void luaK_exp2nextreg (FuncState *fs, expdesc *e) { |
958 | luaK_dischargevars(fs, e); | | 958 | luaK_dischargevars(fs, e); |
959 | freeexp(fs, e); | | 959 | freeexp(fs, e); |
960 | luaK_reserveregs(fs, 1); | | 960 | luaK_reserveregs(fs, 1); |
961 | exp2reg(fs, e, fs->freereg - 1); | | 961 | exp2reg(fs, e, fs->freereg - 1); |
962 | } | | 962 | } |
963 | | | 963 | |
964 | | | 964 | |
965 | /* | | 965 | /* |
966 | ** Ensures final expression result is in some (any) register | | 966 | ** Ensures final expression result is in some (any) register |
967 | ** and return that register. | | 967 | ** and return that register. |
968 | */ | | 968 | */ |
969 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | | 969 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
970 | luaK_dischargevars(fs, e); | | 970 | luaK_dischargevars(fs, e); |
971 | if (e->k == VNONRELOC) { /* expression already has a register? */ | | 971 | if (e->k == VNONRELOC) { /* expression already has a register? */ |
972 | if (!hasjumps(e)) /* no jumps? */ | | 972 | if (!hasjumps(e)) /* no jumps? */ |
973 | return e->u.info; /* result is already in a register */ | | 973 | return e->u.info; /* result is already in a register */ |
974 | if (e->u.info >= luaY_nvarstack(fs)) { /* reg. is not a local? */ | | 974 | if (e->u.info >= luaY_nvarstack(fs)) { /* reg. is not a local? */ |
975 | exp2reg(fs, e, e->u.info); /* put final result in it */ | | 975 | exp2reg(fs, e, e->u.info); /* put final result in it */ |
976 | return e->u.info; | | 976 | return e->u.info; |
977 | } | | 977 | } |
978 | /* else expression has jumps and cannot change its register | | 978 | /* else expression has jumps and cannot change its register |
979 | to hold the jump values, because it is a local variable. | | 979 | to hold the jump values, because it is a local variable. |
980 | Go through to the default case. */ | | 980 | Go through to the default case. */ |
981 | } | | 981 | } |
982 | luaK_exp2nextreg(fs, e); /* default: use next available register */ | | 982 | luaK_exp2nextreg(fs, e); /* default: use next available register */ |
983 | return e->u.info; | | 983 | return e->u.info; |
984 | } | | 984 | } |
985 | | | 985 | |
986 | | | 986 | |
987 | /* | | 987 | /* |
988 | ** Ensures final expression result is either in a register | | 988 | ** Ensures final expression result is either in a register |
989 | ** or in an upvalue. | | 989 | ** or in an upvalue. |
990 | */ | | 990 | */ |
991 | void luaK_exp2anyregup (FuncState *fs, expdesc *e) { | | 991 | void luaK_exp2anyregup (FuncState *fs, expdesc *e) { |
992 | if (e->k != VUPVAL || hasjumps(e)) | | 992 | if (e->k != VUPVAL || hasjumps(e)) |
993 | luaK_exp2anyreg(fs, e); | | 993 | luaK_exp2anyreg(fs, e); |
994 | } | | 994 | } |
995 | | | 995 | |
996 | | | 996 | |
997 | /* | | 997 | /* |
998 | ** Ensures final expression result is either in a register | | 998 | ** Ensures final expression result is either in a register |
999 | ** or it is a constant. | | 999 | ** or it is a constant. |
1000 | */ | | 1000 | */ |
1001 | void luaK_exp2val (FuncState *fs, expdesc *e) { | | 1001 | void luaK_exp2val (FuncState *fs, expdesc *e) { |
1002 | if (hasjumps(e)) | | 1002 | if (hasjumps(e)) |
1003 | luaK_exp2anyreg(fs, e); | | 1003 | luaK_exp2anyreg(fs, e); |
1004 | else | | 1004 | else |
1005 | luaK_dischargevars(fs, e); | | 1005 | luaK_dischargevars(fs, e); |
1006 | } | | 1006 | } |
1007 | | | 1007 | |
1008 | | | 1008 | |
1009 | /* | | 1009 | /* |
1010 | ** Try to make 'e' a K expression with an index in the range of R/K | | 1010 | ** Try to make 'e' a K expression with an index in the range of R/K |
1011 | ** indices. Return true iff succeeded. | | 1011 | ** indices. Return true iff succeeded. |
1012 | */ | | 1012 | */ |
1013 | static int luaK_exp2K (FuncState *fs, expdesc *e) { | | 1013 | static int luaK_exp2K (FuncState *fs, expdesc *e) { |
1014 | if (!hasjumps(e)) { | | 1014 | if (!hasjumps(e)) { |
1015 | int info; | | 1015 | int info; |
1016 | switch (e->k) { /* move constants to 'k' */ | | 1016 | switch (e->k) { /* move constants to 'k' */ |
1017 | case VTRUE: info = boolT(fs); break; | | 1017 | case VTRUE: info = boolT(fs); break; |
1018 | case VFALSE: info = boolF(fs); break; | | 1018 | case VFALSE: info = boolF(fs); break; |
1019 | case VNIL: info = nilK(fs); break; | | 1019 | case VNIL: info = nilK(fs); break; |
1020 | case VKINT: info = luaK_intK(fs, e->u.ival); break; | | 1020 | case VKINT: info = luaK_intK(fs, e->u.ival); break; |
1021 | #ifndef _KERNEL | | 1021 | #ifndef _KERNEL |
1022 | case VKFLT: info = luaK_numberK(fs, e->u.nval); break; | | 1022 | case VKFLT: info = luaK_numberK(fs, e->u.nval); break; |
1023 | #endif /* _KERNEL */ | | 1023 | #endif /* _KERNEL */ |
1024 | case VKSTR: info = stringK(fs, e->u.strval); break; | | 1024 | case VKSTR: info = stringK(fs, e->u.strval); break; |
1025 | case VK: info = e->u.info; break; | | 1025 | case VK: info = e->u.info; break; |
1026 | default: return 0; /* not a constant */ | | 1026 | default: return 0; /* not a constant */ |
1027 | } | | 1027 | } |
1028 | if (info <= MAXINDEXRK) { /* does constant fit in 'argC'? */ | | 1028 | if (info <= MAXINDEXRK) { /* does constant fit in 'argC'? */ |
1029 | e->k = VK; /* make expression a 'K' expression */ | | 1029 | e->k = VK; /* make expression a 'K' expression */ |
1030 | e->u.info = info; | | 1030 | e->u.info = info; |
1031 | return 1; | | 1031 | return 1; |
1032 | } | | 1032 | } |
1033 | } | | 1033 | } |
1034 | /* else, expression doesn't fit; leave it unchanged */ | | 1034 | /* else, expression doesn't fit; leave it unchanged */ |
1035 | return 0; | | 1035 | return 0; |
1036 | } | | 1036 | } |
1037 | | | 1037 | |
1038 | | | 1038 | |
1039 | /* | | 1039 | /* |
1040 | ** Ensures final expression result is in a valid R/K index | | 1040 | ** Ensures final expression result is in a valid R/K index |
1041 | ** (that is, it is either in a register or in 'k' with an index | | 1041 | ** (that is, it is either in a register or in 'k' with an index |
1042 | ** in the range of R/K indices). | | 1042 | ** in the range of R/K indices). |
1043 | ** Returns 1 iff expression is K. | | 1043 | ** Returns 1 iff expression is K. |
1044 | */ | | 1044 | */ |
1045 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | | 1045 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
1046 | if (luaK_exp2K(fs, e)) | | 1046 | if (luaK_exp2K(fs, e)) |
1047 | return 1; | | 1047 | return 1; |
1048 | else { /* not a constant in the right range: put it in a register */ | | 1048 | else { /* not a constant in the right range: put it in a register */ |
1049 | luaK_exp2anyreg(fs, e); | | 1049 | luaK_exp2anyreg(fs, e); |
1050 | return 0; | | 1050 | return 0; |
1051 | } | | 1051 | } |
1052 | } | | 1052 | } |
1053 | | | 1053 | |
1054 | | | 1054 | |
1055 | static void codeABRK (FuncState *fs, OpCode o, int a, int b, | | 1055 | static void codeABRK (FuncState *fs, OpCode o, int a, int b, |
1056 | expdesc *ec) { | | 1056 | expdesc *ec) { |
1057 | int k = luaK_exp2RK(fs, ec); | | 1057 | int k = luaK_exp2RK(fs, ec); |
1058 | luaK_codeABCk(fs, o, a, b, ec->u.info, k); | | 1058 | luaK_codeABCk(fs, o, a, b, ec->u.info, k); |
1059 | } | | 1059 | } |
1060 | | | 1060 | |
1061 | | | 1061 | |
1062 | /* | | 1062 | /* |
1063 | ** Generate code to store result of expression 'ex' into variable 'var'. | | 1063 | ** Generate code to store result of expression 'ex' into variable 'var'. |
1064 | */ | | 1064 | */ |
1065 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | | 1065 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { |
1066 | switch (var->k) { | | 1066 | switch (var->k) { |
1067 | case VLOCAL: { | | 1067 | case VLOCAL: { |
1068 | freeexp(fs, ex); | | 1068 | freeexp(fs, ex); |
1069 | exp2reg(fs, ex, var->u.var.ridx); /* compute 'ex' into proper place */ | | 1069 | exp2reg(fs, ex, var->u.var.ridx); /* compute 'ex' into proper place */ |
1070 | return; | | 1070 | return; |
1071 | } | | 1071 | } |
1072 | case VUPVAL: { | | 1072 | case VUPVAL: { |
1073 | int e = luaK_exp2anyreg(fs, ex); | | 1073 | int e = luaK_exp2anyreg(fs, ex); |
1074 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); | | 1074 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); |
1075 | break; | | 1075 | break; |
1076 | } | | 1076 | } |
1077 | case VINDEXUP: { | | 1077 | case VINDEXUP: { |
1078 | codeABRK(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, ex); | | 1078 | codeABRK(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, ex); |
1079 | break; | | 1079 | break; |
1080 | } | | 1080 | } |
1081 | case VINDEXI: { | | 1081 | case VINDEXI: { |
1082 | codeABRK(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, ex); | | 1082 | codeABRK(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, ex); |
1083 | break; | | 1083 | break; |
1084 | } | | 1084 | } |
1085 | case VINDEXSTR: { | | 1085 | case VINDEXSTR: { |
1086 | codeABRK(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, ex); | | 1086 | codeABRK(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, ex); |
1087 | break; | | 1087 | break; |
1088 | } | | 1088 | } |
1089 | case VINDEXED: { | | 1089 | case VINDEXED: { |
1090 | codeABRK(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, ex); | | 1090 | codeABRK(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, ex); |
1091 | break; | | 1091 | break; |
1092 | } | | 1092 | } |
1093 | default: lua_assert(0); /* invalid var kind to store */ | | 1093 | default: lua_assert(0); /* invalid var kind to store */ |
1094 | } | | 1094 | } |
1095 | freeexp(fs, ex); | | 1095 | freeexp(fs, ex); |
1096 | } | | 1096 | } |
1097 | | | 1097 | |
1098 | | | 1098 | |
1099 | /* | | 1099 | /* |
1100 | ** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). | | 1100 | ** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). |
1101 | */ | | 1101 | */ |
1102 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | | 1102 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { |
1103 | int ereg; | | 1103 | int ereg; |
1104 | luaK_exp2anyreg(fs, e); | | 1104 | luaK_exp2anyreg(fs, e); |
1105 | ereg = e->u.info; /* register where 'e' was placed */ | | 1105 | ereg = e->u.info; /* register where 'e' was placed */ |
1106 | freeexp(fs, e); | | 1106 | freeexp(fs, e); |
1107 | e->u.info = fs->freereg; /* base register for op_self */ | | 1107 | e->u.info = fs->freereg; /* base register for op_self */ |
1108 | e->k = VNONRELOC; /* self expression has a fixed register */ | | 1108 | e->k = VNONRELOC; /* self expression has a fixed register */ |
1109 | luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ | | 1109 | luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ |
1110 | codeABRK(fs, OP_SELF, e->u.info, ereg, key); | | 1110 | codeABRK(fs, OP_SELF, e->u.info, ereg, key); |
1111 | freeexp(fs, key); | | 1111 | freeexp(fs, key); |
1112 | } | | 1112 | } |
1113 | | | 1113 | |
1114 | | | 1114 | |
1115 | /* | | 1115 | /* |
1116 | ** Negate condition 'e' (where 'e' is a comparison). | | 1116 | ** Negate condition 'e' (where 'e' is a comparison). |
1117 | */ | | 1117 | */ |
1118 | static void negatecondition (FuncState *fs, expdesc *e) { | | 1118 | static void negatecondition (FuncState *fs, expdesc *e) { |
1119 | Instruction *pc = getjumpcontrol(fs, e->u.info); | | 1119 | Instruction *pc = getjumpcontrol(fs, e->u.info); |
1120 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && | | 1120 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
1121 | GET_OPCODE(*pc) != OP_TEST); | | 1121 | GET_OPCODE(*pc) != OP_TEST); |
1122 | SETARG_k(*pc, (GETARG_k(*pc) ^ 1)); | | 1122 | SETARG_k(*pc, (GETARG_k(*pc) ^ 1)); |
1123 | } | | 1123 | } |
1124 | | | 1124 | |
1125 | | | 1125 | |
1126 | /* | | 1126 | /* |
1127 | ** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond' | | 1127 | ** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond' |
1128 | ** is true, code will jump if 'e' is true.) Return jump position. | | 1128 | ** is true, code will jump if 'e' is true.) Return jump position. |
1129 | ** Optimize when 'e' is 'not' something, inverting the condition | | 1129 | ** Optimize when 'e' is 'not' something, inverting the condition |
1130 | ** and removing the 'not'. | | 1130 | ** and removing the 'not'. |
1131 | */ | | 1131 | */ |
1132 | static int jumponcond (FuncState *fs, expdesc *e, int cond) { | | 1132 | static int jumponcond (FuncState *fs, expdesc *e, int cond) { |
1133 | if (e->k == VRELOC) { | | 1133 | if (e->k == VRELOC) { |
1134 | Instruction ie = getinstruction(fs, e); | | 1134 | Instruction ie = getinstruction(fs, e); |
1135 | if (GET_OPCODE(ie) == OP_NOT) { | | 1135 | if (GET_OPCODE(ie) == OP_NOT) { |
1136 | removelastinstruction(fs); /* remove previous OP_NOT */ | | 1136 | removelastinstruction(fs); /* remove previous OP_NOT */ |
1137 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond); | | 1137 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond); |
1138 | } | | 1138 | } |
1139 | /* else go through */ | | 1139 | /* else go through */ |
1140 | } | | 1140 | } |
1141 | discharge2anyreg(fs, e); | | 1141 | discharge2anyreg(fs, e); |
1142 | freeexp(fs, e); | | 1142 | freeexp(fs, e); |
1143 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond); | | 1143 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond); |
1144 | } | | 1144 | } |
1145 | | | 1145 | |
1146 | | | 1146 | |
1147 | /* | | 1147 | /* |
1148 | ** Emit code to go through if 'e' is true, jump otherwise. | | 1148 | ** Emit code to go through if 'e' is true, jump otherwise. |
1149 | */ | | 1149 | */ |
1150 | void luaK_goiftrue (FuncState *fs, expdesc *e) { | | 1150 | void luaK_goiftrue (FuncState *fs, expdesc *e) { |
1151 | int pc; /* pc of new jump */ | | 1151 | int pc; /* pc of new jump */ |
1152 | luaK_dischargevars(fs, e); | | 1152 | luaK_dischargevars(fs, e); |
1153 | switch (e->k) { | | 1153 | switch (e->k) { |
1154 | case VJMP: { /* condition? */ | | 1154 | case VJMP: { /* condition? */ |
1155 | negatecondition(fs, e); /* jump when it is false */ | | 1155 | negatecondition(fs, e); /* jump when it is false */ |
1156 | pc = e->u.info; /* save jump position */ | | 1156 | pc = e->u.info; /* save jump position */ |
1157 | break; | | 1157 | break; |
1158 | } | | 1158 | } |
1159 | #ifndef _KERNEL | | 1159 | #ifndef _KERNEL |
1160 | case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { | | 1160 | case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { |
1161 | #else /* _KERNEL */ | | 1161 | #else /* _KERNEL */ |
1162 | case VK: case VKINT: case VKSTR: case VTRUE: { | | 1162 | case VK: case VKINT: case VKSTR: case VTRUE: { |
1163 | #endif /* _KERNEL */ | | 1163 | #endif /* _KERNEL */ |
1164 | pc = NO_JUMP; /* always true; do nothing */ | | 1164 | pc = NO_JUMP; /* always true; do nothing */ |
1165 | break; | | 1165 | break; |
1166 | } | | 1166 | } |
1167 | default: { | | 1167 | default: { |
1168 | pc = jumponcond(fs, e, 0); /* jump when false */ | | 1168 | pc = jumponcond(fs, e, 0); /* jump when false */ |
1169 | break; | | 1169 | break; |
1170 | } | | 1170 | } |
1171 | } | | 1171 | } |
1172 | luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ | | 1172 | luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ |
1173 | luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ | | 1173 | luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ |
1174 | e->t = NO_JUMP; | | 1174 | e->t = NO_JUMP; |
1175 | } | | 1175 | } |
1176 | | | 1176 | |
1177 | | | 1177 | |
1178 | /* | | 1178 | /* |
1179 | ** Emit code to go through if 'e' is false, jump otherwise. | | 1179 | ** Emit code to go through if 'e' is false, jump otherwise. |
1180 | */ | | 1180 | */ |
1181 | void luaK_goiffalse (FuncState *fs, expdesc *e) { | | 1181 | void luaK_goiffalse (FuncState *fs, expdesc *e) { |
1182 | int pc; /* pc of new jump */ | | 1182 | int pc; /* pc of new jump */ |
1183 | luaK_dischargevars(fs, e); | | 1183 | luaK_dischargevars(fs, e); |
1184 | switch (e->k) { | | 1184 | switch (e->k) { |
1185 | case VJMP: { | | 1185 | case VJMP: { |
1186 | pc = e->u.info; /* already jump if true */ | | 1186 | pc = e->u.info; /* already jump if true */ |
1187 | break; | | 1187 | break; |
1188 | } | | 1188 | } |
1189 | case VNIL: case VFALSE: { | | 1189 | case VNIL: case VFALSE: { |
1190 | pc = NO_JUMP; /* always false; do nothing */ | | 1190 | pc = NO_JUMP; /* always false; do nothing */ |
1191 | break; | | 1191 | break; |
1192 | } | | 1192 | } |
1193 | default: { | | 1193 | default: { |
1194 | pc = jumponcond(fs, e, 1); /* jump if true */ | | 1194 | pc = jumponcond(fs, e, 1); /* jump if true */ |
1195 | break; | | 1195 | break; |
1196 | } | | 1196 | } |
1197 | } | | 1197 | } |
1198 | luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ | | 1198 | luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ |
1199 | luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ | | 1199 | luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ |
1200 | e->f = NO_JUMP; | | 1200 | e->f = NO_JUMP; |
1201 | } | | 1201 | } |
1202 | | | 1202 | |
1203 | | | 1203 | |
1204 | /* | | 1204 | /* |
1205 | ** Code 'not e', doing constant folding. | | 1205 | ** Code 'not e', doing constant folding. |
1206 | */ | | 1206 | */ |
1207 | static void codenot (FuncState *fs, expdesc *e) { | | 1207 | static void codenot (FuncState *fs, expdesc *e) { |
1208 | switch (e->k) { | | 1208 | switch (e->k) { |
1209 | case VNIL: case VFALSE: { | | 1209 | case VNIL: case VFALSE: { |
1210 | e->k = VTRUE; /* true == not nil == not false */ | | 1210 | e->k = VTRUE; /* true == not nil == not false */ |
1211 | break; | | 1211 | break; |
1212 | } | | 1212 | } |
1213 | #ifndef _KERNEL | | 1213 | #ifndef _KERNEL |
1214 | case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { | | 1214 | case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { |
1215 | #else /* _KERNEL */ | | 1215 | #else /* _KERNEL */ |
1216 | case VK: case VKINT: case VKSTR: case VTRUE: { | | 1216 | case VK: case VKINT: case VKSTR: case VTRUE: { |
1217 | #endif /* _KERNEL */ | | 1217 | #endif /* _KERNEL */ |
1218 | e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ | | 1218 | e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ |
1219 | break; | | 1219 | break; |
1220 | } | | 1220 | } |
1221 | case VJMP: { | | 1221 | case VJMP: { |
1222 | negatecondition(fs, e); | | 1222 | negatecondition(fs, e); |
1223 | break; | | 1223 | break; |
1224 | } | | 1224 | } |
1225 | case VRELOC: | | 1225 | case VRELOC: |
1226 | case VNONRELOC: { | | 1226 | case VNONRELOC: { |
1227 | discharge2anyreg(fs, e); | | 1227 | discharge2anyreg(fs, e); |
1228 | freeexp(fs, e); | | 1228 | freeexp(fs, e); |
1229 | e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); | | 1229 | e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); |
1230 | e->k = VRELOC; | | 1230 | e->k = VRELOC; |
1231 | break; | | 1231 | break; |
1232 | } | | 1232 | } |
1233 | default: lua_assert(0); /* cannot happen */ | | 1233 | default: lua_assert(0); /* cannot happen */ |
1234 | } | | 1234 | } |
1235 | /* interchange true and false lists */ | | 1235 | /* interchange true and false lists */ |
1236 | { int temp = e->f; e->f = e->t; e->t = temp; } | | 1236 | { int temp = e->f; e->f = e->t; e->t = temp; } |
1237 | removevalues(fs, e->f); /* values are useless when negated */ | | 1237 | removevalues(fs, e->f); /* values are useless when negated */ |
1238 | removevalues(fs, e->t); | | 1238 | removevalues(fs, e->t); |
1239 | } | | 1239 | } |
1240 | | | 1240 | |
1241 | | | 1241 | |
1242 | /* | | 1242 | /* |
1243 | ** Check whether expression 'e' is a small literal string | | 1243 | ** Check whether expression 'e' is a small literal string |
1244 | */ | | 1244 | */ |
1245 | static int isKstr (FuncState *fs, expdesc *e) { | | 1245 | static int isKstr (FuncState *fs, expdesc *e) { |
1246 | return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B && | | 1246 | return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B && |
1247 | ttisshrstring(&fs->f->k[e->u.info])); | | 1247 | ttisshrstring(&fs->f->k[e->u.info])); |
1248 | } | | 1248 | } |
1249 | | | 1249 | |
1250 | /* | | 1250 | /* |
1251 | ** Check whether expression 'e' is a literal integer. | | 1251 | ** Check whether expression 'e' is a literal integer. |
1252 | */ | | 1252 | */ |
1253 | int luaK_isKint (expdesc *e) { | | 1253 | int luaK_isKint (expdesc *e) { |
1254 | return (e->k == VKINT && !hasjumps(e)); | | 1254 | return (e->k == VKINT && !hasjumps(e)); |
1255 | } | | 1255 | } |
1256 | | | 1256 | |
1257 | | | 1257 | |
1258 | /* | | 1258 | /* |
1259 | ** Check whether expression 'e' is a literal integer in | | 1259 | ** Check whether expression 'e' is a literal integer in |
1260 | ** proper range to fit in register C | | 1260 | ** proper range to fit in register C |
1261 | */ | | 1261 | */ |
1262 | static int isCint (expdesc *e) { | | 1262 | static int isCint (expdesc *e) { |
1263 | return luaK_isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C)); | | 1263 | return luaK_isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C)); |
1264 | } | | 1264 | } |
1265 | | | 1265 | |
1266 | | | 1266 | |
1267 | /* | | 1267 | /* |
1268 | ** Check whether expression 'e' is a literal integer in | | 1268 | ** Check whether expression 'e' is a literal integer in |
1269 | ** proper range to fit in register sC | | 1269 | ** proper range to fit in register sC |
1270 | */ | | 1270 | */ |
1271 | static int isSCint (expdesc *e) { | | 1271 | static int isSCint (expdesc *e) { |
1272 | return luaK_isKint(e) && fitsC(e->u.ival); | | 1272 | return luaK_isKint(e) && fitsC(e->u.ival); |
1273 | } | | 1273 | } |
1274 | | | 1274 | |
1275 | | | 1275 | |
1276 | /* | | 1276 | /* |
1277 | ** Check whether expression 'e' is a literal integer or float in | | 1277 | ** Check whether expression 'e' is a literal integer or float in |
1278 | ** proper range to fit in a register (sB or sC). | | 1278 | ** proper range to fit in a register (sB or sC). |
1279 | */ | | 1279 | */ |
1280 | static int isSCnumber (expdesc *e, int *pi, int *isfloat) { | | 1280 | static int isSCnumber (expdesc *e, int *pi, int *isfloat) { |
1281 | lua_Integer i; | | 1281 | lua_Integer i; |
1282 | if (e->k == VKINT) | | 1282 | if (e->k == VKINT) |
1283 | i = e->u.ival; | | 1283 | i = e->u.ival; |
1284 | #ifndef _KERNEL | | 1284 | #ifndef _KERNEL |
1285 | else if (e->k == VKFLT && luaV_flttointeger(e->u.nval, &i, F2Ieq)) | | 1285 | else if (e->k == VKFLT && luaV_flttointeger(e->u.nval, &i, F2Ieq)) |
1286 | *isfloat = 1; | | 1286 | *isfloat = 1; |
1287 | #endif /* _KERNEL */ | | 1287 | #endif /* _KERNEL */ |
1288 | else | | 1288 | else |
1289 | return 0; /* not a number */ | | 1289 | return 0; /* not a number */ |
1290 | if (!hasjumps(e) && fitsC(i)) { | | 1290 | if (!hasjumps(e) && fitsC(i)) { |
1291 | *pi = int2sC(cast_int(i)); | | 1291 | *pi = int2sC(cast_int(i)); |
1292 | return 1; | | 1292 | return 1; |
1293 | } | | 1293 | } |
1294 | else | | 1294 | else |
1295 | return 0; | | 1295 | return 0; |
1296 | } | | 1296 | } |
1297 | | | 1297 | |
1298 | | | 1298 | |
1299 | /* | | 1299 | /* |
1300 | ** Create expression 't[k]'. 't' must have its final result already in a | | 1300 | ** Create expression 't[k]'. 't' must have its final result already in a |
1301 | ** register or upvalue. Upvalues can only be indexed by literal strings. | | 1301 | ** register or upvalue. Upvalues can only be indexed by literal strings. |
1302 | ** Keys can be literal strings in the constant table or arbitrary | | 1302 | ** Keys can be literal strings in the constant table or arbitrary |
1303 | ** values in registers. | | 1303 | ** values in registers. |
1304 | */ | | 1304 | */ |
1305 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | | 1305 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
1306 | if (k->k == VKSTR) | | 1306 | if (k->k == VKSTR) |
1307 | str2K(fs, k); | | 1307 | str2K(fs, k); |
1308 | lua_assert(!hasjumps(t) && | | 1308 | lua_assert(!hasjumps(t) && |
1309 | (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); | | 1309 | (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); |
1310 | if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ | | 1310 | if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ |
1311 | luaK_exp2anyreg(fs, t); /* put it in a register */ | | 1311 | luaK_exp2anyreg(fs, t); /* put it in a register */ |
1312 | if (t->k == VUPVAL) { | | 1312 | if (t->k == VUPVAL) { |
1313 | t->u.ind.t = t->u.info; /* upvalue index */ | | 1313 | t->u.ind.t = t->u.info; /* upvalue index */ |
1314 | t->u.ind.idx = k->u.info; /* literal string */ | | 1314 | t->u.ind.idx = k->u.info; /* literal string */ |
1315 | t->k = VINDEXUP; | | 1315 | t->k = VINDEXUP; |
1316 | } | | 1316 | } |
1317 | else { | | 1317 | else { |
1318 | /* register index of the table */ | | 1318 | /* register index of the table */ |
1319 | t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info; | | 1319 | t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info; |
1320 | if (isKstr(fs, k)) { | | 1320 | if (isKstr(fs, k)) { |
1321 | t->u.ind.idx = k->u.info; /* literal string */ | | 1321 | t->u.ind.idx = k->u.info; /* literal string */ |
1322 | t->k = VINDEXSTR; | | 1322 | t->k = VINDEXSTR; |
1323 | } | | 1323 | } |
1324 | else if (isCint(k)) { | | 1324 | else if (isCint(k)) { |
1325 | t->u.ind.idx = cast_int(k->u.ival); /* int. constant in proper range */ | | 1325 | t->u.ind.idx = cast_int(k->u.ival); /* int. constant in proper range */ |
1326 | t->k = VINDEXI; | | 1326 | t->k = VINDEXI; |
1327 | } | | 1327 | } |
1328 | else { | | 1328 | else { |
1329 | t->u.ind.idx = luaK_exp2anyreg(fs, k); /* register */ | | 1329 | t->u.ind.idx = luaK_exp2anyreg(fs, k); /* register */ |
1330 | t->k = VINDEXED; | | 1330 | t->k = VINDEXED; |
1331 | } | | 1331 | } |
1332 | } | | 1332 | } |
1333 | } | | 1333 | } |
1334 | | | 1334 | |
1335 | | | 1335 | |
1336 | /* | | 1336 | /* |
1337 | ** Return false if folding can raise an error. | | 1337 | ** Return false if folding can raise an error. |
1338 | ** Bitwise operations need operands convertible to integers; division | | 1338 | ** Bitwise operations need operands convertible to integers; division |
1339 | ** operations cannot have 0 as divisor. | | 1339 | ** operations cannot have 0 as divisor. |
1340 | */ | | 1340 | */ |
1341 | static int validop (int op, TValue *v1, TValue *v2) { | | 1341 | static int validop (int op, TValue *v1, TValue *v2) { |
1342 | switch (op) { | | 1342 | switch (op) { |
1343 | case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: | | 1343 | case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: |
1344 | case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ | | 1344 | case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ |
1345 | lua_Integer i; | | 1345 | lua_Integer i; |
1346 | return (luaV_tointegerns(v1, &i, LUA_FLOORN2I) && | | 1346 | return (luaV_tointegerns(v1, &i, LUA_FLOORN2I) && |
1347 | luaV_tointegerns(v2, &i, LUA_FLOORN2I)); | | 1347 | luaV_tointegerns(v2, &i, LUA_FLOORN2I)); |
1348 | } | | 1348 | } |
1349 | #ifndef _KERNEL | | 1349 | #ifndef _KERNEL |
1350 | case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ | | 1350 | case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ |
1351 | #else /* _KERNEL */ | | 1351 | #else /* _KERNEL */ |
1352 | case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ | | 1352 | case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ |
1353 | #endif /* _KERNEL */ | | 1353 | #endif /* _KERNEL */ |
1354 | return (nvalue(v2) != 0); | | 1354 | return (nvalue(v2) != 0); |
1355 | default: return 1; /* everything else is valid */ | | 1355 | default: return 1; /* everything else is valid */ |
1356 | } | | 1356 | } |
1357 | } | | 1357 | } |
1358 | | | 1358 | |
1359 | | | 1359 | |
1360 | /* | | 1360 | /* |
1361 | ** Try to "constant-fold" an operation; return 1 iff successful. | | 1361 | ** Try to "constant-fold" an operation; return 1 iff successful. |
1362 | ** (In this case, 'e1' has the final result.) | | 1362 | ** (In this case, 'e1' has the final result.) |
1363 | */ | | 1363 | */ |
1364 | static int constfolding (FuncState *fs, int op, expdesc *e1, | | 1364 | static int constfolding (FuncState *fs, int op, expdesc *e1, |
1365 | const expdesc *e2) { | | 1365 | const expdesc *e2) { |
1366 | TValue v1, v2, res; | | 1366 | TValue v1, v2, res; |
1367 | if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) | | 1367 | if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) |
1368 | return 0; /* non-numeric operands or not safe to fold */ | | 1368 | return 0; /* non-numeric operands or not safe to fold */ |
1369 | luaO_rawarith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ | | 1369 | luaO_rawarith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ |
1370 | if (ttisinteger(&res)) { | | 1370 | if (ttisinteger(&res)) { |
1371 | e1->k = VKINT; | | 1371 | e1->k = VKINT; |
1372 | e1->u.ival = ivalue(&res); | | 1372 | e1->u.ival = ivalue(&res); |
1373 | } | | 1373 | } |
1374 | else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ | | 1374 | else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ |
1375 | #ifndef _KERNEL | | 1375 | #ifndef _KERNEL |
1376 | lua_Number n = fltvalue(&res); | | 1376 | lua_Number n = fltvalue(&res); |
1377 | if (luai_numisnan(n) || n == 0) | | 1377 | if (luai_numisnan(n) || n == 0) |
1378 | return 0; | | 1378 | return 0; |
1379 | e1->k = VKFLT; | | 1379 | e1->k = VKFLT; |
1380 | e1->u.nval = n; | | 1380 | e1->u.nval = n; |
1381 | #else /* _KERNEL */ | | 1381 | #else /* _KERNEL */ |
1382 | return 0; /* if it is not integer, we must fail */ | | 1382 | return 0; /* if it is not integer, we must fail */ |
1383 | #endif /* _KERNEL */ | | 1383 | #endif /* _KERNEL */ |
1384 | } | | 1384 | } |
1385 | return 1; | | 1385 | return 1; |
1386 | } | | 1386 | } |
1387 | | | 1387 | |
1388 | | | 1388 | |
1389 | /* | | 1389 | /* |
1390 | ** Emit code for unary expressions that "produce values" | | 1390 | ** Emit code for unary expressions that "produce values" |
1391 | ** (everything but 'not'). | | 1391 | ** (everything but 'not'). |
1392 | ** Expression to produce final result will be encoded in 'e'. | | 1392 | ** Expression to produce final result will be encoded in 'e'. |
1393 | */ | | 1393 | */ |
1394 | static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { | | 1394 | static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { |
1395 | int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ | | 1395 | int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ |
1396 | freeexp(fs, e); | | 1396 | freeexp(fs, e); |
1397 | e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ | | 1397 | e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ |
1398 | e->k = VRELOC; /* all those operations are relocatable */ | | 1398 | e->k = VRELOC; /* all those operations are relocatable */ |
1399 | luaK_fixline(fs, line); | | 1399 | luaK_fixline(fs, line); |
1400 | } | | 1400 | } |
1401 | | | 1401 | |
1402 | | | 1402 | |
1403 | /* | | 1403 | /* |
1404 | ** Emit code for binary expressions that "produce values" | | 1404 | ** Emit code for binary expressions that "produce values" |
1405 | ** (everything but logical operators 'and'/'or' and comparison | | 1405 | ** (everything but logical operators 'and'/'or' and comparison |
1406 | ** operators). | | 1406 | ** operators). |
1407 | ** Expression to produce final result will be encoded in 'e1'. | | 1407 | ** Expression to produce final result will be encoded in 'e1'. |
1408 | */ | | 1408 | */ |
1409 | static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, | | 1409 | static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, |
1410 | OpCode op, int v2, int flip, int line, | | 1410 | OpCode op, int v2, int flip, int line, |
1411 | OpCode mmop, TMS event) { | | 1411 | OpCode mmop, TMS event) { |
1412 | int v1 = luaK_exp2anyreg(fs, e1); | | 1412 | int v1 = luaK_exp2anyreg(fs, e1); |
1413 | int pc = luaK_codeABCk(fs, op, 0, v1, v2, 0); | | 1413 | int pc = luaK_codeABCk(fs, op, 0, v1, v2, 0); |
1414 | freeexps(fs, e1, e2); | | 1414 | freeexps(fs, e1, e2); |
1415 | e1->u.info = pc; | | 1415 | e1->u.info = pc; |
1416 | e1->k = VRELOC; /* all those operations are relocatable */ | | 1416 | e1->k = VRELOC; /* all those operations are relocatable */ |
1417 | luaK_fixline(fs, line); | | 1417 | luaK_fixline(fs, line); |
1418 | luaK_codeABCk(fs, mmop, v1, v2, event, flip); /* to call metamethod */ | | 1418 | luaK_codeABCk(fs, mmop, v1, v2, event, flip); /* to call metamethod */ |
1419 | luaK_fixline(fs, line); | | 1419 | luaK_fixline(fs, line); |
1420 | } | | 1420 | } |
1421 | | | 1421 | |
1422 | | | 1422 | |
1423 | /* | | 1423 | /* |
1424 | ** Emit code for binary expressions that "produce values" over | | 1424 | ** Emit code for binary expressions that "produce values" over |
1425 | ** two registers. | | 1425 | ** two registers. |
1426 | */ | | 1426 | */ |
1427 | static void codebinexpval (FuncState *fs, OpCode op, | | 1427 | static void codebinexpval (FuncState *fs, OpCode op, |
1428 | expdesc *e1, expdesc *e2, int line) { | | 1428 | expdesc *e1, expdesc *e2, int line) { |
1429 | int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ | | 1429 | int v2 = luaK_exp2anyreg(fs, e2); /* make sure 'e2' is in a register */ |
| | | 1430 | /* 'e1' must be already in a register or it is a constant */ |
| | | 1431 | lua_assert((VNIL <= e1->k && e1->k <= VKSTR) || |
| | | 1432 | e1->k == VNONRELOC || e1->k == VRELOC); |
1430 | lua_assert(OP_ADD <= op && op <= OP_SHR); | | 1433 | lua_assert(OP_ADD <= op && op <= OP_SHR); |
1431 | finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, | | 1434 | finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, |
1432 | cast(TMS, (op - OP_ADD) + TM_ADD)); | | 1435 | cast(TMS, (op - OP_ADD) + TM_ADD)); |
1433 | } | | 1436 | } |
1434 | | | 1437 | |
1435 | | | 1438 | |
1436 | /* | | 1439 | /* |
1437 | ** Code binary operators with immediate operands. | | 1440 | ** Code binary operators with immediate operands. |
1438 | */ | | 1441 | */ |
1439 | static void codebini (FuncState *fs, OpCode op, | | 1442 | static void codebini (FuncState *fs, OpCode op, |
1440 | expdesc *e1, expdesc *e2, int flip, int line, | | 1443 | expdesc *e1, expdesc *e2, int flip, int line, |
1441 | TMS event) { | | 1444 | TMS event) { |
1442 | int v2 = int2sC(cast_int(e2->u.ival)); /* immediate operand */ | | 1445 | int v2 = int2sC(cast_int(e2->u.ival)); /* immediate operand */ |
1443 | lua_assert(e2->k == VKINT); | | 1446 | lua_assert(e2->k == VKINT); |
1444 | finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINI, event); | | 1447 | finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINI, event); |
1445 | } | | 1448 | } |
1446 | | | 1449 | |
1447 | | | 1450 | |
1448 | /* Try to code a binary operator negating its second operand. | | 1451 | /* Try to code a binary operator negating its second operand. |
1449 | ** For the metamethod, 2nd operand must keep its original value. | | 1452 | ** For the metamethod, 2nd operand must keep its original value. |
1450 | */ | | 1453 | */ |
1451 | static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, | | 1454 | static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, |
1452 | OpCode op, int line, TMS event) { | | 1455 | OpCode op, int line, TMS event) { |
1453 | if (!luaK_isKint(e2)) | | 1456 | if (!luaK_isKint(e2)) |
1454 | return 0; /* not an integer constant */ | | 1457 | return 0; /* not an integer constant */ |
1455 | else { | | 1458 | else { |
1456 | lua_Integer i2 = e2->u.ival; | | 1459 | lua_Integer i2 = e2->u.ival; |
1457 | if (!(fitsC(i2) && fitsC(-i2))) | | 1460 | if (!(fitsC(i2) && fitsC(-i2))) |
1458 | return 0; /* not in the proper range */ | | 1461 | return 0; /* not in the proper range */ |
1459 | else { /* operating a small integer constant */ | | 1462 | else { /* operating a small integer constant */ |
1460 | int v2 = cast_int(i2); | | 1463 | int v2 = cast_int(i2); |
1461 | finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); | | 1464 | finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); |
1462 | /* correct metamethod argument */ | | 1465 | /* correct metamethod argument */ |
1463 | SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); | | 1466 | SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); |
1464 | return 1; /* successfully coded */ | | 1467 | return 1; /* successfully coded */ |
1465 | } | | 1468 | } |
1466 | } | | 1469 | } |
1467 | } | | 1470 | } |
1468 | | | 1471 | |
1469 | | | 1472 | |
1470 | static void swapexps (expdesc *e1, expdesc *e2) { | | 1473 | static void swapexps (expdesc *e1, expdesc *e2) { |
1471 | expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ | | 1474 | expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ |
1472 | } | | 1475 | } |
1473 | | | 1476 | |
1474 | | | 1477 | |
1475 | /* | | 1478 | /* |
1476 | ** Code arithmetic operators ('+', '-', ...). If second operand is a | | 1479 | ** Code arithmetic operators ('+', '-', ...). If second operand is a |
1477 | ** constant in the proper range, use variant opcodes with K operands. | | 1480 | ** constant in the proper range, use variant opcodes with K operands. |
1478 | */ | | 1481 | */ |
1479 | static void codearith (FuncState *fs, BinOpr opr, | | 1482 | static void codearith (FuncState *fs, BinOpr opr, |
1480 | expdesc *e1, expdesc *e2, int flip, int line) { | | 1483 | expdesc *e1, expdesc *e2, int flip, int line) { |
1481 | TMS event = cast(TMS, opr + TM_ADD); | | 1484 | TMS event = cast(TMS, opr + TM_ADD); |
1482 | if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ | | 1485 | if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ |
1483 | int v2 = e2->u.info; /* K index */ | | 1486 | int v2 = e2->u.info; /* K index */ |
1484 | OpCode op = cast(OpCode, opr + OP_ADDK); | | 1487 | OpCode op = cast(OpCode, opr + OP_ADDK); |
1485 | finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); | | 1488 | finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); |
1486 | } | | 1489 | } |
1487 | else { /* 'e2' is neither an immediate nor a K operand */ | | 1490 | else { /* 'e2' is neither an immediate nor a K operand */ |
1488 | OpCode op = cast(OpCode, opr + OP_ADD); | | 1491 | OpCode op = cast(OpCode, opr + OP_ADD); |
1489 | if (flip) | | 1492 | if (flip) |
1490 | swapexps(e1, e2); /* back to original order */ | | 1493 | swapexps(e1, e2); /* back to original order */ |
1491 | codebinexpval(fs, op, e1, e2, line); /* use standard operators */ | | 1494 | codebinexpval(fs, op, e1, e2, line); /* use standard operators */ |
1492 | } | | 1495 | } |
1493 | } | | 1496 | } |
1494 | | | 1497 | |
1495 | | | 1498 | |
1496 | /* | | 1499 | /* |
1497 | ** Code commutative operators ('+', '*'). If first operand is a | | 1500 | ** Code commutative operators ('+', '*'). If first operand is a |
1498 | ** numeric constant, change order of operands to try to use an | | 1501 | ** numeric constant, change order of operands to try to use an |
1499 | ** immediate or K operator. | | 1502 | ** immediate or K operator. |
1500 | */ | | 1503 | */ |
1501 | static void codecommutative (FuncState *fs, BinOpr op, | | 1504 | static void codecommutative (FuncState *fs, BinOpr op, |
1502 | expdesc *e1, expdesc *e2, int line) { | | 1505 | expdesc *e1, expdesc *e2, int line) { |
1503 | int flip = 0; | | 1506 | int flip = 0; |
1504 | if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ | | 1507 | if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ |
1505 | swapexps(e1, e2); /* change order */ | | 1508 | swapexps(e1, e2); /* change order */ |
1506 | flip = 1; | | 1509 | flip = 1; |
1507 | } | | 1510 | } |
1508 | if (op == OPR_ADD && isSCint(e2)) /* immediate operand? */ | | 1511 | if (op == OPR_ADD && isSCint(e2)) /* immediate operand? */ |
1509 | codebini(fs, cast(OpCode, OP_ADDI), e1, e2, flip, line, TM_ADD); | | 1512 | codebini(fs, cast(OpCode, OP_ADDI), e1, e2, flip, line, TM_ADD); |
1510 | else | | 1513 | else |
1511 | codearith(fs, op, e1, e2, flip, line); | | 1514 | codearith(fs, op, e1, e2, flip, line); |
1512 | } | | 1515 | } |
1513 | | | 1516 | |
1514 | | | 1517 | |
1515 | /* | | 1518 | /* |
1516 | ** Code bitwise operations; they are all associative, so the function | | 1519 | ** Code bitwise operations; they are all commutative, so the function |
1517 | ** tries to put an integer constant as the 2nd operand (a K operand). | | 1520 | ** tries to put an integer constant as the 2nd operand (a K operand). |
1518 | */ | | 1521 | */ |
1519 | static void codebitwise (FuncState *fs, BinOpr opr, | | 1522 | static void codebitwise (FuncState *fs, BinOpr opr, |
1520 | expdesc *e1, expdesc *e2, int line) { | | 1523 | expdesc *e1, expdesc *e2, int line) { |
1521 | int flip = 0; | | 1524 | int flip = 0; |
1522 | int v2; | | 1525 | int v2; |
1523 | OpCode op; | | 1526 | OpCode op; |
1524 | if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { | | 1527 | if (e1->k == VKINT && luaK_exp2K(fs, e1)) { |
1525 | swapexps(e1, e2); /* 'e2' will be the constant operand */ | | 1528 | swapexps(e1, e2); /* 'e2' will be the constant operand */ |
1526 | flip = 1; | | 1529 | flip = 1; |
1527 | } | | 1530 | } |
1528 | else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ | | 1531 | else if (!(e2->k == VKINT && luaK_exp2K(fs, e2))) { /* no constants? */ |
1529 | op = cast(OpCode, opr + OP_ADD); | | 1532 | op = cast(OpCode, opr + OP_ADD); |
1530 | codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ | | 1533 | codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ |
1531 | return; | | 1534 | return; |
1532 | } | | 1535 | } |
1533 | v2 = e2->u.info; /* index in K array */ | | 1536 | v2 = e2->u.info; /* index in K array */ |
1534 | op = cast(OpCode, opr + OP_ADDK); | | 1537 | op = cast(OpCode, opr + OP_ADDK); |
1535 | lua_assert(ttisinteger(&fs->f->k[v2])); | | 1538 | lua_assert(ttisinteger(&fs->f->k[v2])); |
1536 | finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, | | 1539 | finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, |
1537 | cast(TMS, opr + TM_ADD)); | | 1540 | cast(TMS, opr + TM_ADD)); |
1538 | } | | 1541 | } |
1539 | | | 1542 | |
1540 | | | 1543 | |
1541 | /* | | 1544 | /* |
1542 | ** Emit code for order comparisons. When using an immediate operand, | | 1545 | ** Emit code for order comparisons. When using an immediate operand, |
1543 | ** 'isfloat' tells whether the original value was a float. | | 1546 | ** 'isfloat' tells whether the original value was a float. |
1544 | */ | | 1547 | */ |
1545 | static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | | 1548 | static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { |
1546 | int r1, r2; | | 1549 | int r1, r2; |
1547 | int im; | | 1550 | int im; |
1548 | int isfloat = 0; | | 1551 | int isfloat = 0; |
1549 | if (isSCnumber(e2, &im, &isfloat)) { | | 1552 | if (isSCnumber(e2, &im, &isfloat)) { |
1550 | /* use immediate operand */ | | 1553 | /* use immediate operand */ |
1551 | r1 = luaK_exp2anyreg(fs, e1); | | 1554 | r1 = luaK_exp2anyreg(fs, e1); |
1552 | r2 = im; | | 1555 | r2 = im; |
1553 | op = cast(OpCode, (op - OP_LT) + OP_LTI); | | 1556 | op = cast(OpCode, (op - OP_LT) + OP_LTI); |
1554 | } | | 1557 | } |
1555 | else if (isSCnumber(e1, &im, &isfloat)) { | | 1558 | else if (isSCnumber(e1, &im, &isfloat)) { |
1556 | /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ | | 1559 | /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ |
1557 | r1 = luaK_exp2anyreg(fs, e2); | | 1560 | r1 = luaK_exp2anyreg(fs, e2); |
1558 | r2 = im; | | 1561 | r2 = im; |
1559 | op = (op == OP_LT) ? OP_GTI : OP_GEI; | | 1562 | op = (op == OP_LT) ? OP_GTI : OP_GEI; |
1560 | } | | 1563 | } |
1561 | else { /* regular case, compare two registers */ | | 1564 | else { /* regular case, compare two registers */ |
1562 | r1 = luaK_exp2anyreg(fs, e1); | | 1565 | r1 = luaK_exp2anyreg(fs, e1); |
1563 | r2 = luaK_exp2anyreg(fs, e2); | | 1566 | r2 = luaK_exp2anyreg(fs, e2); |
1564 | } | | 1567 | } |
1565 | freeexps(fs, e1, e2); | | 1568 | freeexps(fs, e1, e2); |
1566 | e1->u.info = condjump(fs, op, r1, r2, isfloat, 1); | | 1569 | e1->u.info = condjump(fs, op, r1, r2, isfloat, 1); |
1567 | e1->k = VJMP; | | 1570 | e1->k = VJMP; |
1568 | } | | 1571 | } |
1569 | | | 1572 | |
1570 | | | 1573 | |
1571 | /* | | 1574 | /* |
1572 | ** Emit code for equality comparisons ('==', '~='). | | 1575 | ** Emit code for equality comparisons ('==', '~='). |
1573 | ** 'e1' was already put as RK by 'luaK_infix'. | | 1576 | ** 'e1' was already put as RK by 'luaK_infix'. |
1574 | */ | | 1577 | */ |
1575 | static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | | 1578 | static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { |
1576 | int r1, r2; | | 1579 | int r1, r2; |
1577 | int im; | | 1580 | int im; |
1578 | int isfloat = 0; /* not needed here, but kept for symmetry */ | | 1581 | int isfloat = 0; /* not needed here, but kept for symmetry */ |
1579 | OpCode op; | | 1582 | OpCode op; |
1580 | if (e1->k != VNONRELOC) { | | 1583 | if (e1->k != VNONRELOC) { |
1581 | lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT); | | 1584 | lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT); |
1582 | swapexps(e1, e2); | | 1585 | swapexps(e1, e2); |
1583 | } | | 1586 | } |
1584 | r1 = luaK_exp2anyreg(fs, e1); /* 1st expression must be in register */ | | 1587 | r1 = luaK_exp2anyreg(fs, e1); /* 1st expression must be in register */ |
1585 | if (isSCnumber(e2, &im, &isfloat)) { | | 1588 | if (isSCnumber(e2, &im, &isfloat)) { |
1586 | op = OP_EQI; | | 1589 | op = OP_EQI; |
1587 | r2 = im; /* immediate operand */ | | 1590 | r2 = im; /* immediate operand */ |
1588 | } | | 1591 | } |
1589 | else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */ | | 1592 | else if (luaK_exp2RK(fs, e2)) { /* 2nd expression is constant? */ |
1590 | op = OP_EQK; | | 1593 | op = OP_EQK; |
1591 | r2 = e2->u.info; /* constant index */ | | 1594 | r2 = e2->u.info; /* constant index */ |
1592 | } | | 1595 | } |
1593 | else { | | 1596 | else { |
1594 | op = OP_EQ; /* will compare two registers */ | | 1597 | op = OP_EQ; /* will compare two registers */ |
1595 | r2 = luaK_exp2anyreg(fs, e2); | | 1598 | r2 = luaK_exp2anyreg(fs, e2); |
1596 | } | | 1599 | } |
1597 | freeexps(fs, e1, e2); | | 1600 | freeexps(fs, e1, e2); |
1598 | e1->u.info = condjump(fs, op, r1, r2, isfloat, (opr == OPR_EQ)); | | 1601 | e1->u.info = condjump(fs, op, r1, r2, isfloat, (opr == OPR_EQ)); |
1599 | e1->k = VJMP; | | 1602 | e1->k = VJMP; |
1600 | } | | 1603 | } |
1601 | | | 1604 | |
1602 | | | 1605 | |
1603 | /* | | 1606 | /* |
1604 | ** Apply prefix operation 'op' to expression 'e'. | | 1607 | ** Apply prefix operation 'op' to expression 'e'. |
1605 | */ | | 1608 | */ |
1606 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { | | 1609 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { |
1607 | static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; | | 1610 | static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; |
1608 | luaK_dischargevars(fs, e); | | 1611 | luaK_dischargevars(fs, e); |
1609 | switch (op) { | | 1612 | switch (op) { |
1610 | case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ | | 1613 | case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ |
1611 | if (constfolding(fs, op + LUA_OPUNM, e, &ef)) | | 1614 | if (constfolding(fs, op + LUA_OPUNM, e, &ef)) |
1612 | break; | | 1615 | break; |
1613 | /* else */ /* FALLTHROUGH */ | | 1616 | /* else */ /* FALLTHROUGH */ |
1614 | case OPR_LEN: | | 1617 | case OPR_LEN: |
1615 | codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); | | 1618 | codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); |
1616 | break; | | 1619 | break; |
1617 | case OPR_NOT: codenot(fs, e); break; | | 1620 | case OPR_NOT: codenot(fs, e); break; |
1618 | default: lua_assert(0); | | 1621 | default: lua_assert(0); |
1619 | } | | 1622 | } |
1620 | } | | 1623 | } |
1621 | | | 1624 | |
1622 | | | 1625 | |
1623 | /* | | 1626 | /* |
1624 | ** Process 1st operand 'v' of binary operation 'op' before reading | | 1627 | ** Process 1st operand 'v' of binary operation 'op' before reading |
1625 | ** 2nd operand. | | 1628 | ** 2nd operand. |
1626 | */ | | 1629 | */ |
1627 | void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | | 1630 | void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { |
1628 | luaK_dischargevars(fs, v); | | 1631 | luaK_dischargevars(fs, v); |
1629 | switch (op) { | | 1632 | switch (op) { |
1630 | case OPR_AND: { | | 1633 | case OPR_AND: { |
1631 | luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ | | 1634 | luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ |
1632 | break; | | 1635 | break; |
1633 | } | | 1636 | } |
1634 | case OPR_OR: { | | 1637 | case OPR_OR: { |
1635 | luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ | | 1638 | luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ |
1636 | break; | | 1639 | break; |
1637 | } | | 1640 | } |
1638 | case OPR_CONCAT: { | | 1641 | case OPR_CONCAT: { |
1639 | luaK_exp2nextreg(fs, v); /* operand must be on the stack */ | | 1642 | luaK_exp2nextreg(fs, v); /* operand must be on the stack */ |
1640 | break; | | 1643 | break; |
1641 | } | | 1644 | } |
1642 | case OPR_ADD: case OPR_SUB: | | 1645 | case OPR_ADD: case OPR_SUB: |
1643 | #ifndef _KERNEL | | 1646 | #ifndef _KERNEL |
1644 | case OPR_MUL: case OPR_DIV: case OPR_IDIV: | | 1647 | case OPR_MUL: case OPR_DIV: case OPR_IDIV: |
1645 | case OPR_MOD: case OPR_POW: | | 1648 | case OPR_MOD: case OPR_POW: |
1646 | #else /* _KERNEL */ | | 1649 | #else /* _KERNEL */ |
1647 | case OPR_MUL: case OPR_IDIV: | | 1650 | case OPR_MUL: case OPR_IDIV: |
1648 | case OPR_MOD: | | 1651 | case OPR_MOD: |
1649 | #endif /* _KERNEL */ | | 1652 | #endif /* _KERNEL */ |
1650 | case OPR_BAND: case OPR_BOR: case OPR_BXOR: | | 1653 | case OPR_BAND: case OPR_BOR: case OPR_BXOR: |
1651 | case OPR_SHL: case OPR_SHR: { | | 1654 | case OPR_SHL: case OPR_SHR: { |
1652 | if (!tonumeral(v, NULL)) | | 1655 | if (!tonumeral(v, NULL)) |
1653 | luaK_exp2anyreg(fs, v); | | 1656 | luaK_exp2anyreg(fs, v); |
1654 | /* else keep numeral, which may be folded with 2nd operand */ | | 1657 | /* else keep numeral, which may be folded or used as an immediate |
| | | 1658 | operand */ |
1655 | break; | | 1659 | break; |
1656 | } | | 1660 | } |
1657 | case OPR_EQ: case OPR_NE: { | | 1661 | case OPR_EQ: case OPR_NE: { |
1658 | if (!tonumeral(v, NULL)) | | 1662 | if (!tonumeral(v, NULL)) |
1659 | luaK_exp2RK(fs, v); | | 1663 | luaK_exp2RK(fs, v); |
1660 | /* else keep numeral, which may be an immediate operand */ | | 1664 | /* else keep numeral, which may be an immediate operand */ |
1661 | break; | | 1665 | break; |
1662 | } | | 1666 | } |
1663 | case OPR_LT: case OPR_LE: | | 1667 | case OPR_LT: case OPR_LE: |
1664 | case OPR_GT: case OPR_GE: { | | 1668 | case OPR_GT: case OPR_GE: { |
1665 | int dummy, dummy2; | | 1669 | int dummy, dummy2; |
1666 | if (!isSCnumber(v, &dummy, &dummy2)) | | 1670 | if (!isSCnumber(v, &dummy, &dummy2)) |
1667 | luaK_exp2anyreg(fs, v); | | 1671 | luaK_exp2anyreg(fs, v); |
1668 | /* else keep numeral, which may be an immediate operand */ | | 1672 | /* else keep numeral, which may be an immediate operand */ |
1669 | break; | | 1673 | break; |
1670 | } | | 1674 | } |
1671 | default: lua_assert(0); | | 1675 | default: lua_assert(0); |
1672 | } | | 1676 | } |
1673 | } | | 1677 | } |
1674 | | | 1678 | |
1675 | /* | | 1679 | /* |
1676 | ** Create code for '(e1 .. e2)'. | | 1680 | ** Create code for '(e1 .. e2)'. |
1677 | ** For '(e1 .. e2.1 .. e2.2)' (which is '(e1 .. (e2.1 .. e2.2))', | | 1681 | ** For '(e1 .. e2.1 .. e2.2)' (which is '(e1 .. (e2.1 .. e2.2))', |
1678 | ** because concatenation is right associative), merge both CONCATs. | | 1682 | ** because concatenation is right associative), merge both CONCATs. |
1679 | */ | | 1683 | */ |
1680 | static void codeconcat (FuncState *fs, expdesc *e1, expdesc *e2, int line) { | | 1684 | static void codeconcat (FuncState *fs, expdesc *e1, expdesc *e2, int line) { |
1681 | Instruction *ie2 = previousinstruction(fs); | | 1685 | Instruction *ie2 = previousinstruction(fs); |
1682 | if (GET_OPCODE(*ie2) == OP_CONCAT) { /* is 'e2' a concatenation? */ | | 1686 | if (GET_OPCODE(*ie2) == OP_CONCAT) { /* is 'e2' a concatenation? */ |
1683 | int n = GETARG_B(*ie2); /* # of elements concatenated in 'e2' */ | | 1687 | int n = GETARG_B(*ie2); /* # of elements concatenated in 'e2' */ |
1684 | lua_assert(e1->u.info + 1 == GETARG_A(*ie2)); | | 1688 | lua_assert(e1->u.info + 1 == GETARG_A(*ie2)); |
1685 | freeexp(fs, e2); | | 1689 | freeexp(fs, e2); |
1686 | SETARG_A(*ie2, e1->u.info); /* correct first element ('e1') */ | | 1690 | SETARG_A(*ie2, e1->u.info); /* correct first element ('e1') */ |
1687 | SETARG_B(*ie2, n + 1); /* will concatenate one more element */ | | 1691 | SETARG_B(*ie2, n + 1); /* will concatenate one more element */ |
1688 | } | | 1692 | } |
1689 | else { /* 'e2' is not a concatenation */ | | 1693 | else { /* 'e2' is not a concatenation */ |
1690 | luaK_codeABC(fs, OP_CONCAT, e1->u.info, 2, 0); /* new concat opcode */ | | 1694 | luaK_codeABC(fs, OP_CONCAT, e1->u.info, 2, 0); /* new concat opcode */ |
1691 | freeexp(fs, e2); | | 1695 | freeexp(fs, e2); |
1692 | luaK_fixline(fs, line); | | 1696 | luaK_fixline(fs, line); |
1693 | } | | 1697 | } |
1694 | } | | 1698 | } |
1695 | | | 1699 | |
1696 | | | 1700 | |
1697 | /* | | 1701 | /* |
1698 | ** Finalize code for binary operation, after reading 2nd operand. | | 1702 | ** Finalize code for binary operation, after reading 2nd operand. |
1699 | */ | | 1703 | */ |
1700 | void luaK_posfix (FuncState *fs, BinOpr opr, | | 1704 | void luaK_posfix (FuncState *fs, BinOpr opr, |
1701 | expdesc *e1, expdesc *e2, int line) { | | 1705 | expdesc *e1, expdesc *e2, int line) { |
1702 | luaK_dischargevars(fs, e2); | | 1706 | luaK_dischargevars(fs, e2); |
1703 | if (foldbinop(opr) && constfolding(fs, opr + LUA_OPADD, e1, e2)) | | 1707 | if (foldbinop(opr) && constfolding(fs, opr + LUA_OPADD, e1, e2)) |
1704 | return; /* done by folding */ | | 1708 | return; /* done by folding */ |
1705 | switch (opr) { | | 1709 | switch (opr) { |
1706 | case OPR_AND: { | | 1710 | case OPR_AND: { |
1707 | lua_assert(e1->t == NO_JUMP); /* list closed by 'luaK_infix' */ | | 1711 | lua_assert(e1->t == NO_JUMP); /* list closed by 'luaK_infix' */ |
1708 | luaK_concat(fs, &e2->f, e1->f); | | 1712 | luaK_concat(fs, &e2->f, e1->f); |
1709 | *e1 = *e2; | | 1713 | *e1 = *e2; |
1710 | break; | | 1714 | break; |
1711 | } | | 1715 | } |
1712 | case OPR_OR: { | | 1716 | case OPR_OR: { |
1713 | lua_assert(e1->f == NO_JUMP); /* list closed by 'luaK_infix' */ | | 1717 | lua_assert(e1->f == NO_JUMP); /* list closed by 'luaK_infix' */ |
1714 | luaK_concat(fs, &e2->t, e1->t); | | 1718 | luaK_concat(fs, &e2->t, e1->t); |
1715 | *e1 = *e2; | | 1719 | *e1 = *e2; |
1716 | break; | | 1720 | break; |
1717 | } | | 1721 | } |
1718 | case OPR_CONCAT: { /* e1 .. e2 */ | | 1722 | case OPR_CONCAT: { /* e1 .. e2 */ |
1719 | luaK_exp2nextreg(fs, e2); | | 1723 | luaK_exp2nextreg(fs, e2); |
1720 | codeconcat(fs, e1, e2, line); | | 1724 | codeconcat(fs, e1, e2, line); |
1721 | break; | | 1725 | break; |
1722 | } | | 1726 | } |
1723 | case OPR_ADD: case OPR_MUL: { | | 1727 | case OPR_ADD: case OPR_MUL: { |
1724 | codecommutative(fs, opr, e1, e2, line); | | 1728 | codecommutative(fs, opr, e1, e2, line); |
1725 | break; | | 1729 | break; |
1726 | } | | 1730 | } |
1727 | case OPR_SUB: { | | 1731 | case OPR_SUB: { |
1728 | if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB)) | | 1732 | if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB)) |
1729 | break; /* coded as (r1 + -I) */ | | 1733 | break; /* coded as (r1 + -I) */ |
1730 | /* ELSE */ | | 1734 | /* ELSE */ |
1731 | } /* FALLTHROUGH */ | | 1735 | } /* FALLTHROUGH */ |
1732 | #ifndef _KERNEL | | 1736 | #ifndef _KERNEL |
1733 | case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { | | 1737 | case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { |
1734 | #else /* _KERNEL */ | | 1738 | #else /* _KERNEL */ |
1735 | case OPR_IDIV: case OPR_MOD: { | | 1739 | case OPR_IDIV: case OPR_MOD: { |
1736 | #endif | | 1740 | #endif |
1737 | codearith(fs, opr, e1, e2, 0, line); | | 1741 | codearith(fs, opr, e1, e2, 0, line); |
1738 | break; | | 1742 | break; |
1739 | } | | 1743 | } |
1740 | case OPR_BAND: case OPR_BOR: case OPR_BXOR: { | | 1744 | case OPR_BAND: case OPR_BOR: case OPR_BXOR: { |
1741 | codebitwise(fs, opr, e1, e2, line); | | 1745 | codebitwise(fs, opr, e1, e2, line); |
1742 | break; | | 1746 | break; |
1743 | } | | 1747 | } |
1744 | case OPR_SHL: { | | 1748 | case OPR_SHL: { |
1745 | if (isSCint(e1)) { | | 1749 | if (isSCint(e1)) { |
1746 | swapexps(e1, e2); | | 1750 | swapexps(e1, e2); |
1747 | codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */ | | 1751 | codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */ |
1748 | } | | 1752 | } |
1749 | else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) { | | 1753 | else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) { |
1750 | /* coded as (r1 >> -I) */; | | 1754 | /* coded as (r1 >> -I) */; |
1751 | } | | 1755 | } |
1752 | else /* regular case (two registers) */ | | 1756 | else /* regular case (two registers) */ |
1753 | codebinexpval(fs, OP_SHL, e1, e2, line); | | 1757 | codebinexpval(fs, OP_SHL, e1, e2, line); |
1754 | break; | | 1758 | break; |
1755 | } | | 1759 | } |
1756 | case OPR_SHR: { | | 1760 | case OPR_SHR: { |
1757 | if (isSCint(e2)) | | 1761 | if (isSCint(e2)) |
1758 | codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ | | 1762 | codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ |
1759 | else /* regular case (two registers) */ | | 1763 | else /* regular case (two registers) */ |
1760 | codebinexpval(fs, OP_SHR, e1, e2, line); | | 1764 | codebinexpval(fs, OP_SHR, e1, e2, line); |
1761 | break; | | 1765 | break; |
1762 | } | | 1766 | } |
1763 | case OPR_EQ: case OPR_NE: { | | 1767 | case OPR_EQ: case OPR_NE: { |
1764 | codeeq(fs, opr, e1, e2); | | 1768 | codeeq(fs, opr, e1, e2); |
1765 | break; | | 1769 | break; |
1766 | } | | 1770 | } |
1767 | case OPR_LT: case OPR_LE: { | | 1771 | case OPR_LT: case OPR_LE: { |
1768 | OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); | | 1772 | OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); |
1769 | codeorder(fs, op, e1, e2); | | 1773 | codeorder(fs, op, e1, e2); |
1770 | break; | | 1774 | break; |
1771 | } | | 1775 | } |
1772 | case OPR_GT: case OPR_GE: { | | 1776 | case OPR_GT: case OPR_GE: { |
1773 | /* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */ | | 1777 | /* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */ |
1774 | OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); | | 1778 | OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); |
1775 | swapexps(e1, e2); | | 1779 | swapexps(e1, e2); |
1776 | codeorder(fs, op, e1, e2); | | 1780 | codeorder(fs, op, e1, e2); |
1777 | break; | | 1781 | break; |
1778 | } | | 1782 | } |
1779 | default: lua_assert(0); | | 1783 | default: lua_assert(0); |
1780 | } | | 1784 | } |
1781 | } | | 1785 | } |
1782 | | | 1786 | |
1783 | | | 1787 | |
1784 | /* | | 1788 | /* |
1785 | ** Change line information associated with current position, by removing | | 1789 | ** Change line information associated with current position, by removing |
1786 | ** previous info and adding it again with new line. | | 1790 | ** previous info and adding it again with new line. |
1787 | */ | | 1791 | */ |
1788 | void luaK_fixline (FuncState *fs, int line) { | | 1792 | void luaK_fixline (FuncState *fs, int line) { |
1789 | removelastlineinfo(fs); | | 1793 | removelastlineinfo(fs); |
1790 | savelineinfo(fs, fs->f, line); | | 1794 | savelineinfo(fs, fs->f, line); |
1791 | } | | 1795 | } |
1792 | | | 1796 | |
1793 | | | 1797 | |
1794 | void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) { | | 1798 | void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) { |
1795 | Instruction *inst = &fs->f->code[pc]; | | 1799 | Instruction *inst = &fs->f->code[pc]; |
1796 | int rb = (hsize != 0) ? luaO_ceillog2(hsize) + 1 : 0; /* hash size */ | | 1800 | int rb = (hsize != 0) ? luaO_ceillog2(hsize) + 1 : 0; /* hash size */ |
1797 | int extra = asize / (MAXARG_C + 1); /* higher bits of array size */ | | 1801 | int extra = asize / (MAXARG_C + 1); /* higher bits of array size */ |
1798 | int rc = asize % (MAXARG_C + 1); /* lower bits of array size */ | | 1802 | int rc = asize % (MAXARG_C + 1); /* lower bits of array size */ |
1799 | int k = (extra > 0); /* true iff needs extra argument */ | | 1803 | int k = (extra > 0); /* true iff needs extra argument */ |
1800 | *inst = CREATE_ABCk(OP_NEWTABLE, ra, rb, rc, k); | | 1804 | *inst = CREATE_ABCk(OP_NEWTABLE, ra, rb, rc, k); |
1801 | *(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra); | | 1805 | *(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra); |
1802 | } | | 1806 | } |
1803 | | | 1807 | |
1804 | | | 1808 | |
1805 | /* | | 1809 | /* |
1806 | ** Emit a SETLIST instruction. | | 1810 | ** Emit a SETLIST instruction. |
1807 | ** 'base' is register that keeps table; | | 1811 | ** 'base' is register that keeps table; |
1808 | ** 'nelems' is #table plus those to be stored now; | | 1812 | ** 'nelems' is #table plus those to be stored now; |
1809 | ** 'tostore' is number of values (in registers 'base + 1',...) to add to | | 1813 | ** 'tostore' is number of values (in registers 'base + 1',...) to add to |
1810 | ** table (or LUA_MULTRET to add up to stack top). | | 1814 | ** table (or LUA_MULTRET to add up to stack top). |
1811 | */ | | 1815 | */ |
1812 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { | | 1816 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { |
1813 | lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); | | 1817 | lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); |
1814 | if (tostore == LUA_MULTRET) | | 1818 | if (tostore == LUA_MULTRET) |
1815 | tostore = 0; | | 1819 | tostore = 0; |
1816 | if (nelems <= MAXARG_C) | | 1820 | if (nelems <= MAXARG_C) |
1817 | luaK_codeABC(fs, OP_SETLIST, base, tostore, nelems); | | 1821 | luaK_codeABC(fs, OP_SETLIST, base, tostore, nelems); |
1818 | else { | | 1822 | else { |
1819 | int extra = nelems / (MAXARG_C + 1); | | 1823 | int extra = nelems / (MAXARG_C + 1); |
1820 | nelems %= (MAXARG_C + 1); | | 1824 | nelems %= (MAXARG_C + 1); |
1821 | luaK_codeABCk(fs, OP_SETLIST, base, tostore, nelems, 1); | | 1825 | luaK_codeABCk(fs, OP_SETLIST, base, tostore, nelems, 1); |
1822 | codeextraarg(fs, extra); | | 1826 | codeextraarg(fs, extra); |
1823 | } | | 1827 | } |
1824 | fs->freereg = base + 1; /* free registers with list values */ | | 1828 | fs->freereg = base + 1; /* free registers with list values */ |
1825 | } | | 1829 | } |
1826 | | | 1830 | |
1827 | | | 1831 | |
1828 | /* | | 1832 | /* |
1829 | ** return the final target of a jump (skipping jumps to jumps) | | 1833 | ** return the final target of a jump (skipping jumps to jumps) |
1830 | */ | | 1834 | */ |
1831 | static int finaltarget (Instruction *code, int i) { | | 1835 | static int finaltarget (Instruction *code, int i) { |
1832 | int count; | | 1836 | int count; |
1833 | for (count = 0; count < 100; count++) { /* avoid infinite loops */ | | 1837 | for (count = 0; count < 100; count++) { /* avoid infinite loops */ |
1834 | Instruction pc = code[i]; | | 1838 | Instruction pc = code[i]; |
1835 | if (GET_OPCODE(pc) != OP_JMP) | | 1839 | if (GET_OPCODE(pc) != OP_JMP) |
1836 | break; | | 1840 | break; |
1837 | else | | 1841 | else |
1838 | i += GETARG_sJ(pc) + 1; | | 1842 | i += GETARG_sJ(pc) + 1; |
1839 | } | | 1843 | } |
1840 | return i; | | 1844 | return i; |
1841 | } | | 1845 | } |
1842 | | | 1846 | |
1843 | | | 1847 | |
1844 | /* | | 1848 | /* |
1845 | ** Do a final pass over the code of a function, doing small peephole | | 1849 | ** Do a final pass over the code of a function, doing small peephole |
1846 | ** optimizations and adjustments. | | 1850 | ** optimizations and adjustments. |
1847 | */ | | 1851 | */ |
1848 | void luaK_finish (FuncState *fs) { | | 1852 | void luaK_finish (FuncState *fs) { |
1849 | int i; | | 1853 | int i; |
1850 | Proto *p = fs->f; | | 1854 | Proto *p = fs->f; |
1851 | for (i = 0; i < fs->pc; i++) { | | 1855 | for (i = 0; i < fs->pc; i++) { |
1852 | Instruction *pc = &p->code[i]; | | 1856 | Instruction *pc = &p->code[i]; |
1853 | lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); | | 1857 | lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); |
1854 | switch (GET_OPCODE(*pc)) { | | 1858 | switch (GET_OPCODE(*pc)) { |
1855 | case OP_RETURN0: case OP_RETURN1: { | | 1859 | case OP_RETURN0: case OP_RETURN1: { |
1856 | if (!(fs->needclose || p->is_vararg)) | | 1860 | if (!(fs->needclose || p->is_vararg)) |
1857 | break; /* no extra work */ | | 1861 | break; /* no extra work */ |
1858 | /* else use OP_RETURN to do the extra work */ | | 1862 | /* else use OP_RETURN to do the extra work */ |
1859 | SET_OPCODE(*pc, OP_RETURN); | | 1863 | SET_OPCODE(*pc, OP_RETURN); |
1860 | } /* FALLTHROUGH */ | | 1864 | } /* FALLTHROUGH */ |
1861 | case OP_RETURN: case OP_TAILCALL: { | | 1865 | case OP_RETURN: case OP_TAILCALL: { |
1862 | if (fs->needclose) | | 1866 | if (fs->needclose) |
1863 | SETARG_k(*pc, 1); /* signal that it needs to close */ | | 1867 | SETARG_k(*pc, 1); /* signal that it needs to close */ |
1864 | if (p->is_vararg) | | 1868 | if (p->is_vararg) |
1865 | SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ | | 1869 | SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ |
1866 | break; | | 1870 | break; |
1867 | } | | 1871 | } |
1868 | case OP_JMP: { | | 1872 | case OP_JMP: { |
1869 | int target = finaltarget(p->code, i); | | 1873 | int target = finaltarget(p->code, i); |
1870 | fixjump(fs, i, target); | | 1874 | fixjump(fs, i, target); |
1871 | break; | | 1875 | break; |
1872 | } | | 1876 | } |
1873 | default: break; | | 1877 | default: break; |
1874 | } | | 1878 | } |
1875 | } | | 1879 | } |
1876 | } | | 1880 | } |