aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-10-09 17:05:48 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-10-09 17:05:48 -0300
commite251e84e0f4e63c4a8d092fd9b95f35dc1f50b2a (patch)
tree4746306a19d344d8559e63604fd5c93ec80c5810
parente6bfbc38b554174918b58f6747e29ce2b18bb3c1 (diff)
downloadlua-e251e84e0f4e63c4a8d092fd9b95f35dc1f50b2a.tar.gz
lua-e251e84e0f4e63c4a8d092fd9b95f35dc1f50b2a.tar.bz2
lua-e251e84e0f4e63c4a8d092fd9b95f35dc1f50b2a.zip
constant folding optimizations
-rw-r--r--lcode.c227
1 files changed, 134 insertions, 93 deletions
diff --git a/lcode.c b/lcode.c
index c34c9648..30593c27 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.16 2005/08/29 20:49:21 roberto Exp roberto $ 2** $Id: lcode.c,v 2.17 2005/09/30 14:23:33 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*/
@@ -27,6 +27,11 @@
27#define hasjumps(e) ((e)->t != (e)->f) 27#define hasjumps(e) ((e)->t != (e)->f)
28 28
29 29
30static int isnumeral(FuncState *fs, expdesc *e) {
31 return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
32}
33
34
30void luaK_nil (FuncState *fs, int from, int n) { 35void luaK_nil (FuncState *fs, int from, int n) {
31 Instruction *previous; 36 Instruction *previous;
32 if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ 37 if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
@@ -213,7 +218,7 @@ static void freereg (FuncState *fs, int reg) {
213 218
214static void freeexp (FuncState *fs, expdesc *e) { 219static void freeexp (FuncState *fs, expdesc *e) {
215 if (e->k == VNONRELOC) 220 if (e->k == VNONRELOC)
216 freereg(fs, e->info); 221 freereg(fs, e->u.s.info);
217} 222}
218 223
219 224
@@ -283,7 +288,7 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
283void luaK_setoneret (FuncState *fs, expdesc *e) { 288void luaK_setoneret (FuncState *fs, expdesc *e) {
284 if (e->k == VCALL) { /* expression is an open function call? */ 289 if (e->k == VCALL) { /* expression is an open function call? */
285 e->k = VNONRELOC; 290 e->k = VNONRELOC;
286 e->info = GETARG_A(getcode(fs, e)); 291 e->u.s.info = GETARG_A(getcode(fs, e));
287 } 292 }
288 else if (e->k == VVARARG) { 293 else if (e->k == VVARARG) {
289 SETARG_B(getcode(fs, e), 2); 294 SETARG_B(getcode(fs, e), 2);
@@ -299,19 +304,19 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
299 break; 304 break;
300 } 305 }
301 case VUPVAL: { 306 case VUPVAL: {
302 e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0); 307 e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
303 e->k = VRELOCABLE; 308 e->k = VRELOCABLE;
304 break; 309 break;
305 } 310 }
306 case VGLOBAL: { 311 case VGLOBAL: {
307 e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info); 312 e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
308 e->k = VRELOCABLE; 313 e->k = VRELOCABLE;
309 break; 314 break;
310 } 315 }
311 case VINDEXED: { 316 case VINDEXED: {
312 freereg(fs, e->aux); 317 freereg(fs, e->u.s.aux);
313 freereg(fs, e->info); 318 freereg(fs, e->u.s.info);
314 e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux); 319 e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
315 e->k = VRELOCABLE; 320 e->k = VRELOCABLE;
316 break; 321 break;
317 } 322 }
@@ -343,7 +348,11 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
343 break; 348 break;
344 } 349 }
345 case VK: { 350 case VK: {
346 luaK_codeABx(fs, OP_LOADK, reg, e->info); 351 luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
352 break;
353 }
354 case VKNUM: {
355 luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
347 break; 356 break;
348 } 357 }
349 case VRELOCABLE: { 358 case VRELOCABLE: {
@@ -352,8 +361,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
352 break; 361 break;
353 } 362 }
354 case VNONRELOC: { 363 case VNONRELOC: {
355 if (reg != e->info) 364 if (reg != e->u.s.info)
356 luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); 365 luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
357 break; 366 break;
358 } 367 }
359 default: { 368 default: {
@@ -361,7 +370,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
361 return; /* nothing to do... */ 370 return; /* nothing to do... */
362 } 371 }
363 } 372 }
364 e->info = reg; 373 e->u.s.info = reg;
365 e->k = VNONRELOC; 374 e->k = VNONRELOC;
366} 375}
367 376
@@ -377,7 +386,7 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) {
377static void exp2reg (FuncState *fs, expdesc *e, int reg) { 386static void exp2reg (FuncState *fs, expdesc *e, int reg) {
378 discharge2reg(fs, e, reg); 387 discharge2reg(fs, e, reg);
379 if (e->k == VJMP) 388 if (e->k == VJMP)
380 luaK_concat(fs, &e->t, e->info); /* put this jump in `t' list */ 389 luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */
381 if (hasjumps(e)) { 390 if (hasjumps(e)) {
382 int final; /* position after whole expression */ 391 int final; /* position after whole expression */
383 int p_f = NO_JUMP; /* position of an eventual LOAD false */ 392 int p_f = NO_JUMP; /* position of an eventual LOAD false */
@@ -395,7 +404,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) {
395 patchlistaux(fs, e->t, final, reg, p_t); 404 patchlistaux(fs, e->t, final, reg, p_t);
396 } 405 }
397 e->f = e->t = NO_JUMP; 406 e->f = e->t = NO_JUMP;
398 e->info = reg; 407 e->u.s.info = reg;
399 e->k = VNONRELOC; 408 e->k = VNONRELOC;
400} 409}
401 410
@@ -411,14 +420,14 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
411int luaK_exp2anyreg (FuncState *fs, expdesc *e) { 420int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
412 luaK_dischargevars(fs, e); 421 luaK_dischargevars(fs, e);
413 if (e->k == VNONRELOC) { 422 if (e->k == VNONRELOC) {
414 if (!hasjumps(e)) return e->info; /* exp is already in a register */ 423 if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */
415 if (e->info >= fs->nactvar) { /* reg. is not a local? */ 424 if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */
416 exp2reg(fs, e, e->info); /* put value on it */ 425 exp2reg(fs, e, e->u.s.info); /* put value on it */
417 return e->info; 426 return e->u.s.info;
418 } 427 }
419 } 428 }
420 luaK_exp2nextreg(fs, e); /* default */ 429 luaK_exp2nextreg(fs, e); /* default */
421 return e->info; 430 return e->u.s.info;
422} 431}
423 432
424 433
@@ -433,19 +442,22 @@ void luaK_exp2val (FuncState *fs, expdesc *e) {
433int luaK_exp2RK (FuncState *fs, expdesc *e) { 442int luaK_exp2RK (FuncState *fs, expdesc *e) {
434 luaK_exp2val(fs, e); 443 luaK_exp2val(fs, e);
435 switch (e->k) { 444 switch (e->k) {
445 case VKNUM:
436 case VTRUE: 446 case VTRUE:
437 case VFALSE: 447 case VFALSE:
438 case VNIL: { 448 case VNIL: {
439 if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ 449 if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
440 e->info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); 450 e->u.s.info = (e->k == VNIL) ? nilK(fs) :
451 (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
452 boolK(fs, (e->k == VTRUE));
441 e->k = VK; 453 e->k = VK;
442 return RKASK(e->info); 454 return RKASK(e->u.s.info);
443 } 455 }
444 else break; 456 else break;
445 } 457 }
446 case VK: { 458 case VK: {
447 if (e->info <= MAXINDEXRK) /* constant fit in argC? */ 459 if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */
448 return RKASK(e->info); 460 return RKASK(e->u.s.info);
449 else break; 461 else break;
450 } 462 }
451 default: break; 463 default: break;
@@ -459,22 +471,22 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
459 switch (var->k) { 471 switch (var->k) {
460 case VLOCAL: { 472 case VLOCAL: {
461 freeexp(fs, ex); 473 freeexp(fs, ex);
462 exp2reg(fs, ex, var->info); 474 exp2reg(fs, ex, var->u.s.info);
463 return; 475 return;
464 } 476 }
465 case VUPVAL: { 477 case VUPVAL: {
466 int e = luaK_exp2anyreg(fs, ex); 478 int e = luaK_exp2anyreg(fs, ex);
467 luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0); 479 luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
468 break; 480 break;
469 } 481 }
470 case VGLOBAL: { 482 case VGLOBAL: {
471 int e = luaK_exp2anyreg(fs, ex); 483 int e = luaK_exp2anyreg(fs, ex);
472 luaK_codeABx(fs, OP_SETGLOBAL, e, var->info); 484 luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
473 break; 485 break;
474 } 486 }
475 case VINDEXED: { 487 case VINDEXED: {
476 int e = luaK_exp2RK(fs, ex); 488 int e = luaK_exp2RK(fs, ex);
477 luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e); 489 luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
478 break; 490 break;
479 } 491 }
480 default: { 492 default: {
@@ -492,15 +504,15 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
492 freeexp(fs, e); 504 freeexp(fs, e);
493 func = fs->freereg; 505 func = fs->freereg;
494 luaK_reserveregs(fs, 2); 506 luaK_reserveregs(fs, 2);
495 luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key)); 507 luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
496 freeexp(fs, key); 508 freeexp(fs, key);
497 e->info = func; 509 e->u.s.info = func;
498 e->k = VNONRELOC; 510 e->k = VNONRELOC;
499} 511}
500 512
501 513
502static void invertjump (FuncState *fs, expdesc *e) { 514static void invertjump (FuncState *fs, expdesc *e) {
503 Instruction *pc = getjumpcontrol(fs, e->info); 515 Instruction *pc = getjumpcontrol(fs, e->u.s.info);
504 lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && 516 lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
505 GET_OPCODE(*pc) != OP_TEST); 517 GET_OPCODE(*pc) != OP_TEST);
506 SETARG_A(*pc, !(GETARG_A(*pc))); 518 SETARG_A(*pc, !(GETARG_A(*pc)));
@@ -518,7 +530,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) {
518 } 530 }
519 discharge2anyreg(fs, e); 531 discharge2anyreg(fs, e);
520 freeexp(fs, e); 532 freeexp(fs, e);
521 return condjump(fs, OP_TESTSET, NO_REG, e->info, cond); 533 return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
522} 534}
523 535
524 536
@@ -526,7 +538,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
526 int pc; /* pc of last jump */ 538 int pc; /* pc of last jump */
527 luaK_dischargevars(fs, e); 539 luaK_dischargevars(fs, e);
528 switch (e->k) { 540 switch (e->k) {
529 case VK: case VTRUE: { 541 case VK: case VKNUM: case VTRUE: {
530 pc = NO_JUMP; /* always true; do nothing */ 542 pc = NO_JUMP; /* always true; do nothing */
531 break; 543 break;
532 } 544 }
@@ -536,7 +548,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
536 } 548 }
537 case VJMP: { 549 case VJMP: {
538 invertjump(fs, e); 550 invertjump(fs, e);
539 pc = e->info; 551 pc = e->u.s.info;
540 break; 552 break;
541 } 553 }
542 default: { 554 default: {
@@ -563,7 +575,7 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
563 break; 575 break;
564 } 576 }
565 case VJMP: { 577 case VJMP: {
566 pc = e->info; 578 pc = e->u.s.info;
567 break; 579 break;
568 } 580 }
569 default: { 581 default: {
@@ -584,7 +596,7 @@ static void codenot (FuncState *fs, expdesc *e) {
584 e->k = VTRUE; 596 e->k = VTRUE;
585 break; 597 break;
586 } 598 }
587 case VK: case VTRUE: { 599 case VK: case VKNUM: case VTRUE: {
588 e->k = VFALSE; 600 e->k = VFALSE;
589 break; 601 break;
590 } 602 }
@@ -596,7 +608,7 @@ static void codenot (FuncState *fs, expdesc *e) {
596 case VNONRELOC: { 608 case VNONRELOC: {
597 discharge2anyreg(fs, e); 609 discharge2anyreg(fs, e);
598 freeexp(fs, e); 610 freeexp(fs, e);
599 e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0); 611 e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
600 e->k = VRELOCABLE; 612 e->k = VRELOCABLE;
601 break; 613 break;
602 } 614 }
@@ -613,34 +625,79 @@ static void codenot (FuncState *fs, expdesc *e) {
613 625
614 626
615void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { 627void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
616 t->aux = luaK_exp2RK(fs, k); 628 t->u.s.aux = luaK_exp2RK(fs, k);
617 t->k = VINDEXED; 629 t->k = VINDEXED;
618} 630}
619 631
620 632
633static int constfolding (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
634 lua_Number v1, v2, r;
635 if (!isnumeral(fs, e1) || !isnumeral(fs, e2)) return 0;
636 v1 = e1->u.nval;
637 v2 = e2->u.nval;
638 switch (op) {
639 case OP_ADD: r = luai_numadd(fs->L, v1, v2); break;
640 case OP_SUB: r = luai_numsub(fs->L, v1, v2); break;
641 case OP_MUL: r = luai_nummul(fs->L, v1, v2); break;
642 case OP_DIV:
643 if (v2 == 0) return 0; /* do not attempt to divide by 0 */
644 r = luai_numdiv(fs->L, v1, v2); break;
645 case OP_MOD: r = luai_nummod(fs->L, v1, v2); break;
646 case OP_POW: r = luai_numpow(fs->L, v1, v2); break;
647 case OP_UNM: r = luai_numunm(fs->L, v1); break;
648 case OP_LEN: return 0; /* no constant folding for 'len' */
649 default: lua_assert(0); r = 0; break;
650 }
651 if (r != r) return 0; /* do not attempt to produce NaN */
652 e1->u.nval = r;
653 return 1;
654}
655
656
657static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
658 if (constfolding(fs, op, e1, e2))
659 return;
660 else {
661 int o1 = luaK_exp2RK(fs, e1);
662 int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
663 freeexp(fs, e2);
664 freeexp(fs, e1);
665 e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
666 e1->k = VRELOCABLE;
667 }
668}
669
670
671static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
672 expdesc *e2) {
673 int o1 = luaK_exp2RK(fs, e1);
674 int o2 = luaK_exp2RK(fs, e2);
675 freeexp(fs, e2);
676 freeexp(fs, e1);
677 if (cond == 0 && op != OP_EQ) {
678 int temp; /* exchange args to replace by `<' or `<=' */
679 temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
680 cond = 1;
681 }
682 e1->u.s.info = condjump(fs, op, cond, o1, o2);
683 e1->k = VJMP;
684}
685
686
621void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { 687void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
688 expdesc e2;
689 e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
622 switch (op) { 690 switch (op) {
623 case OPR_MINUS: { 691 case OPR_MINUS: {
624 luaK_exp2val(fs, e); 692 if (e->k == VK)
625 if (e->k == VK && ttisnumber(&fs->f->k[e->info])) 693 luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
626 e->info = luaK_numberK(fs, luai_numunm(L, nvalue(&fs->f->k[e->info]))); 694 codearith(fs, OP_UNM, e, &e2);
627 else {
628 luaK_exp2anyreg(fs, e);
629 freeexp(fs, e);
630 e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0);
631 e->k = VRELOCABLE;
632 }
633 break;
634 }
635 case OPR_NOT: {
636 codenot(fs, e);
637 break; 695 break;
638 } 696 }
697 case OPR_NOT: codenot(fs, e); break;
639 case OPR_LEN: { 698 case OPR_LEN: {
640 luaK_exp2anyreg(fs, e); 699 luaK_exp2anyreg(fs, e); /* cannot operate on constants */
641 freeexp(fs, e); 700 codearith(fs, OP_LEN, e, &e2);
642 e->info = luaK_codeABC(fs, OP_LEN, 0, e->info, 0);
643 e->k = VRELOCABLE;
644 break; 701 break;
645 } 702 }
646 default: lua_assert(0); 703 default: lua_assert(0);
@@ -663,74 +720,58 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
663 break; 720 break;
664 } 721 }
665 default: { 722 default: {
666 luaK_exp2RK(fs, v); 723 if (!isnumeral(fs, v)) luaK_exp2RK(fs, v);
667 break; 724 break;
668 } 725 }
669 } 726 }
670} 727}
671 728
672 729
673static void codebinop (FuncState *fs, expdesc *res, BinOpr op,
674 int o1, int o2) {
675 if (op <= OPR_POW) { /* arithmetic operator? */
676 OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */
677 res->info = luaK_codeABC(fs, opc, 0, o1, o2);
678 res->k = VRELOCABLE;
679 }
680 else { /* test operator */
681 static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE};
682 int cond = 1;
683 if (op >= OPR_GT) { /* `>' or `>='? */
684 int temp; /* exchange args and replace by `<' or `<=' */
685 temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
686 }
687 else if (op == OPR_NE) cond = 0;
688 res->info = condjump(fs, ops[op - OPR_NE], cond, o1, o2);
689 res->k = VJMP;
690 }
691}
692
693
694void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { 730void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
695 switch (op) { 731 switch (op) {
696 case OPR_AND: { 732 case OPR_AND: {
697 lua_assert(e1->t == NO_JUMP); /* list must be closed */ 733 lua_assert(e1->t == NO_JUMP); /* list must be closed */
698 luaK_dischargevars(fs, e2); 734 luaK_dischargevars(fs, e2);
699 luaK_concat(fs, &e1->f, e2->f); 735 luaK_concat(fs, &e1->f, e2->f);
700 e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t; 736 e1->k = e2->k; e1->u.s.info = e2->u.s.info;
737 e1->u.s.aux = e2->u.s.aux; e1->t = e2->t;
701 break; 738 break;
702 } 739 }
703 case OPR_OR: { 740 case OPR_OR: {
704 lua_assert(e1->f == NO_JUMP); /* list must be closed */ 741 lua_assert(e1->f == NO_JUMP); /* list must be closed */
705 luaK_dischargevars(fs, e2); 742 luaK_dischargevars(fs, e2);
706 luaK_concat(fs, &e1->t, e2->t); 743 luaK_concat(fs, &e1->t, e2->t);
707 e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f; 744 e1->k = e2->k; e1->u.s.info = e2->u.s.info;
745 e1->u.s.aux = e2->u.s.aux; e1->f = e2->f;
708 break; 746 break;
709 } 747 }
710 case OPR_CONCAT: { 748 case OPR_CONCAT: {
711 luaK_exp2val(fs, e2); 749 luaK_exp2val(fs, e2);
712 if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { 750 if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
713 lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1); 751 lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
714 freeexp(fs, e1); 752 freeexp(fs, e1);
715 SETARG_B(getcode(fs, e2), e1->info); 753 SETARG_B(getcode(fs, e2), e1->u.s.info);
716 e1->k = e2->k; e1->info = e2->info; 754 e1->k = e2->k; e1->u.s.info = e2->u.s.info;
717 } 755 }
718 else { 756 else {
719 luaK_exp2nextreg(fs, e2); 757 luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
720 freeexp(fs, e2); 758 codearith(fs, OP_CONCAT, e1, e2);
721 freeexp(fs, e1);
722 e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info);
723 e1->k = VRELOCABLE;
724 } 759 }
725 break; 760 break;
726 } 761 }
727 default: { 762 case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
728 int o1 = luaK_exp2RK(fs, e1); 763 case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
729 int o2 = luaK_exp2RK(fs, e2); 764 case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
730 freeexp(fs, e2); 765 case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
731 freeexp(fs, e1); 766 case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
732 codebinop(fs, e1, op, o1, o2); 767 case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
733 } 768 case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
769 case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
770 case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
771 case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
772 case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
773 case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
774 default: lua_assert(0);
734 } 775 }
735} 776}
736 777