diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 123 |
1 files changed, 61 insertions, 62 deletions
@@ -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 | ||
224 | static int addk (FuncState *fs, TObject *k) { | 224 | static 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) { | |||
243 | int luaK_stringk (FuncState *fs, TString *s) { | 243 | int 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 | ||
250 | static int number_constant (FuncState *fs, lua_Number r) { | 250 | static 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 | |||
257 | static 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 | ||
301 | static int code_label (FuncState *fs, OpCode op, int A, int sBc) { | 309 | static 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 | ||
307 | static void dischargejumps (FuncState *fs, expdesc *e, int reg) { | 315 | static 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 | ||
425 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | 439 | int 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) { | |||
584 | static void codenot (FuncState *fs, expdesc *e) { | 601 | static 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; |