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 | ** 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,16 +27,24 @@ · 21 unmodified lines | |||
| 27 | #define hasjumps(e) ((e)->t != (e)->f) | 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 | 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? */ |
| 33 | GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) { | 38 | if (fs->pc == 0) /* function start? */ |
| 34 | int pfrom = GETARG_A(*previous); | 39 | return; /* positions are already clean */ |
| 35 | int pto = GETARG_B(*previous); | 40 | if (GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) { |
| 36 | if (pfrom <= from && from <= pto+1) { /* can connect both? */ | 41 | int pfrom = GETARG_A(*previous); |
| 37 | if (from+n-1 > pto) | 42 | int pto = GETARG_B(*previous); |
| 38 | SETARG_B(*previous, from+n-1); | 43 | if (pfrom <= from && from <= pto+1) { /* can connect both? */ |
| 39 | return; | 44 | if (from+n-1 > pto) |
| 45 | SETARG_B(*previous, from+n-1); | ||
| 46 | return; | ||
| 47 | } | ||
| 40 | } | 48 | } |
| 41 | } | 49 | } |
| 42 | luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ | 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) { | 126 | static int patchtestreg (FuncState *fs, int node, int reg) { |
| 119 | if (reg != NO_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 | SETARG_A(*i, reg); | 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 | *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); | 133 | *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); |
| 134 | |||
| 135 | return 1; | ||
| 123 | } | 136 | } |
| 124 | 137 | ||
| 125 | 138 | ||
| 126 | static void removevalues (FuncState *fs, int list) { | 139 | static void removevalues (FuncState *fs, int list) { |
| 127 | for (; list != NO_JUMP; list = getjump(fs, list)) { | 140 | for (; list != NO_JUMP; list = getjump(fs, list)) |
| 128 | Instruction *i = getjumpcontrol(fs, list); | 141 | patchtestreg(fs, list, NO_REG); |
| 129 | if (GET_OPCODE(*i) == OP_TESTSET) | ||
| 130 | patchtestreg(i, NO_REG); | ||
| 131 | } | ||
| 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 | int dtarget) { | 146 | int dtarget) { |
| 137 | while (list != NO_JUMP) { | 147 | while (list != NO_JUMP) { |
| 138 | int next = getjump(fs, list); | 148 | int next = getjump(fs, list); |
| 139 | Instruction *i = getjumpcontrol(fs, list); | 149 | if (patchtestreg(fs, list, reg)) |
| 140 | if (GET_OPCODE(*i) == OP_TESTSET) { | ||
| 141 | patchtestreg(i, reg); | ||
| 142 | fixjump(fs, list, vtarget); | 150 | fixjump(fs, list, vtarget); |
| 143 | } | ||
| 144 | else | 151 | else |
| 145 | fixjump(fs, list, dtarget); /* jump to default target */ | 152 | fixjump(fs, list, dtarget); /* jump to default target */ |
| 146 | list = next; | 153 | list = next; |
| @@ -210,7 +217,7 @@ static void freereg (FuncState *fs, int reg) { · 63 unmodified lines | |||
| 210 | 217 | ||
| 211 | static void freeexp (FuncState *fs, expdesc *e) { | 218 | static void freeexp (FuncState *fs, expdesc *e) { |
| 212 | if (e->k == VNONRELOC) | 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 | void luaK_setoneret (FuncState *fs, expdesc *e) { | 287 | void luaK_setoneret (FuncState *fs, expdesc *e) { |
| 281 | if (e->k == VCALL) { /* expression is an open function call? */ | 288 | if (e->k == VCALL) { /* expression is an open function call? */ |
| 282 | e->k = VNONRELOC; | 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 | else if (e->k == VVARARG) { | 292 | else if (e->k == VVARARG) { |
| 286 | SETARG_B(getcode(fs, e), 2); | 293 | SETARG_B(getcode(fs, e), 2); |
| @@ -296,19 +303,19 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { · 9 unmodified lines | |||
| 296 | break; | 303 | break; |
| 297 | } | 304 | } |
| 298 | case VUPVAL: { | 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 | e->k = VRELOCABLE; | 307 | e->k = VRELOCABLE; |
| 301 | break; | 308 | break; |
| 302 | } | 309 | } |
| 303 | case VGLOBAL: { | 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 | e->k = VRELOCABLE; | 312 | e->k = VRELOCABLE; |
| 306 | break; | 313 | break; |
| 307 | } | 314 | } |
| 308 | case VINDEXED: { | 315 | case VINDEXED: { |
| 309 | freereg(fs, e->aux); | 316 | freereg(fs, e->u.s.aux); |
| 310 | freereg(fs, e->info); | 317 | freereg(fs, e->u.s.info); |
| 311 | e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux); | 318 | e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); |
| 312 | e->k = VRELOCABLE; | 319 | e->k = VRELOCABLE; |
| 313 | break; | 320 | break; |
| 314 | } | 321 | } |
| @@ -340,7 +347,11 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { · 25 unmodified lines | |||
| 340 | break; | 347 | break; |
| 341 | } | 348 | } |
| 342 | case VK: { | 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 | break; | 355 | break; |
| 345 | } | 356 | } |
| 346 | case VRELOCABLE: { | 357 | case VRELOCABLE: { |
| @@ -349,8 +360,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { · 2 unmodified lines | |||
| 349 | break; | 360 | break; |
| 350 | } | 361 | } |
| 351 | case VNONRELOC: { | 362 | case VNONRELOC: { |
| 352 | if (reg != e->info) | 363 | if (reg != e->u.s.info) |
| 353 | luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); | 364 | luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); |
| 354 | break; | 365 | break; |
| 355 | } | 366 | } |
| 356 | default: { | 367 | default: { |
| @@ -358,7 +369,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { · 1 unmodified line | |||
| 358 | return; /* nothing to do... */ | 369 | return; /* nothing to do... */ |
| 359 | } | 370 | } |
| 360 | } | 371 | } |
| 361 | e->info = reg; | 372 | e->u.s.info = reg; |
| 362 | e->k = VNONRELOC; | 373 | e->k = VNONRELOC; |
| 363 | } | 374 | } |
| 364 | 375 | ||
| @@ -374,15 +385,13 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) { · 9 unmodified lines | |||
| 374 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { | 385 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { |
| 375 | discharge2reg(fs, e, reg); | 386 | discharge2reg(fs, e, reg); |
| 376 | if (e->k == VJMP) | 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 | if (hasjumps(e)) { | 389 | if (hasjumps(e)) { |
| 379 | int final; /* position after whole expression */ | 390 | int final; /* position after whole expression */ |
| 380 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ | 391 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
| 381 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ | 392 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ |
| 382 | if (need_value(fs, e->t) || need_value(fs, e->f)) { | 393 | if (need_value(fs, e->t) || need_value(fs, e->f)) { |
| 383 | int fj = NO_JUMP; /* first jump (over LOAD ops.) */ | 394 | int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); |
| 384 | if (e->k != VJMP) | ||
| 385 | fj = luaK_jump(fs); | ||
| 386 | p_f = code_label(fs, reg, 0, 1); | 395 | p_f = code_label(fs, reg, 0, 1); |
| 387 | p_t = code_label(fs, reg, 1, 0); | 396 | p_t = code_label(fs, reg, 1, 0); |
| 388 | luaK_patchtohere(fs, fj); | 397 | luaK_patchtohere(fs, fj); |
| @@ -392,7 +401,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { · 3 unmodified lines | |||
| 392 | patchlistaux(fs, e->t, final, reg, p_t); | 401 | patchlistaux(fs, e->t, final, reg, p_t); |
| 393 | } | 402 | } |
| 394 | e->f = e->t = NO_JUMP; | 403 | e->f = e->t = NO_JUMP; |
| 395 | e->info = reg; | 404 | e->u.s.info = reg; |
| 396 | e->k = VNONRELOC; | 405 | e->k = VNONRELOC; |
| 397 | } | 406 | } |
| 398 | 407 | ||
| @@ -408,14 +417,14 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { · 9 unmodified lines | |||
| 408 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | 417 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
| 409 | luaK_dischargevars(fs, e); | 418 | luaK_dischargevars(fs, e); |
| 410 | if (e->k == VNONRELOC) { | 419 | if (e->k == VNONRELOC) { |
| 411 | if (!hasjumps(e)) return e->info; /* exp is already in a register */ | 420 | if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ |
| 412 | if (e->info >= fs->nactvar) { /* reg. is not a local? */ | 421 | if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ |
| 413 | exp2reg(fs, e, e->info); /* put value on it */ | 422 | exp2reg(fs, e, e->u.s.info); /* put value on it */ |
| 414 | return e->info; | 423 | return e->u.s.info; |
| 415 | } | 424 | } |
| 416 | } | 425 | } |
| 417 | luaK_exp2nextreg(fs, e); /* default */ | 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 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | 439 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
| 431 | luaK_exp2val(fs, e); | 440 | luaK_exp2val(fs, e); |
| 432 | switch (e->k) { | 441 | switch (e->k) { |
| 442 | case VKNUM: | ||
| 433 | case VTRUE: | 443 | case VTRUE: |
| 434 | case VFALSE: | 444 | case VFALSE: |
| 435 | case VNIL: { | 445 | case VNIL: { |
| 436 | if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ | 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 | e->k = VK; | 450 | e->k = VK; |
| 439 | return RKASK(e->info); | 451 | return RKASK(e->u.s.info); |
| 440 | } | 452 | } |
| 441 | else break; | 453 | else break; |
| 442 | } | 454 | } |
| 443 | case VK: { | 455 | case VK: { |
| 444 | if (e->info <= MAXINDEXRK) /* constant fit in argC? */ | 456 | if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ |
| 445 | return RKASK(e->info); | 457 | return RKASK(e->u.s.info); |
| 446 | else break; | 458 | else break; |
| 447 | } | 459 | } |
| 448 | default: break; | 460 | default: break; |
| @@ -456,22 +468,22 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { · 7 unmodified lines | |||
| 456 | switch (var->k) { | 468 | switch (var->k) { |
| 457 | case VLOCAL: { | 469 | case VLOCAL: { |
| 458 | freeexp(fs, ex); | 470 | freeexp(fs, ex); |
| 459 | exp2reg(fs, ex, var->info); | 471 | exp2reg(fs, ex, var->u.s.info); |
| 460 | return; | 472 | return; |
| 461 | } | 473 | } |
| 462 | case VUPVAL: { | 474 | case VUPVAL: { |
| 463 | int e = luaK_exp2anyreg(fs, ex); | 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 | break; | 477 | break; |
| 466 | } | 478 | } |
| 467 | case VGLOBAL: { | 479 | case VGLOBAL: { |
| 468 | int e = luaK_exp2anyreg(fs, ex); | 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 | break; | 482 | break; |
| 471 | } | 483 | } |
| 472 | case VINDEXED: { | 484 | case VINDEXED: { |
| 473 | int e = luaK_exp2RK(fs, ex); | 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 | break; | 487 | break; |
| 476 | } | 488 | } |
| 477 | default: { | 489 | default: { |
| @@ -489,15 +501,15 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { · 11 unmodified lines | |||
| 489 | freeexp(fs, e); | 501 | freeexp(fs, e); |
| 490 | func = fs->freereg; | 502 | func = fs->freereg; |
| 491 | luaK_reserveregs(fs, 2); | 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 | freeexp(fs, key); | 505 | freeexp(fs, key); |
| 494 | e->info = func; | 506 | e->u.s.info = func; |
| 495 | e->k = VNONRELOC; | 507 | e->k = VNONRELOC; |
| 496 | } | 508 | } |
| 497 | 509 | ||
| 498 | 510 | ||
| 499 | static void invertjump (FuncState *fs, expdesc *e) { | 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 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && | 513 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
| 502 | GET_OPCODE(*pc) != OP_TEST); | 514 | GET_OPCODE(*pc) != OP_TEST); |
| 503 | SETARG_A(*pc, !(GETARG_A(*pc))); | 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 | discharge2anyreg(fs, e); | 528 | discharge2anyreg(fs, e); |
| 517 | freeexp(fs, e); | 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 | int pc; /* pc of last jump */ | 535 | int pc; /* pc of last jump */ |
| 524 | luaK_dischargevars(fs, e); | 536 | luaK_dischargevars(fs, e); |
| 525 | switch (e->k) { | 537 | switch (e->k) { |
| 526 | case VK: case VTRUE: { | 538 | case VK: case VKNUM: case VTRUE: { |
| 527 | pc = NO_JUMP; /* always true; do nothing */ | 539 | pc = NO_JUMP; /* always true; do nothing */ |
| 528 | break; | 540 | break; |
| 529 | } | 541 | } |
| @@ -533,7 +545,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { · 3 unmodified lines | |||
| 533 | } | 545 | } |
| 534 | case VJMP: { | 546 | case VJMP: { |
| 535 | invertjump(fs, e); | 547 | invertjump(fs, e); |
| 536 | pc = e->info; | 548 | pc = e->u.s.info; |
| 537 | break; | 549 | break; |
| 538 | } | 550 | } |
| 539 | default: { | 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 | int pc; /* pc of last jump */ | 563 | int pc; /* pc of last jump */ |
| 552 | luaK_dischargevars(fs, e); | 564 | luaK_dischargevars(fs, e); |
| 553 | switch (e->k) { | 565 | switch (e->k) { |
| @@ -560,7 +572,7 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { · 6 unmodified lines | |||
| 560 | break; | 572 | break; |
| 561 | } | 573 | } |
| 562 | case VJMP: { | 574 | case VJMP: { |
| 563 | pc = e->info; | 575 | pc = e->u.s.info; |
| 564 | break; | 576 | break; |
| 565 | } | 577 | } |
| 566 | default: { | 578 | default: { |
| @@ -581,7 +593,7 @@ static void codenot (FuncState *fs, expdesc *e) { · 14 unmodified lines | |||
| 581 | e->k = VTRUE; | 593 | e->k = VTRUE; |
| 582 | break; | 594 | break; |
| 583 | } | 595 | } |
| 584 | case VK: case VTRUE: { | 596 | case VK: case VKNUM: case VTRUE: { |
| 585 | e->k = VFALSE; | 597 | e->k = VFALSE; |
| 586 | break; | 598 | break; |
| 587 | } | 599 | } |
| @@ -593,7 +605,7 @@ static void codenot (FuncState *fs, expdesc *e) { · 5 unmodified lines | |||
| 593 | case VNONRELOC: { | 605 | case VNONRELOC: { |
| 594 | discharge2anyreg(fs, e); | 606 | discharge2anyreg(fs, e); |
| 595 | freeexp(fs, e); | 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 | e->k = VRELOCABLE; | 609 | e->k = VRELOCABLE; |
| 598 | break; | 610 | break; |
| 599 | } | 611 | } |
| @@ -610,34 +622,81 @@ static void codenot (FuncState *fs, expdesc *e) { · 10 unmodified lines | |||
| 610 | 622 | ||
| 611 | 623 | ||
| 612 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | 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 | t->k = VINDEXED; | 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 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { | 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 | switch (op) { | 689 | switch (op) { |
| 620 | case OPR_MINUS: { | 690 | case OPR_MINUS: { |
| 621 | luaK_exp2val(fs, e); | 691 | if (e->k == VK) |
| 622 | if (e->k == VK && ttisnumber(&fs->f->k[e->info])) | 692 | luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ |
| 623 | e->info = luaK_numberK(fs, luai_numunm(L, nvalue(&fs->f->k[e->info]))); | 693 | codearith(fs, OP_UNM, e, &e2); |
| 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); | ||
| 634 | break; | 694 | break; |
| 635 | } | 695 | } |
| 696 | case OPR_NOT: codenot(fs, e); break; | ||
| 636 | case OPR_LEN: { | 697 | case OPR_LEN: { |
| 637 | luaK_exp2anyreg(fs, e); | 698 | luaK_exp2anyreg(fs, e); /* cannot operate on constants */ |
| 638 | freeexp(fs, e); | 699 | codearith(fs, OP_LEN, e, &e2); |
| 639 | e->info = luaK_codeABC(fs, OP_LEN, 0, e->info, 0); | ||
| 640 | e->k = VRELOCABLE; | ||
| 641 | break; | 700 | break; |
| 642 | } | 701 | } |
| 643 | default: lua_assert(0); | 702 | default: lua_assert(0); |
| @@ -660,74 +719,58 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { · 16 unmodified lines | |||
| 660 | break; | 719 | break; |
| 661 | } | 720 | } |
| 662 | default: { | 721 | default: { |
| 663 | luaK_exp2RK(fs, v); | 722 | if (!isnumeral(v)) luaK_exp2RK(fs, v); |
| 664 | break; | 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 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | 729 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { |
| 692 | switch (op) { | 730 | switch (op) { |
| 693 | case OPR_AND: { | 731 | case OPR_AND: { |
| 694 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | 732 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ |
| 695 | luaK_dischargevars(fs, e2); | 733 | luaK_dischargevars(fs, e2); |
| 696 | luaK_concat(fs, &e1->f, e2->f); | 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 | break; | 737 | break; |
| 699 | } | 738 | } |
| 700 | case OPR_OR: { | 739 | case OPR_OR: { |
| 701 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ | 740 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ |
| 702 | luaK_dischargevars(fs, e2); | 741 | luaK_dischargevars(fs, e2); |
| 703 | luaK_concat(fs, &e1->t, e2->t); | 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 | break; | 745 | break; |
| 706 | } | 746 | } |
| 707 | case OPR_CONCAT: { | 747 | case OPR_CONCAT: { |
| 708 | luaK_exp2val(fs, e2); | 748 | luaK_exp2val(fs, e2); |
| 709 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | 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 | freeexp(fs, e1); | 751 | freeexp(fs, e1); |
| 712 | SETARG_B(getcode(fs, e2), e1->info); | 752 | SETARG_B(getcode(fs, e2), e1->u.s.info); |
| 713 | e1->k = e2->k; e1->info = e2->info; | 753 | e1->k = e2->k; e1->u.s.info = e2->u.s.info; |
| 714 | } | 754 | } |
| 715 | else { | 755 | else { |
| 716 | luaK_exp2nextreg(fs, e2); | 756 | luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ |
| 717 | freeexp(fs, e2); | 757 | codearith(fs, OP_CONCAT, e1, e2); |
| 718 | freeexp(fs, e1); | ||
| 719 | e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info); | ||
| 720 | e1->k = VRELOCABLE; | ||
| 721 | } | 758 | } |
| 722 | break; | 759 | break; |
| 723 | } | 760 | } |
| 724 | default: { | 761 | case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; |
| 725 | int o1 = luaK_exp2RK(fs, e1); | 762 | case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; |
| 726 | int o2 = luaK_exp2RK(fs, e2); | 763 | case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; |
| 727 | freeexp(fs, e2); | 764 | case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; |
| 728 | freeexp(fs, e1); | 765 | case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; |
| 729 | codebinop(fs, e1, op, o1, o2); | 766 | case OPR_POW: codearith(fs, OP_POW, e1, e2); break; |
| 730 | } | 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 | Proto *f = fs->f; | 784 | Proto *f = fs->f; |
| 742 | dischargejpc(fs); /* `pc' will change */ | 785 | dischargejpc(fs); /* `pc' will change */ |
| 743 | /* put new instruction in code array */ | 786 | /* put new instruction in code array */ |