summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/lcode.c
diff options
context:
space:
mode:
authorRichard Quirk <richard.quirk@gmail.com>2014-03-19 19:31:31 +0100
committerMarcin Bukat <marcin.bukat@gmail.com>2014-04-02 20:31:54 +0200
commit36378988ad4059982742f05f5eb50580b456840a (patch)
treeee70be810d894566c5e351f21a1ebb79be742a85 /apps/plugins/lua/lcode.c
parent020f16a1c7d5bc9a302671cef03f56ac735e20c5 (diff)
downloadrockbox-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.c400
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
35void luaK_nil (FuncState *fs, int from, int n) { 37void 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
179LUAI_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
179void luaK_patchtohere (FuncState *fs, int list) { 192void 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
212static 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
227int 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
236int 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
244static 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
250int 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
199void luaK_checkstack (FuncState *fs, int n) { 261void 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
223static void freeexp (FuncState *fs, expdesc *e) { 285static 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
229static int addk (FuncState *fs, TValue *k, TValue *v) { 291static 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
250int luaK_stringK (FuncState *fs, TString *s) { 319int 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
257int luaK_numberK (FuncState *fs, lua_Number r) { 326int 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) {
292void luaK_setoneret (FuncState *fs, expdesc *e) { 371void 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) {
390static void exp2reg (FuncState *fs, expdesc *e, int reg) { 468static 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) {
422int luaK_exp2anyreg (FuncState *fs, expdesc *e) { 500int 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
514void 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) {
444int luaK_exp2RK (FuncState *fs, expdesc *e) { 528int 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
503void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { 585void 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
516static void invertjump (FuncState *fs, expdesc *e) { 598static 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
567static void luaK_goiffalse (FuncState *fs, expdesc *e) { 645void 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
629void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { 703void 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
635static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { 713static 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
661static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { 724static 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
697void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { 762void 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
745void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { 813void 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
797static 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
812int 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
820int 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
827void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { 867void 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