diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 67 |
1 files changed, 26 insertions, 41 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.108 2002/06/13 13:39:55 roberto Exp $ | 2 | ** $Id: lcode.c,v 1.109 2002/08/05 14:07:34 roberto Exp roberto $ |
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 | */ |
@@ -100,14 +100,14 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) { | |||
100 | static int need_value (FuncState *fs, int list, int cond) { | 100 | static int need_value (FuncState *fs, int list, int cond) { |
101 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) { | 101 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) { |
102 | Instruction i = *getjumpcontrol(fs, list); | 102 | Instruction i = *getjumpcontrol(fs, list); |
103 | if (GET_OPCODE(i) != OP_TEST || GETARG_B(i) != cond) return 1; | 103 | if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1; |
104 | } | 104 | } |
105 | return 0; /* not found */ | 105 | return 0; /* not found */ |
106 | } | 106 | } |
107 | 107 | ||
108 | 108 | ||
109 | static void patchtestreg (Instruction *i, int reg) { | 109 | static void patchtestreg (Instruction *i, int reg) { |
110 | if (reg == NO_REG) reg = GETARG_C(*i); | 110 | if (reg == NO_REG) reg = GETARG_B(*i); |
111 | SETARG_A(*i, reg); | 111 | SETARG_A(*i, reg); |
112 | } | 112 | } |
113 | 113 | ||
@@ -122,7 +122,7 @@ static void luaK_patchlistaux (FuncState *fs, int list, | |||
122 | luaK_fixjump(fs, list, dtarget); /* jump to default target */ | 122 | luaK_fixjump(fs, list, dtarget); /* jump to default target */ |
123 | } | 123 | } |
124 | else { | 124 | else { |
125 | if (GETARG_B(*i)) { | 125 | if (GETARG_C(*i)) { |
126 | lua_assert(ttarget != NO_JUMP); | 126 | lua_assert(ttarget != NO_JUMP); |
127 | patchtestreg(i, treg); | 127 | patchtestreg(i, treg); |
128 | luaK_fixjump(fs, list, ttarget); | 128 | luaK_fixjump(fs, list, ttarget); |
@@ -409,7 +409,7 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) { | |||
409 | } | 409 | } |
410 | default: break; | 410 | default: break; |
411 | } | 411 | } |
412 | /* not a constant in the right range: put in a register */ | 412 | /* not a constant in the right range: put it in a register */ |
413 | return luaK_exp2anyreg(fs, e); | 413 | return luaK_exp2anyreg(fs, e); |
414 | } | 414 | } |
415 | 415 | ||
@@ -432,8 +432,8 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { | |||
432 | break; | 432 | break; |
433 | } | 433 | } |
434 | case VINDEXED: { | 434 | case VINDEXED: { |
435 | int e = luaK_exp2anyreg(fs, exp); | 435 | int e = luaK_exp2RK(fs, exp); |
436 | luaK_codeABC(fs, OP_SETTABLE, e, var->info, var->aux); | 436 | luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e); |
437 | break; | 437 | break; |
438 | } | 438 | } |
439 | default: { | 439 | default: { |
@@ -460,8 +460,9 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | |||
460 | 460 | ||
461 | static void invertjump (FuncState *fs, expdesc *e) { | 461 | static void invertjump (FuncState *fs, expdesc *e) { |
462 | Instruction *pc = getjumpcontrol(fs, e->info); | 462 | Instruction *pc = getjumpcontrol(fs, e->info); |
463 | lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT)); | 463 | lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) && |
464 | SETARG_B(*pc, !(GETARG_B(*pc))); | 464 | GET_OPCODE(*pc) != OP_TEST); |
465 | SETARG_A(*pc, !(GETARG_A(*pc))); | ||
465 | } | 466 | } |
466 | 467 | ||
467 | 468 | ||
@@ -470,13 +471,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
470 | Instruction ie = getcode(fs, e); | 471 | Instruction ie = getcode(fs, e); |
471 | if (GET_OPCODE(ie) == OP_NOT) { | 472 | if (GET_OPCODE(ie) == OP_NOT) { |
472 | fs->pc--; /* remove previous OP_NOT */ | 473 | fs->pc--; /* remove previous OP_NOT */ |
473 | return luaK_condjump(fs, OP_TEST, NO_REG, !cond ,GETARG_B(ie)); | 474 | return luaK_condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond); |
474 | } | 475 | } |
475 | /* else go through */ | 476 | /* else go through */ |
476 | } | 477 | } |
477 | discharge2anyreg(fs, e); | 478 | discharge2anyreg(fs, e); |
478 | freeexp(fs, e); | 479 | freeexp(fs, e); |
479 | return luaK_condjump(fs, OP_TEST, NO_REG, cond, e->info); | 480 | return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond); |
480 | } | 481 | } |
481 | 482 | ||
482 | 483 | ||
@@ -605,11 +606,6 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
605 | luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ | 606 | luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ |
606 | break; | 607 | break; |
607 | } | 608 | } |
608 | case OPR_SUB: case OPR_DIV: case OPR_POW: { | ||
609 | /* non-comutative operators */ | ||
610 | luaK_exp2anyreg(fs, v); /* first operand must be a register */ | ||
611 | break; | ||
612 | } | ||
613 | default: { | 609 | default: { |
614 | luaK_exp2RK(fs, v); | 610 | luaK_exp2RK(fs, v); |
615 | break; | 611 | break; |
@@ -619,13 +615,11 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
619 | 615 | ||
620 | 616 | ||
621 | static void codebinop (FuncState *fs, expdesc *res, BinOpr op, | 617 | static void codebinop (FuncState *fs, expdesc *res, BinOpr op, |
622 | int o1, int o2, int ic) { | 618 | int o1, int o2) { |
623 | switch (op) { | 619 | switch (op) { |
624 | case OPR_SUB: | 620 | case OPR_SUB: |
625 | case OPR_DIV: | 621 | case OPR_DIV: |
626 | case OPR_POW: | 622 | case OPR_POW: |
627 | lua_assert(!ic); | ||
628 | /* go through */ | ||
629 | case OPR_ADD: | 623 | case OPR_ADD: |
630 | case OPR_MULT: { /* ORDER OPR */ | 624 | case OPR_MULT: { /* ORDER OPR */ |
631 | OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); | 625 | OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); |
@@ -635,20 +629,21 @@ static void codebinop (FuncState *fs, expdesc *res, BinOpr op, | |||
635 | } | 629 | } |
636 | case OPR_NE: | 630 | case OPR_NE: |
637 | case OPR_EQ: { | 631 | case OPR_EQ: { |
638 | res->info = luaK_condjump(fs, OP_EQ, o1, (op == OPR_EQ), o2); | 632 | res->info = luaK_condjump(fs, OP_EQ, (op == OPR_EQ), o1, o2); |
639 | res->k = VJMP; | 633 | res->k = VJMP; |
640 | break; | 634 | break; |
641 | } | 635 | } |
642 | case OPR_LT: | ||
643 | case OPR_LE: | ||
644 | case OPR_GT: | 636 | case OPR_GT: |
645 | case OPR_GE: { /* ORDER OPR */ | 637 | case OPR_GE: { /* ORDER OPR */ |
646 | OpCode opc; | 638 | int temp; |
647 | int i = op - OPR_LT; | 639 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ |
648 | if (ic) /* operands were interchanged? */ | 640 | op -= 2; /* GT -> LT, GE -> LE */ |
649 | i = (i+2)&3; /* correct operator */ | 641 | /* go through */ |
650 | opc = cast(OpCode, i + OP_LT); | 642 | } |
651 | res->info = luaK_condjump(fs, opc, o1, 1, o2); | 643 | case OPR_LT: |
644 | case OPR_LE: { | ||
645 | OpCode opc = cast(OpCode, (op - OPR_LT) + OP_LT); | ||
646 | res->info = luaK_condjump(fs, opc, 1, o1, o2); | ||
652 | res->k = VJMP; | 647 | res->k = VJMP; |
653 | break; | 648 | break; |
654 | } | 649 | } |
@@ -691,21 +686,11 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | |||
691 | break; | 686 | break; |
692 | } | 687 | } |
693 | default: { | 688 | default: { |
694 | int o1, o2; | 689 | int o1 = luaK_exp2RK(fs, e1); |
695 | int ic; /* interchange flag */ | 690 | int o2 = luaK_exp2RK(fs, e2); |
696 | if (e1->k != VK) { /* not a constant operator? */ | ||
697 | o1 = e1->info; | ||
698 | o2 = luaK_exp2RK(fs, e2); /* maybe other operator is constant... */ | ||
699 | ic = 0; | ||
700 | } | ||
701 | else { /* interchange operands */ | ||
702 | o2 = luaK_exp2RK(fs, e1); /* constant must be 2nd operand */ | ||
703 | o1 = luaK_exp2anyreg(fs, e2); /* other operator must be in register */ | ||
704 | ic = 1; | ||
705 | } | ||
706 | freeexp(fs, e2); | 691 | freeexp(fs, e2); |
707 | freeexp(fs, e1); | 692 | freeexp(fs, e1); |
708 | codebinop(fs, e1, op, o1, o2, ic); | 693 | codebinop(fs, e1, op, o1, o2); |
709 | } | 694 | } |
710 | } | 695 | } |
711 | } | 696 | } |