Showing the changes to src/lcode.c (1 of 39 files). Show all
Unified · Split
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lcode.c,v 2.16 2005/08/29 20:49:21 roberto Exp $ | |
| 2 | +** $Id: lcode.c,v 2.22 2005/11/16 11:55:27 roberto Exp $ | |
| 3 | 3 | ** Code generator for Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -27,16 +27,24 @@ · 21 unmodified lines | ||
| 27 | 27 | #define hasjumps(e) ((e)->t != (e)->f) |
| 28 | 28 | |
| 29 | 29 | |
| 30 | +static int isnumeral(expdesc *e) { | |
| 31 | + return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); | |
| 32 | +} | |
| 33 | + | |
| 34 | + | |
| 30 | 35 | void luaK_nil (FuncState *fs, int from, int n) { |
| 31 | 36 | Instruction *previous; |
| 32 | − if (fs->pc > fs->lasttarget && /* no jumps to current position? */ | |
| 33 | − GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) { | |
| 34 | − int pfrom = GETARG_A(*previous); | |
| 35 | − int pto = GETARG_B(*previous); | |
| 36 | − if (pfrom <= from && from <= pto+1) { /* can connect both? */ | |
| 37 | − if (from+n-1 > pto) | |
| 38 | − SETARG_B(*previous, from+n-1); | |
| 39 | − return; | |
| 37 | + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ | |
| 38 | + if (fs->pc == 0) /* function start? */ | |
| 39 | + return; /* positions are already clean */ | |
| 40 | + if (GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) { | |
| 41 | + int pfrom = GETARG_A(*previous); | |
| 42 | + int pto = GETARG_B(*previous); | |
| 43 | + if (pfrom <= from && from <= pto+1) { /* can connect both? */ | |
| 44 | + if (from+n-1 > pto) | |
| 45 | + SETARG_B(*previous, from+n-1); | |
| 46 | + return; | |
| 47 | + } | |
| 40 | 48 | } |
| 41 | 49 | } |
| 42 | 50 | luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ |
| @@ -115,20 +123,22 @@ static int need_value (FuncState *fs, int list) { · 72 unmodified lines | ||
| 115 | 123 | } |
| 116 | 124 | |
| 117 | 125 | |
| 118 | −static void patchtestreg (Instruction *i, int reg) { | |
| 119 | − if (reg != NO_REG) | |
| 126 | +static int patchtestreg (FuncState *fs, int node, int reg) { | |
| 127 | + Instruction *i = getjumpcontrol(fs, node); | |
| 128 | + if (GET_OPCODE(*i) != OP_TESTSET) | |
| 129 | + return 0; /* cannot patch other instructions */ | |
| 130 | + if (reg != NO_REG && reg != GETARG_B(*i)) | |
| 120 | 131 | SETARG_A(*i, reg); |
| 121 | − else /* no register to put value; change TESTSET to TEST */ | |
| 132 | + else /* no register to put value or register already has the value */ | |
| 122 | 133 | *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); |
| 134 | + | |
| 135 | + return 1; | |
| 123 | 136 | } |
| 124 | 137 | |
| 125 | 138 | |
| 126 | 139 | static void removevalues (FuncState *fs, int list) { |
| 127 | − for (; list != NO_JUMP; list = getjump(fs, list)) { | |
| 128 | − Instruction *i = getjumpcontrol(fs, list); | |
| 129 | − if (GET_OPCODE(*i) == OP_TESTSET) | |
| 130 | − patchtestreg(i, NO_REG); | |
| 131 | − } | |
| 140 | + for (; list != NO_JUMP; list = getjump(fs, list)) | |
| 141 | + patchtestreg(fs, list, NO_REG); | |
| 132 | 142 | } |
| 133 | 143 | |
| 134 | 144 | |
| @@ -136,11 +146,8 @@ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, · 1 unmodified line | ||
| 136 | 146 | int dtarget) { |
| 137 | 147 | while (list != NO_JUMP) { |
| 138 | 148 | int next = getjump(fs, list); |
| 139 | − Instruction *i = getjumpcontrol(fs, list); | |
| 140 | − if (GET_OPCODE(*i) == OP_TESTSET) { | |
| 141 | − patchtestreg(i, reg); | |
| 149 | + if (patchtestreg(fs, list, reg)) | |
| 142 | 150 | fixjump(fs, list, vtarget); |
| 143 | − } | |
| 144 | 151 | else |
| 145 | 152 | fixjump(fs, list, dtarget); /* jump to default target */ |
| 146 | 153 | list = next; |
| @@ -210,7 +217,7 @@ static void freereg (FuncState *fs, int reg) { · 63 unmodified lines | ||
| 210 | 217 | |
| 211 | 218 | static void freeexp (FuncState *fs, expdesc *e) { |
| 212 | 219 | if (e->k == VNONRELOC) |
| 213 | − freereg(fs, e->info); | |
| 220 | + freereg(fs, e->u.s.info); | |
| 214 | 221 | } |
| 215 | 222 | |
| 216 | 223 | |
| @@ -280,7 +287,7 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { · 63 unmodified lines | ||
| 280 | 287 | void luaK_setoneret (FuncState *fs, expdesc *e) { |
| 281 | 288 | if (e->k == VCALL) { /* expression is an open function call? */ |
| 282 | 289 | e->k = VNONRELOC; |
| 283 | − e->info = GETARG_A(getcode(fs, e)); | |
| 290 | + e->u.s.info = GETARG_A(getcode(fs, e)); | |
| 284 | 291 | } |
| 285 | 292 | else if (e->k == VVARARG) { |
| 286 | 293 | SETARG_B(getcode(fs, e), 2); |
| @@ -296,19 +303,19 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { · 9 unmodified lines | ||
| 296 | 303 | break; |
| 297 | 304 | } |
| 298 | 305 | case VUPVAL: { |
| 299 | − e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0); | |
| 306 | + e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); | |
| 300 | 307 | e->k = VRELOCABLE; |
| 301 | 308 | break; |
| 302 | 309 | } |
| 303 | 310 | case VGLOBAL: { |
| 304 | − e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info); | |
| 311 | + e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); | |
| 305 | 312 | e->k = VRELOCABLE; |
| 306 | 313 | break; |
| 307 | 314 | } |
| 308 | 315 | case VINDEXED: { |
| 309 | − freereg(fs, e->aux); | |
| 310 | − freereg(fs, e->info); | |
| 311 | − e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux); | |
| 316 | + freereg(fs, e->u.s.aux); | |
| 317 | + freereg(fs, e->u.s.info); | |
| 318 | + e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); | |
| 312 | 319 | e->k = VRELOCABLE; |
| 313 | 320 | break; |
| 314 | 321 | } |
| @@ -340,7 +347,11 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { · 25 unmodified lines | ||
| 340 | 347 | break; |
| 341 | 348 | } |
| 342 | 349 | case VK: { |
| 343 | − luaK_codeABx(fs, OP_LOADK, reg, e->info); | |
| 350 | + luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); | |
| 351 | + break; | |
| 352 | + } | |
| 353 | + case VKNUM: { | |
| 354 | + luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); | |
| 344 | 355 | break; |
| 345 | 356 | } |
| 346 | 357 | case VRELOCABLE: { |
| @@ -349,8 +360,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { · 2 unmodified lines | ||
| 349 | 360 | break; |
| 350 | 361 | } |
| 351 | 362 | case VNONRELOC: { |
| 352 | − if (reg != e->info) | |
| 353 | − luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); | |
| 363 | + if (reg != e->u.s.info) | |
| 364 | + luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); | |
| 354 | 365 | break; |
| 355 | 366 | } |
| 356 | 367 | default: { |
| @@ -358,7 +369,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { · 1 unmodified line | ||
| 358 | 369 | return; /* nothing to do... */ |
| 359 | 370 | } |
| 360 | 371 | } |
| 361 | − e->info = reg; | |
| 372 | + e->u.s.info = reg; | |
| 362 | 373 | e->k = VNONRELOC; |
| 363 | 374 | } |
| 364 | 375 | |
| @@ -374,15 +385,13 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) { · 9 unmodified lines | ||
| 374 | 385 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { |
| 375 | 386 | discharge2reg(fs, e, reg); |
| 376 | 387 | if (e->k == VJMP) |
| 377 | − luaK_concat(fs, &e->t, e->info); /* put this jump in `t' list */ | |
| 388 | + luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ | |
| 378 | 389 | if (hasjumps(e)) { |
| 379 | 390 | int final; /* position after whole expression */ |
| 380 | 391 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
| 381 | 392 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ |
| 382 | 393 | if (need_value(fs, e->t) || need_value(fs, e->f)) { |
| 383 | − int fj = NO_JUMP; /* first jump (over LOAD ops.) */ | |
| 384 | − if (e->k != VJMP) | |
| 385 | − fj = luaK_jump(fs); | |
| 394 | + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); | |
| 386 | 395 | p_f = code_label(fs, reg, 0, 1); |
| 387 | 396 | p_t = code_label(fs, reg, 1, 0); |
| 388 | 397 | luaK_patchtohere(fs, fj); |
| @@ -392,7 +401,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { · 3 unmodified lines | ||
| 392 | 401 | patchlistaux(fs, e->t, final, reg, p_t); |
| 393 | 402 | } |
| 394 | 403 | e->f = e->t = NO_JUMP; |
| 395 | − e->info = reg; | |
| 404 | + e->u.s.info = reg; | |
| 396 | 405 | e->k = VNONRELOC; |
| 397 | 406 | } |
| 398 | 407 | |
| @@ -408,14 +417,14 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { · 9 unmodified lines | ||
| 408 | 417 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
| 409 | 418 | luaK_dischargevars(fs, e); |
| 410 | 419 | if (e->k == VNONRELOC) { |
| 411 | − if (!hasjumps(e)) return e->info; /* exp is already in a register */ | |
| 412 | − if (e->info >= fs->nactvar) { /* reg. is not a local? */ | |
| 413 | − exp2reg(fs, e, e->info); /* put value on it */ | |
| 414 | − return e->info; | |
| 420 | + if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ | |
| 421 | + if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ | |
| 422 | + exp2reg(fs, e, e->u.s.info); /* put value on it */ | |
| 423 | + return e->u.s.info; | |
| 415 | 424 | } |
| 416 | 425 | } |
| 417 | 426 | luaK_exp2nextreg(fs, e); /* default */ |
| 418 | − return e->info; | |
| 427 | + return e->u.s.info; | |
| 419 | 428 | } |
| 420 | 429 | |
| 421 | 430 | |
| @@ -430,19 +439,22 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { · 8 unmodified lines | ||
| 430 | 439 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
| 431 | 440 | luaK_exp2val(fs, e); |
| 432 | 441 | switch (e->k) { |
| 442 | + case VKNUM: | |
| 433 | 443 | case VTRUE: |
| 434 | 444 | case VFALSE: |
| 435 | 445 | case VNIL: { |
| 436 | 446 | if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ |
| 437 | − e->info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); | |
| 447 | + e->u.s.info = (e->k == VNIL) ? nilK(fs) : | |
| 448 | + (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : | |
| 449 | + boolK(fs, (e->k == VTRUE)); | |
| 438 | 450 | e->k = VK; |
| 439 | − return RKASK(e->info); | |
| 451 | + return RKASK(e->u.s.info); | |
| 440 | 452 | } |
| 441 | 453 | else break; |
| 442 | 454 | } |
| 443 | 455 | case VK: { |
| 444 | − if (e->info <= MAXINDEXRK) /* constant fit in argC? */ | |
| 445 | − return RKASK(e->info); | |
| 456 | + if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ | |
| 457 | + return RKASK(e->u.s.info); | |
| 446 | 458 | else break; |
| 447 | 459 | } |
| 448 | 460 | default: break; |
| @@ -456,22 +468,22 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { · 7 unmodified lines | ||
| 456 | 468 | switch (var->k) { |
| 457 | 469 | case VLOCAL: { |
| 458 | 470 | freeexp(fs, ex); |
| 459 | − exp2reg(fs, ex, var->info); | |
| 471 | + exp2reg(fs, ex, var->u.s.info); | |
| 460 | 472 | return; |
| 461 | 473 | } |
| 462 | 474 | case VUPVAL: { |
| 463 | 475 | int e = luaK_exp2anyreg(fs, ex); |
| 464 | − luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0); | |
| 476 | + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); | |
| 465 | 477 | break; |
| 466 | 478 | } |
| 467 | 479 | case VGLOBAL: { |
| 468 | 480 | int e = luaK_exp2anyreg(fs, ex); |
| 469 | − luaK_codeABx(fs, OP_SETGLOBAL, e, var->info); | |
| 481 | + luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); | |
| 470 | 482 | break; |
| 471 | 483 | } |
| 472 | 484 | case VINDEXED: { |
| 473 | 485 | int e = luaK_exp2RK(fs, ex); |
| 474 | − luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e); | |
| 486 | + luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); | |
| 475 | 487 | break; |
| 476 | 488 | } |
| 477 | 489 | default: { |
| @@ -489,15 +501,15 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { · 11 unmodified lines | ||
| 489 | 501 | freeexp(fs, e); |
| 490 | 502 | func = fs->freereg; |
| 491 | 503 | luaK_reserveregs(fs, 2); |
| 492 | − luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key)); | |
| 504 | + luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); | |
| 493 | 505 | freeexp(fs, key); |
| 494 | − e->info = func; | |
| 506 | + e->u.s.info = func; | |
| 495 | 507 | e->k = VNONRELOC; |
| 496 | 508 | } |
| 497 | 509 | |
| 498 | 510 | |
| 499 | 511 | static void invertjump (FuncState *fs, expdesc *e) { |
| 500 | − Instruction *pc = getjumpcontrol(fs, e->info); | |
| 512 | + Instruction *pc = getjumpcontrol(fs, e->u.s.info); | |
| 501 | 513 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
| 502 | 514 | GET_OPCODE(*pc) != OP_TEST); |
| 503 | 515 | SETARG_A(*pc, !(GETARG_A(*pc))); |
| @@ -515,7 +527,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { · 11 unmodified lines | ||
| 515 | 527 | } |
| 516 | 528 | discharge2anyreg(fs, e); |
| 517 | 529 | freeexp(fs, e); |
| 518 | − return condjump(fs, OP_TESTSET, NO_REG, e->info, cond); | |
| 530 | + return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); | |
| 519 | 531 | } |
| 520 | 532 | |
| 521 | 533 | |
| @@ -523,7 +535,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { · 1 unmodified line | ||
| 523 | 535 | int pc; /* pc of last jump */ |
| 524 | 536 | luaK_dischargevars(fs, e); |
| 525 | 537 | switch (e->k) { |
| 526 | − case VK: case VTRUE: { | |
| 538 | + case VK: case VKNUM: case VTRUE: { | |
| 527 | 539 | pc = NO_JUMP; /* always true; do nothing */ |
| 528 | 540 | break; |
| 529 | 541 | } |
| @@ -533,7 +545,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { · 3 unmodified lines | ||
| 533 | 545 | } |
| 534 | 546 | case VJMP: { |
| 535 | 547 | invertjump(fs, e); |
| 536 | − pc = e->info; | |
| 548 | + pc = e->u.s.info; | |
| 537 | 549 | break; |
| 538 | 550 | } |
| 539 | 551 | default: { |
| @@ -547,7 +559,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { · 7 unmodified lines | ||
| 547 | 559 | } |
| 548 | 560 | |
| 549 | 561 | |
| 550 | −void luaK_goiffalse (FuncState *fs, expdesc *e) { | |
| 562 | +static void luaK_goiffalse (FuncState *fs, expdesc *e) { | |
| 551 | 563 | int pc; /* pc of last jump */ |
| 552 | 564 | luaK_dischargevars(fs, e); |
| 553 | 565 | switch (e->k) { |
| @@ -560,7 +572,7 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { · 6 unmodified lines | ||
| 560 | 572 | break; |
| 561 | 573 | } |
| 562 | 574 | case VJMP: { |
| 563 | − pc = e->info; | |
| 575 | + pc = e->u.s.info; | |
| 564 | 576 | break; |
| 565 | 577 | } |
| 566 | 578 | default: { |
| @@ -581,7 +593,7 @@ static void codenot (FuncState *fs, expdesc *e) { · 14 unmodified lines | ||
| 581 | 593 | e->k = VTRUE; |
| 582 | 594 | break; |
| 583 | 595 | } |
| 584 | − case VK: case VTRUE: { | |
| 596 | + case VK: case VKNUM: case VTRUE: { | |
| 585 | 597 | e->k = VFALSE; |
| 586 | 598 | break; |
| 587 | 599 | } |
| @@ -593,7 +605,7 @@ static void codenot (FuncState *fs, expdesc *e) { · 5 unmodified lines | ||
| 593 | 605 | case VNONRELOC: { |
| 594 | 606 | discharge2anyreg(fs, e); |
| 595 | 607 | freeexp(fs, e); |
| 596 | − e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0); | |
| 608 | + e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); | |
| 597 | 609 | e->k = VRELOCABLE; |
| 598 | 610 | break; |
| 599 | 611 | } |
| @@ -610,34 +622,81 @@ static void codenot (FuncState *fs, expdesc *e) { · 10 unmodified lines | ||
| 610 | 622 | |
| 611 | 623 | |
| 612 | 624 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
| 613 | − t->aux = luaK_exp2RK(fs, k); | |
| 625 | + t->u.s.aux = luaK_exp2RK(fs, k); | |
| 614 | 626 | t->k = VINDEXED; |
| 615 | 627 | } |
| 616 | 628 | |
| 617 | 629 | |
| 630 | +static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | |
| 631 | + lua_Number v1, v2, r; | |
| 632 | + if (!isnumeral(e1) || !isnumeral(e2)) return 0; | |
| 633 | + v1 = e1->u.nval; | |
| 634 | + v2 = e2->u.nval; | |
| 635 | + switch (op) { | |
| 636 | + case OP_ADD: r = luai_numadd(v1, v2); break; | |
| 637 | + case OP_SUB: r = luai_numsub(v1, v2); break; | |
| 638 | + case OP_MUL: r = luai_nummul(v1, v2); break; | |
| 639 | + case OP_DIV: | |
| 640 | + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ | |
| 641 | + r = luai_numdiv(v1, v2); break; | |
| 642 | + case OP_MOD: | |
| 643 | + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ | |
| 644 | + r = luai_nummod(v1, v2); break; | |
| 645 | + case OP_POW: r = luai_numpow(v1, v2); break; | |
| 646 | + case OP_UNM: r = luai_numunm(v1); break; | |
| 647 | + case OP_LEN: return 0; /* no constant folding for 'len' */ | |
| 648 | + default: lua_assert(0); r = 0; break; | |
| 649 | + } | |
| 650 | + if (r != r) return 0; /* do not attempt to produce NaN */ | |
| 651 | + e1->u.nval = r; | |
| 652 | + return 1; | |
| 653 | +} | |
| 654 | + | |
| 655 | + | |
| 656 | +static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | |
| 657 | + if (constfolding(op, e1, e2)) | |
| 658 | + return; | |
| 659 | + else { | |
| 660 | + int o1 = luaK_exp2RK(fs, e1); | |
| 661 | + int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; | |
| 662 | + freeexp(fs, e2); | |
| 663 | + freeexp(fs, e1); | |
| 664 | + e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); | |
| 665 | + e1->k = VRELOCABLE; | |
| 666 | + } | |
| 667 | +} | |
| 668 | + | |
| 669 | + | |
| 670 | +static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, | |
| 671 | + expdesc *e2) { | |
| 672 | + int o1 = luaK_exp2RK(fs, e1); | |
| 673 | + int o2 = luaK_exp2RK(fs, e2); | |
| 674 | + freeexp(fs, e2); | |
| 675 | + freeexp(fs, e1); | |
| 676 | + if (cond == 0 && op != OP_EQ) { | |
| 677 | + int temp; /* exchange args to replace by `<' or `<=' */ | |
| 678 | + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ | |
| 679 | + cond = 1; | |
| 680 | + } | |
| 681 | + e1->u.s.info = condjump(fs, op, cond, o1, o2); | |
| 682 | + e1->k = VJMP; | |
| 683 | +} | |
| 684 | + | |
| 685 | + | |
| 618 | 686 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { |
| 687 | + expdesc e2; | |
| 688 | + e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; | |
| 619 | 689 | switch (op) { |
| 620 | 690 | case OPR_MINUS: { |
| 621 | − luaK_exp2val(fs, e); | |
| 622 | − if (e->k == VK && ttisnumber(&fs->f->k[e->info])) | |
| 623 | − e->info = luaK_numberK(fs, luai_numunm(L, nvalue(&fs->f->k[e->info]))); | |
| 624 | − else { | |
| 625 | − luaK_exp2anyreg(fs, e); | |
| 626 | − freeexp(fs, e); | |
| 627 | − e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0); | |
| 628 | − e->k = VRELOCABLE; | |
| 629 | − } | |
| 630 | − break; | |
| 631 | − } | |
| 632 | − case OPR_NOT: { | |
| 633 | − codenot(fs, e); | |
| 691 | + if (e->k == VK) | |
| 692 | + luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ | |
| 693 | + codearith(fs, OP_UNM, e, &e2); | |
| 634 | 694 | break; |
| 635 | 695 | } |
| 696 | + case OPR_NOT: codenot(fs, e); break; | |
| 636 | 697 | case OPR_LEN: { |
| 637 | − luaK_exp2anyreg(fs, e); | |
| 638 | − freeexp(fs, e); | |
| 639 | − e->info = luaK_codeABC(fs, OP_LEN, 0, e->info, 0); | |
| 640 | − e->k = VRELOCABLE; | |
| 698 | + luaK_exp2anyreg(fs, e); /* cannot operate on constants */ | |
| 699 | + codearith(fs, OP_LEN, e, &e2); | |
| 641 | 700 | break; |
| 642 | 701 | } |
| 643 | 702 | default: lua_assert(0); |
| @@ -660,74 +719,58 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { · 16 unmodified lines | ||
| 660 | 719 | break; |
| 661 | 720 | } |
| 662 | 721 | default: { |
| 663 | − luaK_exp2RK(fs, v); | |
| 722 | + if (!isnumeral(v)) luaK_exp2RK(fs, v); | |
| 664 | 723 | break; |
| 665 | 724 | } |
| 666 | 725 | } |
| 667 | 726 | } |
| 668 | 727 | |
| 669 | 728 | |
| 670 | −static void codebinop (FuncState *fs, expdesc *res, BinOpr op, | |
| 671 | − int o1, int o2) { | |
| 672 | − if (op <= OPR_POW) { /* arithmetic operator? */ | |
| 673 | − OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */ | |
| 674 | − res->info = luaK_codeABC(fs, opc, 0, o1, o2); | |
| 675 | − res->k = VRELOCABLE; | |
| 676 | − } | |
| 677 | − else { /* test operator */ | |
| 678 | − static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE}; | |
| 679 | − int cond = 1; | |
| 680 | − if (op >= OPR_GT) { /* `>' or `>='? */ | |
| 681 | − int temp; /* exchange args and replace by `<' or `<=' */ | |
| 682 | − temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ | |
| 683 | − } | |
| 684 | − else if (op == OPR_NE) cond = 0; | |
| 685 | − res->info = condjump(fs, ops[op - OPR_NE], cond, o1, o2); | |
| 686 | − res->k = VJMP; | |
| 687 | − } | |
| 688 | −} | |
| 689 | − | |
| 690 | − | |
| 691 | 729 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { |
| 692 | 730 | switch (op) { |
| 693 | 731 | case OPR_AND: { |
| 694 | 732 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ |
| 695 | 733 | luaK_dischargevars(fs, e2); |
| 696 | 734 | luaK_concat(fs, &e1->f, e2->f); |
| 697 | − e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t; | |
| 735 | + e1->k = e2->k; e1->u.s.info = e2->u.s.info; | |
| 736 | + e1->u.s.aux = e2->u.s.aux; e1->t = e2->t; | |
| 698 | 737 | break; |
| 699 | 738 | } |
| 700 | 739 | case OPR_OR: { |
| 701 | 740 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ |
| 702 | 741 | luaK_dischargevars(fs, e2); |
| 703 | 742 | luaK_concat(fs, &e1->t, e2->t); |
| 704 | − e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f; | |
| 743 | + e1->k = e2->k; e1->u.s.info = e2->u.s.info; | |
| 744 | + e1->u.s.aux = e2->u.s.aux; e1->f = e2->f; | |
| 705 | 745 | break; |
| 706 | 746 | } |
| 707 | 747 | case OPR_CONCAT: { |
| 708 | 748 | luaK_exp2val(fs, e2); |
| 709 | 749 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { |
| 710 | − lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1); | |
| 750 | + lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); | |
| 711 | 751 | freeexp(fs, e1); |
| 712 | − SETARG_B(getcode(fs, e2), e1->info); | |
| 713 | − e1->k = e2->k; e1->info = e2->info; | |
| 752 | + SETARG_B(getcode(fs, e2), e1->u.s.info); | |
| 753 | + e1->k = e2->k; e1->u.s.info = e2->u.s.info; | |
| 714 | 754 | } |
| 715 | 755 | else { |
| 716 | − luaK_exp2nextreg(fs, e2); | |
| 717 | − freeexp(fs, e2); | |
| 718 | − freeexp(fs, e1); | |
| 719 | − e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info); | |
| 720 | − e1->k = VRELOCABLE; | |
| 756 | + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ | |
| 757 | + codearith(fs, OP_CONCAT, e1, e2); | |
| 721 | 758 | } |
| 722 | 759 | break; |
| 723 | 760 | } |
| 724 | − default: { | |
| 725 | − int o1 = luaK_exp2RK(fs, e1); | |
| 726 | − int o2 = luaK_exp2RK(fs, e2); | |
| 727 | − freeexp(fs, e2); | |
| 728 | − freeexp(fs, e1); | |
| 729 | − codebinop(fs, e1, op, o1, o2); | |
| 730 | − } | |
| 761 | + case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; | |
| 762 | + case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; | |
| 763 | + case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; | |
| 764 | + case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; | |
| 765 | + case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; | |
| 766 | + case OPR_POW: codearith(fs, OP_POW, e1, e2); break; | |
| 767 | + case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; | |
| 768 | + case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; | |
| 769 | + case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; | |
| 770 | + case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; | |
| 771 | + case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; | |
| 772 | + case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; | |
| 773 | + default: lua_assert(0); | |
| 731 | 774 | } |
| 732 | 775 | } |
| 733 | 776 | |
| @@ -737,7 +780,7 @@ void luaK_fixline (FuncState *fs, int line) { · 3 unmodified lines | ||
| 737 | 780 | } |
| 738 | 781 | |
| 739 | 782 | |
| 740 | −int luaK_code (FuncState *fs, Instruction i, int line) { | |
| 783 | +static int luaK_code (FuncState *fs, Instruction i, int line) { | |
| 741 | 784 | Proto *f = fs->f; |
| 742 | 785 | dischargejpc(fs); /* `pc' will change */ |
| 743 | 786 | /* put new instruction in code array */ |