diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-04-14 14:47:24 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-04-14 14:47:24 -0300 |
| commit | c1666a13e3cc7aa853a513bc0d739849caf75106 (patch) | |
| tree | 9e9ad4ca6605b74e78c4768df70c3733f11d2725 | |
| parent | e02750ec60189e15b68fe5a6b9d9a9a802b47def (diff) | |
| download | lua-c1666a13e3cc7aa853a513bc0d739849caf75106.tar.gz lua-c1666a13e3cc7aa853a513bc0d739849caf75106.tar.bz2 lua-c1666a13e3cc7aa853a513bc0d739849caf75106.zip | |
better code organization
| -rw-r--r-- | lcode.c | 200 |
1 files changed, 133 insertions, 67 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.24 2000/04/12 18:57:19 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.25 2000/04/13 16:51:01 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 | */ |
| @@ -304,6 +304,49 @@ void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue) { | |||
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | 306 | ||
| 307 | static int code_label (FuncState *fs, OpCode op, int arg) { | ||
| 308 | int j = luaK_getlabel(fs); | ||
| 309 | luaK_code1(fs, op, arg); | ||
| 310 | return j; | ||
| 311 | } | ||
| 312 | |||
| 313 | |||
| 314 | static void jump_to_value (FuncState *fs, expdesc *v, Instruction previous) { | ||
| 315 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ | ||
| 316 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ | ||
| 317 | int final; /* position after whole expression */ | ||
| 318 | if (ISJUMP(previous)) { | ||
| 319 | luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in true list */ | ||
| 320 | p_nil = code_label(fs, OP_PUSHNILJMP, 0); | ||
| 321 | p_1 = code_label(fs, OP_PUSHINT, 1); | ||
| 322 | } | ||
| 323 | else { /* still may need a PUSHNIL or a PUSHINT */ | ||
| 324 | int need_nil = need_value(fs, v->u.l.f, OP_JMPONF); | ||
| 325 | int need_1 = need_value(fs, v->u.l.t, OP_JMPONT); | ||
| 326 | if (need_nil && need_1) { | ||
| 327 | int j = code_label(fs, OP_JMP, 0); /* skip both pushes */ | ||
| 328 | p_nil = code_label(fs, OP_PUSHNILJMP, 0); | ||
| 329 | p_1 = code_label(fs, OP_PUSHINT, 1); | ||
| 330 | luaK_patchlist(fs, j, luaK_getlabel(fs)); | ||
| 331 | luaK_deltastack(fs, -1); /* previous PUSHINT may be skipped */ | ||
| 332 | } | ||
| 333 | else if (need_nil || need_1) { | ||
| 334 | int j = code_label(fs, OP_JMP, 0); /* skip one push */ | ||
| 335 | if (need_nil) | ||
| 336 | p_nil = code_label(fs, OP_PUSHNIL, 1); | ||
| 337 | else /* need_1 */ | ||
| 338 | p_1 = code_label(fs, OP_PUSHINT, 1); | ||
| 339 | luaK_patchlist(fs, j, luaK_getlabel(fs)); | ||
| 340 | luaK_deltastack(fs, -1); /* previous PUSHs may be skipped */ | ||
| 341 | } | ||
| 342 | } | ||
| 343 | final = luaK_getlabel(fs); | ||
| 344 | luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); | ||
| 345 | luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); | ||
| 346 | v->u.l.f = v->u.l.t = NO_JUMP; | ||
| 347 | } | ||
| 348 | |||
| 349 | |||
| 307 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | 350 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { |
| 308 | FuncState *fs = ls->fs; | 351 | FuncState *fs = ls->fs; |
| 309 | if (!discharge(fs, v)) { /* `v' is an expression? */ | 352 | if (!discharge(fs, v)) { /* `v' is an expression? */ |
| @@ -314,38 +357,8 @@ void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | |||
| 314 | if (onlyone) | 357 | if (onlyone) |
| 315 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | 358 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ |
| 316 | } | 359 | } |
| 317 | else { /* expression has jumps... */ | 360 | else /* expression has jumps... */ |
| 318 | int p_nil = 0; /* position of an eventual PUSHNIL */ | 361 | jump_to_value(fs, v, previous); |
| 319 | int p_1 = 0; /* position of an eventual PUSHINT */ | ||
| 320 | int final; /* position after whole expression */ | ||
| 321 | if (ISJUMP(previous)) { | ||
| 322 | luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in true list */ | ||
| 323 | p_nil = luaK_code0(fs, OP_PUSHNILJMP); | ||
| 324 | p_1 = luaK_code1(fs, OP_PUSHINT, 1); | ||
| 325 | } | ||
| 326 | else { /* still may need a PUSHNIL or a PUSHINT */ | ||
| 327 | int need_nil = need_value(fs, v->u.l.f, OP_JMPONF); | ||
| 328 | int need_1 = need_value(fs, v->u.l.t, OP_JMPONT); | ||
| 329 | if (need_nil && need_1) { | ||
| 330 | luaK_code1(fs, OP_JMP, 2); /* skip both pushes */ | ||
| 331 | p_nil = luaK_code0(fs, OP_PUSHNILJMP); | ||
| 332 | p_1 = luaK_code1(fs, OP_PUSHINT, 1); | ||
| 333 | luaK_deltastack(fs, -1); /* previous PUSHINT may be skipped */ | ||
| 334 | } | ||
| 335 | else if (need_nil || need_1) { | ||
| 336 | luaK_code1(fs, OP_JMP, 1); /* skip one push */ | ||
| 337 | if (need_nil) | ||
| 338 | p_nil = luaK_code1(fs, OP_PUSHNIL, 1); | ||
| 339 | else /* need_1 */ | ||
| 340 | p_1 = luaK_code1(fs, OP_PUSHINT, 1); | ||
| 341 | luaK_deltastack(fs, -1); /* previous PUSHs may be skipped */ | ||
| 342 | } | ||
| 343 | } | ||
| 344 | final = luaK_getlabel(fs); | ||
| 345 | luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); | ||
| 346 | luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); | ||
| 347 | v->u.l.f = v->u.l.t = NO_JUMP; | ||
| 348 | } | ||
| 349 | } | 362 | } |
| 350 | } | 363 | } |
| 351 | 364 | ||
| @@ -431,37 +444,93 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
| 431 | int delta = 0; | 444 | int delta = 0; |
| 432 | enum {iO, iU, iS, iAB, iP} mode; /* instruction format (or iP to optimize) */ | 445 | enum {iO, iU, iS, iAB, iP} mode; /* instruction format (or iP to optimize) */ |
| 433 | mode = iP; | 446 | mode = iP; |
| 447 | |||
| 434 | switch (o) { | 448 | switch (o) { |
| 435 | 449 | ||
| 436 | case OP_CLOSURE: delta = -arg2+1; mode = iAB; break; | 450 | case OP_CLOSURE: |
| 437 | case OP_SETLINE: mode = iU; break; | 451 | delta = -arg2+1; |
| 438 | case OP_CALL: mode = iAB; break; | 452 | mode = iAB; |
| 439 | case OP_PUSHINT: delta = 1; mode = iS; break; | 453 | break; |
| 440 | case OP_SETGLOBAL: delta = -1; mode = iU; break; | 454 | |
| 441 | case OP_SETTABLE: delta = -arg2; mode = iAB; break; | 455 | case OP_SETLINE: |
| 442 | case OP_SETLIST: delta = -(arg2+1); mode = iAB; break; | 456 | mode = iU; |
| 443 | case OP_SETMAP: delta = -2*(arg1+1); mode = iU; break; | 457 | break; |
| 444 | case OP_FORLOOP: delta = -3; arg1 = NO_JUMP; mode = iS; break; | 458 | |
| 459 | case OP_CALL: | ||
| 460 | mode = iAB; | ||
| 461 | break; | ||
| 462 | |||
| 463 | case OP_PUSHINT: | ||
| 464 | delta = 1; | ||
| 465 | mode = iS; | ||
| 466 | break; | ||
| 467 | |||
| 468 | case OP_SETTABLE: | ||
| 469 | delta = -arg2; | ||
| 470 | mode = iAB; | ||
| 471 | break; | ||
| 472 | |||
| 473 | case OP_SETLIST: | ||
| 474 | delta = -(arg2+1); | ||
| 475 | mode = iAB; | ||
| 476 | break; | ||
| 445 | 477 | ||
| 446 | case OP_FORPREP: arg1 = NO_JUMP; /* go through */ | 478 | case OP_SETMAP: |
| 447 | case OP_JMP: mode = iS; break; | 479 | delta = -2*(arg1+1); |
| 480 | mode = iU; | ||
| 481 | break; | ||
| 448 | 482 | ||
| 449 | case OP_END: case OP_PUSHNILJMP: case OP_NOT: | 483 | case OP_FORLOOP: |
| 450 | mode = iO; break; | 484 | delta = -3; |
| 485 | arg1 = NO_JUMP; | ||
| 486 | mode = iS; | ||
| 487 | break; | ||
| 451 | 488 | ||
| 452 | case OP_PUSHSTRING: case OP_PUSHNUM: | 489 | case OP_SETLOCAL: |
| 453 | case OP_PUSHNEGNUM: case OP_PUSHUPVALUE: | 490 | case OP_SETGLOBAL: |
| 454 | case OP_GETGLOBAL: case OP_PUSHSELF: case OP_CREATETABLE: | 491 | delta = -1; |
| 455 | delta = 1; mode = iU; break; | 492 | mode = iU; |
| 493 | break; | ||
| 456 | 494 | ||
| 457 | case OP_JMPLT: case OP_JMPLE: case OP_JMPGT: case OP_JMPGE: | 495 | case OP_FORPREP: |
| 458 | delta = -2; arg1 = NO_JUMP; mode = iS; break; | 496 | case OP_JMP: |
| 497 | arg1 = NO_JUMP; | ||
| 498 | mode = iS; | ||
| 499 | break; | ||
| 459 | 500 | ||
| 460 | case OP_MULT: case OP_DIV: case OP_POW: | 501 | case OP_END: |
| 461 | delta = -1; mode = iO; break; | 502 | case OP_PUSHNILJMP: |
| 503 | case OP_NOT: | ||
| 504 | mode = iO; | ||
| 505 | break; | ||
| 462 | 506 | ||
| 463 | case OP_SETLOCAL: /* `setlocal' default pops one value */ | 507 | case OP_PUSHSTRING: |
| 464 | delta = -1; arg2 = 1; mode = iAB; break; | 508 | case OP_PUSHNUM: |
| 509 | case OP_PUSHNEGNUM: | ||
| 510 | case OP_PUSHUPVALUE: | ||
| 511 | case OP_GETLOCAL: | ||
| 512 | case OP_GETGLOBAL: | ||
| 513 | case OP_PUSHSELF: | ||
| 514 | case OP_CREATETABLE: | ||
| 515 | delta = 1; | ||
| 516 | mode = iU; | ||
| 517 | break; | ||
| 518 | |||
| 519 | case OP_JMPLT: | ||
| 520 | case OP_JMPLE: | ||
| 521 | case OP_JMPGT: | ||
| 522 | case OP_JMPGE: | ||
| 523 | delta = -2; | ||
| 524 | arg1 = NO_JUMP; | ||
| 525 | mode = iS; | ||
| 526 | break; | ||
| 527 | |||
| 528 | case OP_MULT: | ||
| 529 | case OP_DIV: | ||
| 530 | case OP_POW: | ||
| 531 | delta = -1; | ||
| 532 | mode = iO; | ||
| 533 | break; | ||
| 465 | 534 | ||
| 466 | case OP_RETURN: | 535 | case OP_RETURN: |
| 467 | if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) { | 536 | if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) { |
| @@ -483,18 +552,10 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
| 483 | delta = -arg1; | 552 | delta = -arg1; |
| 484 | switch(GET_OPCODE(i)) { | 553 | switch(GET_OPCODE(i)) { |
| 485 | case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); break; | 554 | case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); break; |
| 486 | case OP_SETLOCAL: SETARG_B(i, GETARG_B(i)+arg1); break; | ||
| 487 | default: mode = iU; break; | 555 | default: mode = iU; break; |
| 488 | } | 556 | } |
| 489 | break; | 557 | break; |
| 490 | 558 | ||
| 491 | case OP_GETLOCAL: | ||
| 492 | delta = 1; | ||
| 493 | if (i == CREATE_AB(OP_SETLOCAL, arg1, 1)) | ||
| 494 | SETARG_B(i, 0); | ||
| 495 | else mode = iU; | ||
| 496 | break; | ||
| 497 | |||
| 498 | case OP_GETTABLE: | 559 | case OP_GETTABLE: |
| 499 | delta = -1; | 560 | delta = -1; |
| 500 | switch(GET_OPCODE(i)) { | 561 | switch(GET_OPCODE(i)) { |
| @@ -558,7 +619,10 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
| 558 | } | 619 | } |
| 559 | break; | 620 | break; |
| 560 | 621 | ||
| 561 | case OP_JMPT: case OP_JMPF: case OP_JMPONT: case OP_JMPONF: | 622 | case OP_JMPT: |
| 623 | case OP_JMPF: | ||
| 624 | case OP_JMPONT: | ||
| 625 | case OP_JMPONF: | ||
| 562 | delta = -1; | 626 | delta = -1; |
| 563 | arg1 = NO_JUMP; | 627 | arg1 = NO_JUMP; |
| 564 | switch (GET_OPCODE(i)) { | 628 | switch (GET_OPCODE(i)) { |
| @@ -567,8 +631,10 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
| 567 | } | 631 | } |
| 568 | break; | 632 | break; |
| 569 | 633 | ||
| 570 | case OP_GETDOTTED: case OP_GETINDEXED: | 634 | case OP_GETDOTTED: |
| 571 | case OP_TAILCALL: case OP_ADDI: | 635 | case OP_GETINDEXED: |
| 636 | case OP_TAILCALL: | ||
| 637 | case OP_ADDI: | ||
| 572 | LUA_INTERNALERROR(L, "instruction used only for optimizations"); | 638 | LUA_INTERNALERROR(L, "instruction used only for optimizations"); |
| 573 | return 0; /* to avoid warnings */ | 639 | return 0; /* to avoid warnings */ |
| 574 | 640 | ||
