diff options
| -rw-r--r-- | lcode.c | 88 |
1 files changed, 35 insertions, 53 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.94 2002/04/02 20:34:53 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.95 2002/04/09 18:49:30 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 | */ |
| @@ -293,33 +293,6 @@ static int code_label (FuncState *fs, int A, int b, int jump) { | |||
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | 295 | ||
| 296 | static void dischargejumps (FuncState *fs, expdesc *e, int reg) { | ||
| 297 | if (e->k == VJMP || hasjumps(e)) { | ||
| 298 | int final; /* position after whole expression */ | ||
| 299 | int p_f = NO_JUMP; /* position of an eventual PUSH false */ | ||
| 300 | int p_t = NO_JUMP; /* position of an eventual PUSH true */ | ||
| 301 | if (e->k == VJMP || need_value(fs, e->f, OP_TESTF) || | ||
| 302 | need_value(fs, e->t, OP_TESTT)) { | ||
| 303 | /* expression needs values */ | ||
| 304 | if (e->k != VJMP) { | ||
| 305 | luaK_getlabel(fs); /* these instruction may be jump target */ | ||
| 306 | luaK_codeAsBc(fs, OP_JMP, 0, 2); /* to jump over both pushes */ | ||
| 307 | } | ||
| 308 | else { /* last expression is a conditional (test + jump) */ | ||
| 309 | fs->pc--; /* remove its jump */ | ||
| 310 | lua_assert(testOpMode(GET_OPCODE(fs->f->code[fs->pc - 1]), OpModeT)); | ||
| 311 | } | ||
| 312 | p_t = code_label(fs, reg, 1, 1); | ||
| 313 | p_f = code_label(fs, reg, 0, 0); | ||
| 314 | } | ||
| 315 | final = luaK_getlabel(fs); | ||
| 316 | luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); | ||
| 317 | luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); | ||
| 318 | } | ||
| 319 | e->f = e->t = NO_JUMP; | ||
| 320 | } | ||
| 321 | |||
| 322 | |||
| 323 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | 296 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { |
| 324 | luaK_dischargevars(fs, e); | 297 | luaK_dischargevars(fs, e); |
| 325 | switch (e->k) { | 298 | switch (e->k) { |
| @@ -340,7 +313,15 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
| 340 | SETARG_A(*pc, reg); | 313 | SETARG_A(*pc, reg); |
| 341 | break; | 314 | break; |
| 342 | } | 315 | } |
| 343 | default: return; | 316 | case VNONRELOC: { |
| 317 | if (reg != e->info) | ||
| 318 | luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); | ||
| 319 | break; | ||
| 320 | } | ||
| 321 | default: { | ||
| 322 | lua_assert(e->k == VVOID || e->k == VJMP); | ||
| 323 | return; /* nothing to do... */ | ||
| 324 | } | ||
| 344 | } | 325 | } |
| 345 | e->info = reg; | 326 | e->info = reg; |
| 346 | e->k = VNONRELOC; | 327 | e->k = VNONRELOC; |
| @@ -357,36 +338,39 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) { | |||
| 357 | 338 | ||
| 358 | static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) { | 339 | static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) { |
| 359 | discharge2reg(fs, e, reg); | 340 | discharge2reg(fs, e, reg); |
| 360 | switch (e->k) { | 341 | if (e->k == VJMP || hasjumps(e)) { |
| 361 | case VVOID: { | 342 | int final; /* position after whole expression */ |
| 362 | return; /* nothing to do... */ | 343 | int p_f = NO_JUMP; /* position of an eventual PUSH false */ |
| 363 | } | 344 | int p_t = NO_JUMP; /* position of an eventual PUSH true */ |
| 364 | case VNONRELOC: { | 345 | if (e->k == VJMP || need_value(fs, e->f, OP_TESTF) || |
| 365 | if (reg != e->info) | 346 | need_value(fs, e->t, OP_TESTT)) { |
| 366 | luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); | 347 | /* expression needs values */ |
| 367 | break; | 348 | if (e->k != VJMP) { |
| 368 | } | 349 | luaK_getlabel(fs); /* these instruction may be jump target */ |
| 369 | case VJMP: { | 350 | luaK_codeAsBc(fs, OP_JMP, 0, 2); /* to jump over both pushes */ |
| 370 | break; | 351 | } |
| 371 | } | 352 | else { /* last expression is a conditional (test + jump) */ |
| 372 | default: { | 353 | fs->pc--; /* remove its jump */ |
| 373 | lua_assert(0); /* cannot happen */ | 354 | lua_assert(testOpMode(GET_OPCODE(fs->f->code[fs->pc - 1]), OpModeT)); |
| 374 | break; | 355 | } |
| 356 | p_t = code_label(fs, reg, 1, 1); | ||
| 357 | p_f = code_label(fs, reg, 0, 0); | ||
| 375 | } | 358 | } |
| 359 | final = luaK_getlabel(fs); | ||
| 360 | luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); | ||
| 361 | luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); | ||
| 376 | } | 362 | } |
| 377 | dischargejumps(fs, e, reg); | 363 | e->f = e->t = NO_JUMP; |
| 378 | e->info = reg; | 364 | e->info = reg; |
| 379 | e->k = VNONRELOC; | 365 | e->k = VNONRELOC; |
| 380 | } | 366 | } |
| 381 | 367 | ||
| 382 | 368 | ||
| 383 | void luaK_exp2nextreg (FuncState *fs, expdesc *e) { | 369 | void luaK_exp2nextreg (FuncState *fs, expdesc *e) { |
| 384 | int reg; | ||
| 385 | luaK_dischargevars(fs, e); | 370 | luaK_dischargevars(fs, e); |
| 386 | freeexp(fs, e); | 371 | freeexp(fs, e); |
| 387 | reg = fs->freereg; | ||
| 388 | luaK_reserveregs(fs, 1); | 372 | luaK_reserveregs(fs, 1); |
| 389 | luaK_exp2reg(fs, e, reg); | 373 | luaK_exp2reg(fs, e, fs->freereg - 1); |
| 390 | } | 374 | } |
| 391 | 375 | ||
| 392 | 376 | ||
| @@ -395,7 +379,7 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | |||
| 395 | if (e->k == VNONRELOC) { | 379 | if (e->k == VNONRELOC) { |
| 396 | if (!hasjumps(e)) return e->info; /* exp is already in a register */ | 380 | if (!hasjumps(e)) return e->info; /* exp is already in a register */ |
| 397 | if (e->info >= fs->nactloc) { /* reg. is not a local? */ | 381 | if (e->info >= fs->nactloc) { /* reg. is not a local? */ |
| 398 | dischargejumps(fs, e, e->info); /* put value on it */ | 382 | luaK_exp2reg(fs, e, e->info); /* put value on it */ |
| 399 | return e->info; | 383 | return e->info; |
| 400 | } | 384 | } |
| 401 | } | 385 | } |
| @@ -440,23 +424,20 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { | |||
| 440 | case VLOCAL: { | 424 | case VLOCAL: { |
| 441 | freeexp(fs, exp); | 425 | freeexp(fs, exp); |
| 442 | luaK_exp2reg(fs, exp, var->info); | 426 | luaK_exp2reg(fs, exp, var->info); |
| 443 | break; | 427 | return; |
| 444 | } | 428 | } |
| 445 | case VUPVAL: { | 429 | case VUPVAL: { |
| 446 | int e = luaK_exp2anyreg(fs, exp); | 430 | int e = luaK_exp2anyreg(fs, exp); |
| 447 | freereg(fs, e); | ||
| 448 | luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0); | 431 | luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0); |
| 449 | break; | 432 | break; |
| 450 | } | 433 | } |
| 451 | case VGLOBAL: { | 434 | case VGLOBAL: { |
| 452 | int e = luaK_exp2anyreg(fs, exp); | 435 | int e = luaK_exp2anyreg(fs, exp); |
| 453 | freereg(fs, e); | ||
| 454 | luaK_codeABc(fs, OP_SETGLOBAL, e, var->info); | 436 | luaK_codeABc(fs, OP_SETGLOBAL, e, var->info); |
| 455 | break; | 437 | break; |
| 456 | } | 438 | } |
| 457 | case VINDEXED: { | 439 | case VINDEXED: { |
| 458 | int e = luaK_exp2anyreg(fs, exp); | 440 | int e = luaK_exp2anyreg(fs, exp); |
| 459 | freereg(fs, e); | ||
| 460 | luaK_codeABC(fs, OP_SETTABLE, e, var->info, var->aux); | 441 | luaK_codeABC(fs, OP_SETTABLE, e, var->info, var->aux); |
| 461 | break; | 442 | break; |
| 462 | } | 443 | } |
| @@ -465,6 +446,7 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { | |||
| 465 | break; | 446 | break; |
| 466 | } | 447 | } |
| 467 | } | 448 | } |
| 449 | freeexp(fs, exp); | ||
| 468 | } | 450 | } |
| 469 | 451 | ||
| 470 | 452 | ||
