|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
-** $Id: lcode.c,v 1.94 2002/04/02 20:34:53 roberto Exp roberto $
|
|
|
|
|
|
+** $Id: lcode.c,v 1.95 2002/04/09 18:49:30 roberto Exp roberto $
|
|
** Code generator for Lua
|
|
** Code generator for Lua
|
|
** See Copyright Notice in lua.h
|
|
** See Copyright Notice in lua.h
|
|
*/
|
|
*/
|
|
@@ -293,33 +293,6 @@ static int code_label (FuncState *fs, int A, int b, int jump) {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-static void dischargejumps (FuncState *fs, expdesc *e, int reg) {
|
|
|
|
- if (e->k == VJMP || hasjumps(e)) {
|
|
|
|
- int final; /* position after whole expression */
|
|
|
|
- int p_f = NO_JUMP; /* position of an eventual PUSH false */
|
|
|
|
- int p_t = NO_JUMP; /* position of an eventual PUSH true */
|
|
|
|
- if (e->k == VJMP || need_value(fs, e->f, OP_TESTF) ||
|
|
|
|
- need_value(fs, e->t, OP_TESTT)) {
|
|
|
|
- /* expression needs values */
|
|
|
|
- if (e->k != VJMP) {
|
|
|
|
- luaK_getlabel(fs); /* these instruction may be jump target */
|
|
|
|
- luaK_codeAsBc(fs, OP_JMP, 0, 2); /* to jump over both pushes */
|
|
|
|
- }
|
|
|
|
- else { /* last expression is a conditional (test + jump) */
|
|
|
|
- fs->pc--; /* remove its jump */
|
|
|
|
- lua_assert(testOpMode(GET_OPCODE(fs->f->code[fs->pc - 1]), OpModeT));
|
|
|
|
- }
|
|
|
|
- p_t = code_label(fs, reg, 1, 1);
|
|
|
|
- p_f = code_label(fs, reg, 0, 0);
|
|
|
|
- }
|
|
|
|
- final = luaK_getlabel(fs);
|
|
|
|
- luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f);
|
|
|
|
- luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t);
|
|
|
|
- }
|
|
|
|
- e->f = e->t = NO_JUMP;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
|
|
static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
|
|
luaK_dischargevars(fs, e);
|
|
luaK_dischargevars(fs, e);
|
|
switch (e->k) {
|
|
switch (e->k) {
|
|
@@ -340,7 +313,15 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
|
|
SETARG_A(*pc, reg);
|
|
SETARG_A(*pc, reg);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- default: return;
|
|
|
|
|
|
+ case VNONRELOC: {
|
|
|
|
+ if (reg != e->info)
|
|
|
|
+ luaK_codeABC(fs, OP_MOVE, reg, e->info, 0);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ default: {
|
|
|
|
+ lua_assert(e->k == VVOID || e->k == VJMP);
|
|
|
|
+ return; /* nothing to do... */
|
|
|
|
+ }
|
|
}
|
|
}
|
|
e->info = reg;
|
|
e->info = reg;
|
|
e->k = VNONRELOC;
|
|
e->k = VNONRELOC;
|
|
@@ -357,36 +338,39 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) {
|
|
|
|
|
|
static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) {
|
|
static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) {
|
|
discharge2reg(fs, e, reg);
|
|
discharge2reg(fs, e, reg);
|
|
- switch (e->k) {
|
|
|
|
- case VVOID: {
|
|
|
|
- return; /* nothing to do... */
|
|
|
|
- }
|
|
|
|
- case VNONRELOC: {
|
|
|
|
- if (reg != e->info)
|
|
|
|
- luaK_codeABC(fs, OP_MOVE, reg, e->info, 0);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- case VJMP: {
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- default: {
|
|
|
|
- lua_assert(0); /* cannot happen */
|
|
|
|
- break;
|
|
|
|
|
|
+ if (e->k == VJMP || hasjumps(e)) {
|
|
|
|
+ int final; /* position after whole expression */
|
|
|
|
+ int p_f = NO_JUMP; /* position of an eventual PUSH false */
|
|
|
|
+ int p_t = NO_JUMP; /* position of an eventual PUSH true */
|
|
|
|
+ if (e->k == VJMP || need_value(fs, e->f, OP_TESTF) ||
|
|
|
|
+ need_value(fs, e->t, OP_TESTT)) {
|
|
|
|
+ /* expression needs values */
|
|
|
|
+ if (e->k != VJMP) {
|
|
|
|
+ luaK_getlabel(fs); /* these instruction may be jump target */
|
|
|
|
+ luaK_codeAsBc(fs, OP_JMP, 0, 2); /* to jump over both pushes */
|
|
|
|
+ }
|
|
|
|
+ else { /* last expression is a conditional (test + jump) */
|
|
|
|
+ fs->pc--; /* remove its jump */
|
|
|
|
+ lua_assert(testOpMode(GET_OPCODE(fs->f->code[fs->pc - 1]), OpModeT));
|
|
|
|
+ }
|
|
|
|
+ p_t = code_label(fs, reg, 1, 1);
|
|
|
|
+ p_f = code_label(fs, reg, 0, 0);
|
|
}
|
|
}
|
|
|
|
+ final = luaK_getlabel(fs);
|
|
|
|
+ luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f);
|
|
|
|
+ luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t);
|
|
}
|
|
}
|
|
- dischargejumps(fs, e, reg);
|
|
|
|
|
|
+ e->f = e->t = NO_JUMP;
|
|
e->info = reg;
|
|
e->info = reg;
|
|
e->k = VNONRELOC;
|
|
e->k = VNONRELOC;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
|
|
void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
|
|
- int reg;
|
|
|
|
luaK_dischargevars(fs, e);
|
|
luaK_dischargevars(fs, e);
|
|
freeexp(fs, e);
|
|
freeexp(fs, e);
|
|
- reg = fs->freereg;
|
|
|
|
luaK_reserveregs(fs, 1);
|
|
luaK_reserveregs(fs, 1);
|
|
- luaK_exp2reg(fs, e, reg);
|
|
|
|
|
|
+ luaK_exp2reg(fs, e, fs->freereg - 1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -395,7 +379,7 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
|
|
if (e->k == VNONRELOC) {
|
|
if (e->k == VNONRELOC) {
|
|
if (!hasjumps(e)) return e->info; /* exp is already in a register */
|
|
if (!hasjumps(e)) return e->info; /* exp is already in a register */
|
|
if (e->info >= fs->nactloc) { /* reg. is not a local? */
|
|
if (e->info >= fs->nactloc) { /* reg. is not a local? */
|
|
- dischargejumps(fs, e, e->info); /* put value on it */
|
|
|
|
|
|
+ luaK_exp2reg(fs, e, e->info); /* put value on it */
|
|
return e->info;
|
|
return e->info;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -440,23 +424,20 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
|
|
case VLOCAL: {
|
|
case VLOCAL: {
|
|
freeexp(fs, exp);
|
|
freeexp(fs, exp);
|
|
luaK_exp2reg(fs, exp, var->info);
|
|
luaK_exp2reg(fs, exp, var->info);
|
|
- break;
|
|
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
case VUPVAL: {
|
|
case VUPVAL: {
|
|
int e = luaK_exp2anyreg(fs, exp);
|
|
int e = luaK_exp2anyreg(fs, exp);
|
|
- freereg(fs, e);
|
|
|
|
luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0);
|
|
luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case VGLOBAL: {
|
|
case VGLOBAL: {
|
|
int e = luaK_exp2anyreg(fs, exp);
|
|
int e = luaK_exp2anyreg(fs, exp);
|
|
- freereg(fs, e);
|
|
|
|
luaK_codeABc(fs, OP_SETGLOBAL, e, var->info);
|
|
luaK_codeABc(fs, OP_SETGLOBAL, e, var->info);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case VINDEXED: {
|
|
case VINDEXED: {
|
|
int e = luaK_exp2anyreg(fs, exp);
|
|
int e = luaK_exp2anyreg(fs, exp);
|
|
- freereg(fs, e);
|
|
|
|
luaK_codeABC(fs, OP_SETTABLE, e, var->info, var->aux);
|
|
luaK_codeABC(fs, OP_SETTABLE, e, var->info, var->aux);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -465,6 +446,7 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ freeexp(fs, exp);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|