aboutsummaryrefslogtreecommitdiff
path: root/lcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcode.c')
-rw-r--r--lcode.c123
1 files changed, 61 insertions, 62 deletions
diff --git a/lcode.c b/lcode.c
index 210450fa..4e8d23c1 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 1.82 2001/09/07 17:39:10 roberto Exp $ 2** $Id: lcode.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
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*/
@@ -221,10 +221,10 @@ static void freeexp (FuncState *fs, expdesc *e) {
221} 221}
222 222
223 223
224static int addk (FuncState *fs, TObject *k) { 224static int addk (FuncState *fs, TObject *k, TObject *v) {
225 const TObject *index = luaH_get(fs->h, k); 225 const TObject *index = luaH_get(fs->h, k);
226 if (ttype(index) == LUA_TNUMBER) { 226 if (ttype(index) == LUA_TNUMBER) {
227 lua_assert(luaO_equalObj(&fs->f->k[cast(int, nvalue(index))], k)); 227 lua_assert(luaO_equalObj(&fs->f->k[cast(int, nvalue(index))], v));
228 return cast(int, nvalue(index)); 228 return cast(int, nvalue(index));
229 } 229 }
230 else { /* constant not found; create a new entry */ 230 else { /* constant not found; create a new entry */
@@ -232,7 +232,7 @@ static int addk (FuncState *fs, TObject *k) {
232 Proto *f = fs->f; 232 Proto *f = fs->f;
233 luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, 233 luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject,
234 MAXARG_Bc, "constant table overflow"); 234 MAXARG_Bc, "constant table overflow");
235 setobj(&f->k[fs->nk], k); 235 setobj(&f->k[fs->nk], v);
236 setnvalue(&o, fs->nk); 236 setnvalue(&o, fs->nk);
237 luaH_set(fs->L, fs->h, k, &o); 237 luaH_set(fs->L, fs->h, k, &o);
238 return fs->nk++; 238 return fs->nk++;
@@ -243,14 +243,22 @@ static int addk (FuncState *fs, TObject *k) {
243int luaK_stringk (FuncState *fs, TString *s) { 243int luaK_stringk (FuncState *fs, TString *s) {
244 TObject o; 244 TObject o;
245 setsvalue(&o, s); 245 setsvalue(&o, s);
246 return addk(fs, &o); 246 return addk(fs, &o, &o);
247} 247}
248 248
249 249
250static int number_constant (FuncState *fs, lua_Number r) { 250static int number_constant (FuncState *fs, lua_Number r) {
251 TObject o; 251 TObject o;
252 setnvalue(&o, r); 252 setnvalue(&o, r);
253 return addk(fs, &o); 253 return addk(fs, &o, &o);
254}
255
256
257static int nil_constant (FuncState *fs) {
258 TObject k, v;
259 setnilvalue(&v);
260 sethvalue(&k, fs->h); /* cannot use nil as key; instead use table itself */
261 return addk(fs, &k, &v);
254} 262}
255 263
256 264
@@ -298,27 +306,29 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
298} 306}
299 307
300 308
301static int code_label (FuncState *fs, OpCode op, int A, int sBc) { 309static int code_label (FuncState *fs, int A, int b, int jump) {
302 luaK_getlabel(fs); /* those instructions may be jump targets */ 310 luaK_getlabel(fs); /* those instructions may be jump targets */
303 return luaK_codeAsBc(fs, op, A, sBc); 311 return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
304} 312}
305 313
306 314
307static void dischargejumps (FuncState *fs, expdesc *e, int reg) { 315static void dischargejumps (FuncState *fs, expdesc *e, int reg) {
308 if (hasjumps(e)) { 316 if (hasjumps(e)) {
309 int final; /* position after whole expression */ 317 int final; /* position after whole expression */
310 int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ 318 int p_f = NO_JUMP; /* position of an eventual PUSH false */
311 int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ 319 int p_t = NO_JUMP; /* position of an eventual PUSH true */
312 if (need_value(fs, e->f, OP_TESTF) || need_value(fs, e->t, OP_TESTT)) { 320 if (need_value(fs, e->f, OP_TESTF) || need_value(fs, e->t, OP_TESTT)) {
313 /* expression needs values */ 321 /* expression needs values */
314 if (e->k != VJMP) 322 if (e->k != VJMP) {
315 code_label(fs, OP_JMP, 0, 2); /* to jump over both pushes */ 323 luaK_getlabel(fs); /* these instruction may be jump target */
316 p_nil = code_label(fs, OP_NILJMP, reg, 0); 324 luaK_codeAsBc(fs, OP_JMP, 0, 2); /* to jump over both pushes */
317 p_1 = code_label(fs, OP_LOADINT, reg, 1); 325 }
326 p_f = code_label(fs, reg, 0, 1);
327 p_t = code_label(fs, reg, 1, 0);
318 } 328 }
319 final = luaK_getlabel(fs); 329 final = luaK_getlabel(fs);
320 luaK_patchlistaux(fs, e->f, p_nil, NO_REG, final, reg, p_nil); 330 luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f);
321 luaK_patchlistaux(fs, e->t, final, reg, p_1, NO_REG, p_1); 331 luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t);
322 } 332 }
323 e->f = e->t = NO_JUMP; 333 e->f = e->t = NO_JUMP;
324} 334}
@@ -331,6 +341,10 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
331 luaK_nil(fs, reg, 1); 341 luaK_nil(fs, reg, 1);
332 break; 342 break;
333 } 343 }
344 case VFALSE: case VTRUE: {
345 luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
346 break;
347 }
334 case VNUMBER: { 348 case VNUMBER: {
335 lua_Number f = e->u.n; 349 lua_Number f = e->u.n;
336 int i = cast(int, f); 350 int i = cast(int, f);
@@ -424,13 +438,25 @@ void luaK_exp2val (FuncState *fs, expdesc *e) {
424 438
425int luaK_exp2RK (FuncState *fs, expdesc *e) { 439int luaK_exp2RK (FuncState *fs, expdesc *e) {
426 luaK_exp2val(fs, e); 440 luaK_exp2val(fs, e);
427 if (e->k == VNUMBER && fs->nk + MAXSTACK <= MAXARG_C) { 441 switch (e->k) {
428 e->u.i.info = number_constant(fs, e->u.n); 442 case VNUMBER: case VNIL: {
429 e->k = VK; 443 if (fs->nk + MAXSTACK <= MAXARG_C) { /* constant fit in argC? */
444 e->u.i.info = (e->k == VNIL) ? nil_constant(fs) :
445 number_constant(fs, e->u.n);
446 e->k = VK;
447 return e->u.i.info + MAXSTACK;
448 }
449 else break;
450 }
451 case VK: {
452 if (e->u.i.info + MAXSTACK <= MAXARG_C) /* constant fit in argC? */
453 return e->u.i.info + MAXSTACK;
454 else break;
455 }
456 default: break;
430 } 457 }
431 else if (!(e->k == VK && e->u.i.info + MAXSTACK <= MAXARG_C)) 458 /* not a constant in the right range: put in a register */
432 luaK_exp2anyreg(fs, e); /* not a constant in the right range */ 459 return luaK_exp2anyreg(fs, e);
433 return (e->k == VK) ? e->u.i.info+MAXSTACK : e->u.i.info;
434} 460}
435 461
436 462
@@ -521,11 +547,11 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
521 int pc; /* pc of last jump */ 547 int pc; /* pc of last jump */
522 luaK_dischargevars(fs, e); 548 luaK_dischargevars(fs, e);
523 switch (e->k) { 549 switch (e->k) {
524 case VK: case VNUMBER: { 550 case VK: case VNUMBER: case VTRUE: {
525 pc = NO_JUMP; /* always true; do nothing */ 551 pc = NO_JUMP; /* always true; do nothing */
526 break; 552 break;
527 } 553 }
528 case VNIL: { 554 case VFALSE: {
529 pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ 555 pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */
530 break; 556 break;
531 } 557 }
@@ -534,14 +560,8 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
534 pc = e->u.i.info; 560 pc = e->u.i.info;
535 break; 561 break;
536 } 562 }
537 case VRELOCABLE:
538 case VNONRELOC: {
539 pc = jumponcond(fs, e, OP_TESTF);
540 break;
541 }
542 default: { 563 default: {
543 pc = 0; /* to avoid warnings */ 564 pc = jumponcond(fs, e, OP_TESTF);
544 lua_assert(0); /* cannot happen */
545 break; 565 break;
546 } 566 }
547 } 567 }
@@ -555,23 +575,20 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) {
555 int pc; /* pc of last jump */ 575 int pc; /* pc of last jump */
556 luaK_dischargevars(fs, e); 576 luaK_dischargevars(fs, e);
557 switch (e->k) { 577 switch (e->k) {
558 case VNIL: { 578 case VNIL: case VFALSE: {
559 pc = NO_JUMP; /* always false; do nothing */ 579 pc = NO_JUMP; /* always false; do nothing */
560 break; 580 break;
561 } 581 }
562 case VJMP: { 582 case VTRUE: {
563 pc = e->u.i.info; 583 pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */
564 break; 584 break;
565 } 585 }
566 case VK: case VNUMBER: /* cannot optimize it (`or' must keep value) */ 586 case VJMP: {
567 case VRELOCABLE: 587 pc = e->u.i.info;
568 case VNONRELOC: {
569 pc = jumponcond(fs, e, OP_TESTT);
570 break; 588 break;
571 } 589 }
572 default: { 590 default: {
573 pc = 0; /* to avoid warnings */ 591 pc = jumponcond(fs, e, OP_TESTT);
574 lua_assert(0); /* cannot happen */
575 break; 592 break;
576 } 593 }
577 } 594 }
@@ -584,13 +601,12 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) {
584static void codenot (FuncState *fs, expdesc *e) { 601static void codenot (FuncState *fs, expdesc *e) {
585 luaK_dischargevars(fs, e); 602 luaK_dischargevars(fs, e);
586 switch (e->k) { 603 switch (e->k) {
587 case VNIL: { 604 case VNIL: case VFALSE: {
588 e->u.n = 1; 605 e->k = VTRUE;
589 e->k = VNUMBER;
590 break; 606 break;
591 } 607 }
592 case VK: case VNUMBER: { 608 case VK: case VNUMBER: case VTRUE: {
593 e->k = VNIL; 609 e->k = VFALSE;
594 break; 610 break;
595 } 611 }
596 case VJMP: { 612 case VJMP: {
@@ -719,23 +735,6 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
719 } 735 }
720 break; 736 break;
721 } 737 }
722 case OPR_EQ: case OPR_NE: {
723 luaK_exp2val(fs, e2);
724 if (e2->k == VNIL) { /* exp x= nil ? */
725 if (e1->k == VK) { /* constant x= nil ? */
726 if (op == OPR_EQ) /* constant == nil ? */
727 e1->k = VNIL; /* always false */
728 /* else always true (leave the constant itself) */
729 }
730 else {
731 OpCode opc = (op == OPR_EQ) ? OP_TESTF : OP_TESTT;
732 e1->u.i.info = jumponcond(fs, e1, opc);
733 e1->k = VJMP;
734 }
735 break;
736 }
737 /* else go through */
738 }
739 default: { 738 default: {
740 int o1, o2; 739 int o1, o2;
741 OpCode opc; 740 OpCode opc;