diff options
author | Richard Quirk <richard.quirk@gmail.com> | 2014-03-19 19:31:31 +0100 |
---|---|---|
committer | Marcin Bukat <marcin.bukat@gmail.com> | 2014-04-02 20:31:54 +0200 |
commit | 36378988ad4059982742f05f5eb50580b456840a (patch) | |
tree | ee70be810d894566c5e351f21a1ebb79be742a85 /apps/plugins/lua/lcode.c | |
parent | 020f16a1c7d5bc9a302671cef03f56ac735e20c5 (diff) | |
download | rockbox-36378988ad4059982742f05f5eb50580b456840a.tar.gz rockbox-36378988ad4059982742f05f5eb50580b456840a.zip |
Update lua plugin to 5.2.3
Prior to this patch the Lua plugin used version 5.1.4. This change
reduces the number of modifications in the Lua source using some new
defines and because the upstream source is now more flexible.
Unless otherwise stated, l*.[ch] files are taken unmodified from the
upstream lua-5.2.3.
fscanf.c:
file descriptors in rockbox are just ints, they are hidden behind a
void* now so liolib requires less modifications. fscanf is updated to
use void* too.
getc.c: this is a new file required for getc implementation in lauxlib.c
lauxlib.c: LoadF replaced FILE* with int, the rockbox file
descriptor int are cast to FILE* (actually void* due to typedef).
getc uses the PREFIX version. stdin is not used, as per 5.1.4.
lbaselib.c: now uses strspn in the number parsing. print uses DEBUGF now
rather than being commented out.
lbitlib.c: use the built-in version from 5.2.3 rather than Reuben
Thomas's external library. Backwards compatible and adds some new bit
operations.
ldo.c: the LUAI_THROW/TRY defines are now in the core lua code, so have
been removed from rockconf.h
liolib.c: here the implementation has changed to use the LStream from
the original source, and cast the FILE* pointers to int. This has
reduced the number of modifications from the upstream version.
llex.c: the only change from upstream is to remove the locale include.
lmathlib.c: updated from the 5.2.3 version and re-applied the changes
that were made vs 5.1.4 for random numbers and to remove unsupported
float functions.
loadlib.c: upstream version, with the 5.1.4 changes for missing
functions.
lobject.c: upstream version, with ctype.h added and sprintf changed to
snprintf.
loslib.c: upstream version with locale.h removed and 5.1.4 changes for
unsupportable functions.
lstrlib.c: sprintf changed to snprintf.
ltable.c: upstream with the hashnum function from 5.1.4 to avoid frexp
in luai_hashnum.
luaconf.h: updated to 5.2.3 version, restored relevant parts from the
original 5.1.4 configuration. The COMPAT defines that are no longer
available are not included.
lundump.c: VERSION macro conflicts with the core Rockbox equivalent.
rocklib.c: luaL_reg is no longer available, replaced by luaL_Reg
equivalent. Moved checkboolean/optboolean functions to this file and out
of core lua files. luaL_getn is no longer available, replaced by
luaL_rawlen. luaL_register is deprecated, use the newlib/setfuncs
replacements. rli_init has to be called before setting up the newlib to
avoid overwriting the rb table.
rocklib_aux.pl: use rli_checkboolean from rocklib.c.
rocklua.c: new default bits library used, update the library loading
code with idiomatic 5.2 code.
strcspn.c: no longer needed, but strspn.c is required for strspn in
lbaselib.c
Change-Id: I0c7945c755f79083afe98ec117e1e8cf13de2651
Reviewed-on: http://gerrit.rockbox.org/774
Tested: Richard Quirk <richard.quirk@gmail.com>
Reviewed-by: Marcin Bukat <marcin.bukat@gmail.com>
Diffstat (limited to 'apps/plugins/lua/lcode.c')
-rw-r--r-- | apps/plugins/lua/lcode.c | 400 |
1 files changed, 221 insertions, 179 deletions
diff --git a/apps/plugins/lua/lcode.c b/apps/plugins/lua/lcode.c index cff626b7fa..820b95c0e1 100644 --- a/apps/plugins/lua/lcode.c +++ b/apps/plugins/lua/lcode.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ | 2 | ** $Id: lcode.c,v 2.62.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -21,7 +21,9 @@ | |||
21 | #include "lobject.h" | 21 | #include "lobject.h" |
22 | #include "lopcodes.h" | 22 | #include "lopcodes.h" |
23 | #include "lparser.h" | 23 | #include "lparser.h" |
24 | #include "lstring.h" | ||
24 | #include "ltable.h" | 25 | #include "ltable.h" |
26 | #include "lvm.h" | ||
25 | 27 | ||
26 | 28 | ||
27 | #define hasjumps(e) ((e)->t != (e)->f) | 29 | #define hasjumps(e) ((e)->t != (e)->f) |
@@ -34,25 +36,23 @@ static int isnumeral(expdesc *e) { | |||
34 | 36 | ||
35 | void luaK_nil (FuncState *fs, int from, int n) { | 37 | void luaK_nil (FuncState *fs, int from, int n) { |
36 | Instruction *previous; | 38 | Instruction *previous; |
39 | int l = from + n - 1; /* last register to set nil */ | ||
37 | if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ | 40 | if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ |
38 | if (fs->pc == 0) { /* function start? */ | 41 | previous = &fs->f->code[fs->pc-1]; |
39 | if (from >= fs->nactvar) | 42 | if (GET_OPCODE(*previous) == OP_LOADNIL) { |
40 | return; /* positions are already clean */ | 43 | int pfrom = GETARG_A(*previous); |
41 | } | 44 | int pl = pfrom + GETARG_B(*previous); |
42 | else { | 45 | if ((pfrom <= from && from <= pl + 1) || |
43 | previous = &fs->f->code[fs->pc-1]; | 46 | (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ |
44 | if (GET_OPCODE(*previous) == OP_LOADNIL) { | 47 | if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ |
45 | int pfrom = GETARG_A(*previous); | 48 | if (pl > l) l = pl; /* l = max(l, pl) */ |
46 | int pto = GETARG_B(*previous); | 49 | SETARG_A(*previous, from); |
47 | if (pfrom <= from && from <= pto+1) { /* can connect both? */ | 50 | SETARG_B(*previous, l - from); |
48 | if (from+n-1 > pto) | 51 | return; |
49 | SETARG_B(*previous, from+n-1); | ||
50 | return; | ||
51 | } | ||
52 | } | 52 | } |
53 | } | 53 | } /* else go through */ |
54 | } | 54 | } |
55 | luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ | 55 | luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ |
56 | } | 56 | } |
57 | 57 | ||
58 | 58 | ||
@@ -176,6 +176,19 @@ void luaK_patchlist (FuncState *fs, int list, int target) { | |||
176 | } | 176 | } |
177 | 177 | ||
178 | 178 | ||
179 | LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) { | ||
180 | level++; /* argument is +1 to reserve 0 as non-op */ | ||
181 | while (list != NO_JUMP) { | ||
182 | int next = getjump(fs, list); | ||
183 | lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && | ||
184 | (GETARG_A(fs->f->code[list]) == 0 || | ||
185 | GETARG_A(fs->f->code[list]) >= level)); | ||
186 | SETARG_A(fs->f->code[list], level); | ||
187 | list = next; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | |||
179 | void luaK_patchtohere (FuncState *fs, int list) { | 192 | void luaK_patchtohere (FuncState *fs, int list) { |
180 | luaK_getlabel(fs); | 193 | luaK_getlabel(fs); |
181 | luaK_concat(fs, &fs->jpc, list); | 194 | luaK_concat(fs, &fs->jpc, list); |
@@ -196,6 +209,55 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { | |||
196 | } | 209 | } |
197 | 210 | ||
198 | 211 | ||
212 | static int luaK_code (FuncState *fs, Instruction i) { | ||
213 | Proto *f = fs->f; | ||
214 | dischargejpc(fs); /* `pc' will change */ | ||
215 | /* put new instruction in code array */ | ||
216 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, | ||
217 | MAX_INT, "opcodes"); | ||
218 | f->code[fs->pc] = i; | ||
219 | /* save corresponding line information */ | ||
220 | luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, | ||
221 | MAX_INT, "opcodes"); | ||
222 | f->lineinfo[fs->pc] = fs->ls->lastline; | ||
223 | return fs->pc++; | ||
224 | } | ||
225 | |||
226 | |||
227 | int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { | ||
228 | lua_assert(getOpMode(o) == iABC); | ||
229 | lua_assert(getBMode(o) != OpArgN || b == 0); | ||
230 | lua_assert(getCMode(o) != OpArgN || c == 0); | ||
231 | lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); | ||
232 | return luaK_code(fs, CREATE_ABC(o, a, b, c)); | ||
233 | } | ||
234 | |||
235 | |||
236 | int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { | ||
237 | lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); | ||
238 | lua_assert(getCMode(o) == OpArgN); | ||
239 | lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); | ||
240 | return luaK_code(fs, CREATE_ABx(o, a, bc)); | ||
241 | } | ||
242 | |||
243 | |||
244 | static int codeextraarg (FuncState *fs, int a) { | ||
245 | lua_assert(a <= MAXARG_Ax); | ||
246 | return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); | ||
247 | } | ||
248 | |||
249 | |||
250 | int luaK_codek (FuncState *fs, int reg, int k) { | ||
251 | if (k <= MAXARG_Bx) | ||
252 | return luaK_codeABx(fs, OP_LOADK, reg, k); | ||
253 | else { | ||
254 | int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); | ||
255 | codeextraarg(fs, k); | ||
256 | return p; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | |||
199 | void luaK_checkstack (FuncState *fs, int n) { | 261 | void luaK_checkstack (FuncState *fs, int n) { |
200 | int newstack = fs->freereg + n; | 262 | int newstack = fs->freereg + n; |
201 | if (newstack > fs->f->maxstacksize) { | 263 | if (newstack > fs->f->maxstacksize) { |
@@ -222,42 +284,59 @@ static void freereg (FuncState *fs, int reg) { | |||
222 | 284 | ||
223 | static void freeexp (FuncState *fs, expdesc *e) { | 285 | static void freeexp (FuncState *fs, expdesc *e) { |
224 | if (e->k == VNONRELOC) | 286 | if (e->k == VNONRELOC) |
225 | freereg(fs, e->u.s.info); | 287 | freereg(fs, e->u.info); |
226 | } | 288 | } |
227 | 289 | ||
228 | 290 | ||
229 | static int addk (FuncState *fs, TValue *k, TValue *v) { | 291 | static int addk (FuncState *fs, TValue *key, TValue *v) { |
230 | lua_State *L = fs->L; | 292 | lua_State *L = fs->ls->L; |
231 | TValue *idx = luaH_set(L, fs->h, k); | 293 | TValue *idx = luaH_set(L, fs->h, key); |
232 | Proto *f = fs->f; | 294 | Proto *f = fs->f; |
233 | int oldsize = f->sizek; | 295 | int k, oldsize; |
234 | if (ttisnumber(idx)) { | 296 | if (ttisnumber(idx)) { |
235 | lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); | 297 | lua_Number n = nvalue(idx); |
236 | return cast_int(nvalue(idx)); | 298 | lua_number2int(k, n); |
237 | } | 299 | if (luaV_rawequalobj(&f->k[k], v)) |
238 | else { /* constant not found; create a new entry */ | 300 | return k; |
239 | setnvalue(idx, cast_num(fs->nk)); | 301 | /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); |
240 | luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, | 302 | go through and create a new entry for this value */ |
241 | MAXARG_Bx, "constant table overflow"); | ||
242 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | ||
243 | setobj(L, &f->k[fs->nk], v); | ||
244 | luaC_barrier(L, f, v); | ||
245 | return fs->nk++; | ||
246 | } | 303 | } |
304 | /* constant not found; create a new entry */ | ||
305 | oldsize = f->sizek; | ||
306 | k = fs->nk; | ||
307 | /* numerical value does not need GC barrier; | ||
308 | table has no metatable, so it does not need to invalidate cache */ | ||
309 | setnvalue(idx, cast_num(k)); | ||
310 | luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); | ||
311 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | ||
312 | setobj(L, &f->k[k], v); | ||
313 | fs->nk++; | ||
314 | luaC_barrier(L, f, v); | ||
315 | return k; | ||
247 | } | 316 | } |
248 | 317 | ||
249 | 318 | ||
250 | int luaK_stringK (FuncState *fs, TString *s) { | 319 | int luaK_stringK (FuncState *fs, TString *s) { |
251 | TValue o; | 320 | TValue o; |
252 | setsvalue(fs->L, &o, s); | 321 | setsvalue(fs->ls->L, &o, s); |
253 | return addk(fs, &o, &o); | 322 | return addk(fs, &o, &o); |
254 | } | 323 | } |
255 | 324 | ||
256 | 325 | ||
257 | int luaK_numberK (FuncState *fs, lua_Number r) { | 326 | int luaK_numberK (FuncState *fs, lua_Number r) { |
327 | int n; | ||
328 | lua_State *L = fs->ls->L; | ||
258 | TValue o; | 329 | TValue o; |
259 | setnvalue(&o, r); | 330 | setnvalue(&o, r); |
260 | return addk(fs, &o, &o); | 331 | if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ |
332 | /* use raw representation as key to avoid numeric problems */ | ||
333 | setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); | ||
334 | n = addk(fs, L->top - 1, &o); | ||
335 | L->top--; | ||
336 | } | ||
337 | else | ||
338 | n = addk(fs, &o, &o); /* regular case */ | ||
339 | return n; | ||
261 | } | 340 | } |
262 | 341 | ||
263 | 342 | ||
@@ -272,7 +351,7 @@ static int nilK (FuncState *fs) { | |||
272 | TValue k, v; | 351 | TValue k, v; |
273 | setnilvalue(&v); | 352 | setnilvalue(&v); |
274 | /* cannot use nil as key; instead use table itself to represent nil */ | 353 | /* cannot use nil as key; instead use table itself to represent nil */ |
275 | sethvalue(fs->L, &k, fs->h); | 354 | sethvalue(fs->ls->L, &k, fs->h); |
276 | return addk(fs, &k, &v); | 355 | return addk(fs, &k, &v); |
277 | } | 356 | } |
278 | 357 | ||
@@ -292,7 +371,7 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { | |||
292 | void luaK_setoneret (FuncState *fs, expdesc *e) { | 371 | void luaK_setoneret (FuncState *fs, expdesc *e) { |
293 | if (e->k == VCALL) { /* expression is an open function call? */ | 372 | if (e->k == VCALL) { /* expression is an open function call? */ |
294 | e->k = VNONRELOC; | 373 | e->k = VNONRELOC; |
295 | e->u.s.info = GETARG_A(getcode(fs, e)); | 374 | e->u.info = GETARG_A(getcode(fs, e)); |
296 | } | 375 | } |
297 | else if (e->k == VVARARG) { | 376 | else if (e->k == VVARARG) { |
298 | SETARG_B(getcode(fs, e), 2); | 377 | SETARG_B(getcode(fs, e), 2); |
@@ -308,19 +387,18 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
308 | break; | 387 | break; |
309 | } | 388 | } |
310 | case VUPVAL: { | 389 | case VUPVAL: { |
311 | e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); | 390 | e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); |
312 | e->k = VRELOCABLE; | ||
313 | break; | ||
314 | } | ||
315 | case VGLOBAL: { | ||
316 | e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); | ||
317 | e->k = VRELOCABLE; | 391 | e->k = VRELOCABLE; |
318 | break; | 392 | break; |
319 | } | 393 | } |
320 | case VINDEXED: { | 394 | case VINDEXED: { |
321 | freereg(fs, e->u.s.aux); | 395 | OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ |
322 | freereg(fs, e->u.s.info); | 396 | freereg(fs, e->u.ind.idx); |
323 | e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); | 397 | if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ |
398 | freereg(fs, e->u.ind.t); | ||
399 | op = OP_GETTABLE; | ||
400 | } | ||
401 | e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); | ||
324 | e->k = VRELOCABLE; | 402 | e->k = VRELOCABLE; |
325 | break; | 403 | break; |
326 | } | 404 | } |
@@ -347,16 +425,16 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
347 | luaK_nil(fs, reg, 1); | 425 | luaK_nil(fs, reg, 1); |
348 | break; | 426 | break; |
349 | } | 427 | } |
350 | case VFALSE: case VTRUE: { | 428 | case VFALSE: case VTRUE: { |
351 | luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); | 429 | luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); |
352 | break; | 430 | break; |
353 | } | 431 | } |
354 | case VK: { | 432 | case VK: { |
355 | luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); | 433 | luaK_codek(fs, reg, e->u.info); |
356 | break; | 434 | break; |
357 | } | 435 | } |
358 | case VKNUM: { | 436 | case VKNUM: { |
359 | luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); | 437 | luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); |
360 | break; | 438 | break; |
361 | } | 439 | } |
362 | case VRELOCABLE: { | 440 | case VRELOCABLE: { |
@@ -365,8 +443,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
365 | break; | 443 | break; |
366 | } | 444 | } |
367 | case VNONRELOC: { | 445 | case VNONRELOC: { |
368 | if (reg != e->u.s.info) | 446 | if (reg != e->u.info) |
369 | luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); | 447 | luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); |
370 | break; | 448 | break; |
371 | } | 449 | } |
372 | default: { | 450 | default: { |
@@ -374,7 +452,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
374 | return; /* nothing to do... */ | 452 | return; /* nothing to do... */ |
375 | } | 453 | } |
376 | } | 454 | } |
377 | e->u.s.info = reg; | 455 | e->u.info = reg; |
378 | e->k = VNONRELOC; | 456 | e->k = VNONRELOC; |
379 | } | 457 | } |
380 | 458 | ||
@@ -390,7 +468,7 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) { | |||
390 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { | 468 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { |
391 | discharge2reg(fs, e, reg); | 469 | discharge2reg(fs, e, reg); |
392 | if (e->k == VJMP) | 470 | if (e->k == VJMP) |
393 | luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ | 471 | luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */ |
394 | if (hasjumps(e)) { | 472 | if (hasjumps(e)) { |
395 | int final; /* position after whole expression */ | 473 | int final; /* position after whole expression */ |
396 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ | 474 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
@@ -406,7 +484,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { | |||
406 | patchlistaux(fs, e->t, final, reg, p_t); | 484 | patchlistaux(fs, e->t, final, reg, p_t); |
407 | } | 485 | } |
408 | e->f = e->t = NO_JUMP; | 486 | e->f = e->t = NO_JUMP; |
409 | e->u.s.info = reg; | 487 | e->u.info = reg; |
410 | e->k = VNONRELOC; | 488 | e->k = VNONRELOC; |
411 | } | 489 | } |
412 | 490 | ||
@@ -422,14 +500,20 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { | |||
422 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | 500 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
423 | luaK_dischargevars(fs, e); | 501 | luaK_dischargevars(fs, e); |
424 | if (e->k == VNONRELOC) { | 502 | if (e->k == VNONRELOC) { |
425 | if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ | 503 | if (!hasjumps(e)) return e->u.info; /* exp is already in a register */ |
426 | if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ | 504 | if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ |
427 | exp2reg(fs, e, e->u.s.info); /* put value on it */ | 505 | exp2reg(fs, e, e->u.info); /* put value on it */ |
428 | return e->u.s.info; | 506 | return e->u.info; |
429 | } | 507 | } |
430 | } | 508 | } |
431 | luaK_exp2nextreg(fs, e); /* default */ | 509 | luaK_exp2nextreg(fs, e); /* default */ |
432 | return e->u.s.info; | 510 | return e->u.info; |
511 | } | ||
512 | |||
513 | |||
514 | void luaK_exp2anyregup (FuncState *fs, expdesc *e) { | ||
515 | if (e->k != VUPVAL || hasjumps(e)) | ||
516 | luaK_exp2anyreg(fs, e); | ||
433 | } | 517 | } |
434 | 518 | ||
435 | 519 | ||
@@ -444,22 +528,24 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { | |||
444 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | 528 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
445 | luaK_exp2val(fs, e); | 529 | luaK_exp2val(fs, e); |
446 | switch (e->k) { | 530 | switch (e->k) { |
447 | case VKNUM: | ||
448 | case VTRUE: | 531 | case VTRUE: |
449 | case VFALSE: | 532 | case VFALSE: |
450 | case VNIL: { | 533 | case VNIL: { |
451 | if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ | 534 | if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */ |
452 | e->u.s.info = (e->k == VNIL) ? nilK(fs) : | 535 | e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); |
453 | (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : | ||
454 | boolK(fs, (e->k == VTRUE)); | ||
455 | e->k = VK; | 536 | e->k = VK; |
456 | return RKASK(e->u.s.info); | 537 | return RKASK(e->u.info); |
457 | } | 538 | } |
458 | else break; | 539 | else break; |
459 | } | 540 | } |
541 | case VKNUM: { | ||
542 | e->u.info = luaK_numberK(fs, e->u.nval); | ||
543 | e->k = VK; | ||
544 | /* go through */ | ||
545 | } | ||
460 | case VK: { | 546 | case VK: { |
461 | if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ | 547 | if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ |
462 | return RKASK(e->u.s.info); | 548 | return RKASK(e->u.info); |
463 | else break; | 549 | else break; |
464 | } | 550 | } |
465 | default: break; | 551 | default: break; |
@@ -473,22 +559,18 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
473 | switch (var->k) { | 559 | switch (var->k) { |
474 | case VLOCAL: { | 560 | case VLOCAL: { |
475 | freeexp(fs, ex); | 561 | freeexp(fs, ex); |
476 | exp2reg(fs, ex, var->u.s.info); | 562 | exp2reg(fs, ex, var->u.info); |
477 | return; | 563 | return; |
478 | } | 564 | } |
479 | case VUPVAL: { | 565 | case VUPVAL: { |
480 | int e = luaK_exp2anyreg(fs, ex); | 566 | int e = luaK_exp2anyreg(fs, ex); |
481 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); | 567 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); |
482 | break; | ||
483 | } | ||
484 | case VGLOBAL: { | ||
485 | int e = luaK_exp2anyreg(fs, ex); | ||
486 | luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); | ||
487 | break; | 568 | break; |
488 | } | 569 | } |
489 | case VINDEXED: { | 570 | case VINDEXED: { |
571 | OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; | ||
490 | int e = luaK_exp2RK(fs, ex); | 572 | int e = luaK_exp2RK(fs, ex); |
491 | luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); | 573 | luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); |
492 | break; | 574 | break; |
493 | } | 575 | } |
494 | default: { | 576 | default: { |
@@ -501,20 +583,20 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
501 | 583 | ||
502 | 584 | ||
503 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | 585 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { |
504 | int func; | 586 | int ereg; |
505 | luaK_exp2anyreg(fs, e); | 587 | luaK_exp2anyreg(fs, e); |
588 | ereg = e->u.info; /* register where 'e' was placed */ | ||
506 | freeexp(fs, e); | 589 | freeexp(fs, e); |
507 | func = fs->freereg; | 590 | e->u.info = fs->freereg; /* base register for op_self */ |
508 | luaK_reserveregs(fs, 2); | ||
509 | luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); | ||
510 | freeexp(fs, key); | ||
511 | e->u.s.info = func; | ||
512 | e->k = VNONRELOC; | 591 | e->k = VNONRELOC; |
592 | luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ | ||
593 | luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); | ||
594 | freeexp(fs, key); | ||
513 | } | 595 | } |
514 | 596 | ||
515 | 597 | ||
516 | static void invertjump (FuncState *fs, expdesc *e) { | 598 | static void invertjump (FuncState *fs, expdesc *e) { |
517 | Instruction *pc = getjumpcontrol(fs, e->u.s.info); | 599 | Instruction *pc = getjumpcontrol(fs, e->u.info); |
518 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && | 600 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
519 | GET_OPCODE(*pc) != OP_TEST); | 601 | GET_OPCODE(*pc) != OP_TEST); |
520 | SETARG_A(*pc, !(GETARG_A(*pc))); | 602 | SETARG_A(*pc, !(GETARG_A(*pc))); |
@@ -532,7 +614,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
532 | } | 614 | } |
533 | discharge2anyreg(fs, e); | 615 | discharge2anyreg(fs, e); |
534 | freeexp(fs, e); | 616 | freeexp(fs, e); |
535 | return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); | 617 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); |
536 | } | 618 | } |
537 | 619 | ||
538 | 620 | ||
@@ -540,17 +622,13 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
540 | int pc; /* pc of last jump */ | 622 | int pc; /* pc of last jump */ |
541 | luaK_dischargevars(fs, e); | 623 | luaK_dischargevars(fs, e); |
542 | switch (e->k) { | 624 | switch (e->k) { |
543 | case VK: case VKNUM: case VTRUE: { | ||
544 | pc = NO_JUMP; /* always true; do nothing */ | ||
545 | break; | ||
546 | } | ||
547 | case VFALSE: { | ||
548 | pc = luaK_jump(fs); /* always jump */ | ||
549 | break; | ||
550 | } | ||
551 | case VJMP: { | 625 | case VJMP: { |
552 | invertjump(fs, e); | 626 | invertjump(fs, e); |
553 | pc = e->u.s.info; | 627 | pc = e->u.info; |
628 | break; | ||
629 | } | ||
630 | case VK: case VKNUM: case VTRUE: { | ||
631 | pc = NO_JUMP; /* always true; do nothing */ | ||
554 | break; | 632 | break; |
555 | } | 633 | } |
556 | default: { | 634 | default: { |
@@ -564,20 +642,16 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
564 | } | 642 | } |
565 | 643 | ||
566 | 644 | ||
567 | static void luaK_goiffalse (FuncState *fs, expdesc *e) { | 645 | void luaK_goiffalse (FuncState *fs, expdesc *e) { |
568 | int pc; /* pc of last jump */ | 646 | int pc; /* pc of last jump */ |
569 | luaK_dischargevars(fs, e); | 647 | luaK_dischargevars(fs, e); |
570 | switch (e->k) { | 648 | switch (e->k) { |
571 | case VNIL: case VFALSE: { | 649 | case VJMP: { |
572 | pc = NO_JUMP; /* always false; do nothing */ | 650 | pc = e->u.info; |
573 | break; | ||
574 | } | ||
575 | case VTRUE: { | ||
576 | pc = luaK_jump(fs); /* always jump */ | ||
577 | break; | 651 | break; |
578 | } | 652 | } |
579 | case VJMP: { | 653 | case VNIL: case VFALSE: { |
580 | pc = e->u.s.info; | 654 | pc = NO_JUMP; /* always false; do nothing */ |
581 | break; | 655 | break; |
582 | } | 656 | } |
583 | default: { | 657 | default: { |
@@ -610,7 +684,7 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
610 | case VNONRELOC: { | 684 | case VNONRELOC: { |
611 | discharge2anyreg(fs, e); | 685 | discharge2anyreg(fs, e); |
612 | freeexp(fs, e); | 686 | freeexp(fs, e); |
613 | e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); | 687 | e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); |
614 | e->k = VRELOCABLE; | 688 | e->k = VRELOCABLE; |
615 | break; | 689 | break; |
616 | } | 690 | } |
@@ -627,38 +701,28 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
627 | 701 | ||
628 | 702 | ||
629 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | 703 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
630 | t->u.s.aux = luaK_exp2RK(fs, k); | 704 | lua_assert(!hasjumps(t)); |
705 | t->u.ind.t = t->u.info; | ||
706 | t->u.ind.idx = luaK_exp2RK(fs, k); | ||
707 | t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL | ||
708 | : check_exp(vkisinreg(t->k), VLOCAL); | ||
631 | t->k = VINDEXED; | 709 | t->k = VINDEXED; |
632 | } | 710 | } |
633 | 711 | ||
634 | 712 | ||
635 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | 713 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { |
636 | lua_Number v1, v2, r; | 714 | lua_Number r; |
637 | if (!isnumeral(e1) || !isnumeral(e2)) return 0; | 715 | if (!isnumeral(e1) || !isnumeral(e2)) return 0; |
638 | v1 = e1->u.nval; | 716 | if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) |
639 | v2 = e2->u.nval; | 717 | return 0; /* do not attempt to divide by 0 */ |
640 | switch (op) { | 718 | r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); |
641 | case OP_ADD: r = luai_numadd(v1, v2); break; | ||
642 | case OP_SUB: r = luai_numsub(v1, v2); break; | ||
643 | case OP_MUL: r = luai_nummul(v1, v2); break; | ||
644 | case OP_DIV: | ||
645 | if (v2 == 0) return 0; /* do not attempt to divide by 0 */ | ||
646 | r = luai_numdiv(v1, v2); break; | ||
647 | case OP_MOD: | ||
648 | if (v2 == 0) return 0; /* do not attempt to divide by 0 */ | ||
649 | r = luai_nummod(v1, v2); break; | ||
650 | case OP_POW: r = luai_numpow(v1, v2); break; | ||
651 | case OP_UNM: r = luai_numunm(v1); break; | ||
652 | case OP_LEN: return 0; /* no constant folding for 'len' */ | ||
653 | default: lua_assert(0); r = 0; break; | ||
654 | } | ||
655 | if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ | ||
656 | e1->u.nval = r; | 719 | e1->u.nval = r; |
657 | return 1; | 720 | return 1; |
658 | } | 721 | } |
659 | 722 | ||
660 | 723 | ||
661 | static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | 724 | static void codearith (FuncState *fs, OpCode op, |
725 | expdesc *e1, expdesc *e2, int line) { | ||
662 | if (constfolding(op, e1, e2)) | 726 | if (constfolding(op, e1, e2)) |
663 | return; | 727 | return; |
664 | else { | 728 | else { |
@@ -672,8 +736,9 @@ static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | |||
672 | freeexp(fs, e2); | 736 | freeexp(fs, e2); |
673 | freeexp(fs, e1); | 737 | freeexp(fs, e1); |
674 | } | 738 | } |
675 | e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); | 739 | e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); |
676 | e1->k = VRELOCABLE; | 740 | e1->k = VRELOCABLE; |
741 | luaK_fixline(fs, line); | ||
677 | } | 742 | } |
678 | } | 743 | } |
679 | 744 | ||
@@ -689,25 +754,28 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, | |||
689 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ | 754 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ |
690 | cond = 1; | 755 | cond = 1; |
691 | } | 756 | } |
692 | e1->u.s.info = condjump(fs, op, cond, o1, o2); | 757 | e1->u.info = condjump(fs, op, cond, o1, o2); |
693 | e1->k = VJMP; | 758 | e1->k = VJMP; |
694 | } | 759 | } |
695 | 760 | ||
696 | 761 | ||
697 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { | 762 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { |
698 | expdesc e2; | 763 | expdesc e2; |
699 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; | 764 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; |
700 | switch (op) { | 765 | switch (op) { |
701 | case OPR_MINUS: { | 766 | case OPR_MINUS: { |
702 | if (!isnumeral(e)) | 767 | if (isnumeral(e)) /* minus constant? */ |
703 | luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ | 768 | e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ |
704 | codearith(fs, OP_UNM, e, &e2); | 769 | else { |
770 | luaK_exp2anyreg(fs, e); | ||
771 | codearith(fs, OP_UNM, e, &e2, line); | ||
772 | } | ||
705 | break; | 773 | break; |
706 | } | 774 | } |
707 | case OPR_NOT: codenot(fs, e); break; | 775 | case OPR_NOT: codenot(fs, e); break; |
708 | case OPR_LEN: { | 776 | case OPR_LEN: { |
709 | luaK_exp2anyreg(fs, e); /* cannot operate on constants */ | 777 | luaK_exp2anyreg(fs, e); /* cannot operate on constants */ |
710 | codearith(fs, OP_LEN, e, &e2); | 778 | codearith(fs, OP_LEN, e, &e2, line); |
711 | break; | 779 | break; |
712 | } | 780 | } |
713 | default: lua_assert(0); | 781 | default: lua_assert(0); |
@@ -742,7 +810,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
742 | } | 810 | } |
743 | 811 | ||
744 | 812 | ||
745 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | 813 | void luaK_posfix (FuncState *fs, BinOpr op, |
814 | expdesc *e1, expdesc *e2, int line) { | ||
746 | switch (op) { | 815 | switch (op) { |
747 | case OPR_AND: { | 816 | case OPR_AND: { |
748 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | 817 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ |
@@ -761,29 +830,30 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | |||
761 | case OPR_CONCAT: { | 830 | case OPR_CONCAT: { |
762 | luaK_exp2val(fs, e2); | 831 | luaK_exp2val(fs, e2); |
763 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | 832 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { |
764 | lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); | 833 | lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1); |
765 | freeexp(fs, e1); | 834 | freeexp(fs, e1); |
766 | SETARG_B(getcode(fs, e2), e1->u.s.info); | 835 | SETARG_B(getcode(fs, e2), e1->u.info); |
767 | e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; | 836 | e1->k = VRELOCABLE; e1->u.info = e2->u.info; |
768 | } | 837 | } |
769 | else { | 838 | else { |
770 | luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ | 839 | luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ |
771 | codearith(fs, OP_CONCAT, e1, e2); | 840 | codearith(fs, OP_CONCAT, e1, e2, line); |
772 | } | 841 | } |
773 | break; | 842 | break; |
774 | } | 843 | } |
775 | case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; | 844 | case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: |
776 | case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; | 845 | case OPR_MOD: case OPR_POW: { |
777 | case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; | 846 | codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); |
778 | case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; | 847 | break; |
779 | case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; | 848 | } |
780 | case OPR_POW: codearith(fs, OP_POW, e1, e2); break; | 849 | case OPR_EQ: case OPR_LT: case OPR_LE: { |
781 | case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; | 850 | codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2); |
782 | case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; | 851 | break; |
783 | case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; | 852 | } |
784 | case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; | 853 | case OPR_NE: case OPR_GT: case OPR_GE: { |
785 | case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; | 854 | codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2); |
786 | case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; | 855 | break; |
856 | } | ||
787 | default: lua_assert(0); | 857 | default: lua_assert(0); |
788 | } | 858 | } |
789 | } | 859 | } |
@@ -794,46 +864,18 @@ void luaK_fixline (FuncState *fs, int line) { | |||
794 | } | 864 | } |
795 | 865 | ||
796 | 866 | ||
797 | static int luaK_code (FuncState *fs, Instruction i, int line) { | ||
798 | Proto *f = fs->f; | ||
799 | dischargejpc(fs); /* `pc' will change */ | ||
800 | /* put new instruction in code array */ | ||
801 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | ||
802 | MAX_INT, "code size overflow"); | ||
803 | f->code[fs->pc] = i; | ||
804 | /* save corresponding line information */ | ||
805 | luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, | ||
806 | MAX_INT, "code size overflow"); | ||
807 | f->lineinfo[fs->pc] = line; | ||
808 | return fs->pc++; | ||
809 | } | ||
810 | |||
811 | |||
812 | int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { | ||
813 | lua_assert(getOpMode(o) == iABC); | ||
814 | lua_assert(getBMode(o) != OpArgN || b == 0); | ||
815 | lua_assert(getCMode(o) != OpArgN || c == 0); | ||
816 | return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); | ||
817 | } | ||
818 | |||
819 | |||
820 | int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { | ||
821 | lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); | ||
822 | lua_assert(getCMode(o) == OpArgN); | ||
823 | return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); | ||
824 | } | ||
825 | |||
826 | |||
827 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { | 867 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { |
828 | int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; | 868 | int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; |
829 | int b = (tostore == LUA_MULTRET) ? 0 : tostore; | 869 | int b = (tostore == LUA_MULTRET) ? 0 : tostore; |
830 | lua_assert(tostore != 0); | 870 | lua_assert(tostore != 0); |
831 | if (c <= MAXARG_C) | 871 | if (c <= MAXARG_C) |
832 | luaK_codeABC(fs, OP_SETLIST, base, b, c); | 872 | luaK_codeABC(fs, OP_SETLIST, base, b, c); |
833 | else { | 873 | else if (c <= MAXARG_Ax) { |
834 | luaK_codeABC(fs, OP_SETLIST, base, b, 0); | 874 | luaK_codeABC(fs, OP_SETLIST, base, b, 0); |
835 | luaK_code(fs, cast(Instruction, c), fs->ls->lastline); | 875 | codeextraarg(fs, c); |
836 | } | 876 | } |
877 | else | ||
878 | luaX_syntaxerror(fs->ls, "constructor too long"); | ||
837 | fs->freereg = base + 1; /* free registers with list values */ | 879 | fs->freereg = base + 1; /* free registers with list values */ |
838 | } | 880 | } |
839 | 881 | ||