diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-10-09 17:05:48 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-10-09 17:05:48 -0300 |
commit | e251e84e0f4e63c4a8d092fd9b95f35dc1f50b2a (patch) | |
tree | 4746306a19d344d8559e63604fd5c93ec80c5810 | |
parent | e6bfbc38b554174918b58f6747e29ce2b18bb3c1 (diff) | |
download | lua-e251e84e0f4e63c4a8d092fd9b95f35dc1f50b2a.tar.gz lua-e251e84e0f4e63c4a8d092fd9b95f35dc1f50b2a.tar.bz2 lua-e251e84e0f4e63c4a8d092fd9b95f35dc1f50b2a.zip |
constant folding optimizations
-rw-r--r-- | lcode.c | 227 |
1 files changed, 134 insertions, 93 deletions
@@ -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 | ||
30 | static int isnumeral(FuncState *fs, expdesc *e) { | ||
31 | return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); | ||
32 | } | ||
33 | |||
34 | |||
30 | void luaK_nil (FuncState *fs, int from, int n) { | 35 | void 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 | ||
214 | static void freeexp (FuncState *fs, expdesc *e) { | 219 | static 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) { | |||
283 | void luaK_setoneret (FuncState *fs, expdesc *e) { | 288 | void 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) { | |||
377 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { | 386 | static 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) { | |||
411 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | 420 | int 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) { | |||
433 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | 442 | int 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 | ||
502 | static void invertjump (FuncState *fs, expdesc *e) { | 514 | static 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 | ||
615 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | 627 | void 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 | ||
633 | static 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 | |||
657 | static 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 | |||
671 | static 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 | |||
621 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { | 687 | void 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 | ||
673 | static 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 | |||
694 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | 730 | void 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 | ||