|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
-** $Id: lcode.c,v 2.128 2017/10/02 22:50:57 roberto Exp roberto $
|
|
|
|
|
|
+** $Id: lcode.c,v 2.129 2017/10/04 15:49:24 roberto Exp roberto $
|
|
** Code generator for Lua
|
|
** Code generator for Lua
|
|
** See Copyright Notice in lua.h
|
|
** See Copyright Notice in lua.h
|
|
*/
|
|
*/
|
|
@@ -202,7 +202,7 @@ static int patchtestreg (FuncState *fs, int node, int reg) {
|
|
else {
|
|
else {
|
|
/* no register to put value or register already has the value;
|
|
/* no register to put value or register already has the value;
|
|
change instruction to simple test */
|
|
change instruction to simple test */
|
|
- *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
|
|
|
|
|
|
+ *i = CREATE_ABCk(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i), 0);
|
|
}
|
|
}
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -365,13 +365,18 @@ static int luaK_code (FuncState *fs, Instruction i) {
|
|
** Format and emit an 'iABC' instruction. (Assertions check consistency
|
|
** Format and emit an 'iABC' instruction. (Assertions check consistency
|
|
** of parameters versus opcode.)
|
|
** of parameters versus opcode.)
|
|
*/
|
|
*/
|
|
-int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
|
|
|
|
|
|
+int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) {
|
|
lua_assert(getOpMode(o) == iABC);
|
|
lua_assert(getOpMode(o) == iABC);
|
|
- lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C);
|
|
|
|
- return luaK_code(fs, CREATE_ABC(o, a, b, c));
|
|
|
|
|
|
+ lua_assert(a <= MAXARG_A && b <= MAXARG_B &&
|
|
|
|
+ c <= MAXARG_C && (k & ~1) == 0);
|
|
|
|
+ return luaK_code(fs, CREATE_ABCk(o, a, b, c, k));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+#define codeABsC(fs,o,a,b,c,k) luaK_codeABCk(fs,o,a,b,((c) + MAXARG_sC),k)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
/*
|
|
/*
|
|
** Format and emit an 'iABx' instruction.
|
|
** Format and emit an 'iABx' instruction.
|
|
*/
|
|
*/
|
|
@@ -448,7 +453,7 @@ void luaK_reserveregs (FuncState *fs, int n) {
|
|
)
|
|
)
|
|
*/
|
|
*/
|
|
static void freereg (FuncState *fs, int reg) {
|
|
static void freereg (FuncState *fs, int reg) {
|
|
- if (!ISK(reg) && reg >= fs->nactvar) {
|
|
|
|
|
|
+ if (reg >= fs->nactvar) {
|
|
fs->freereg--;
|
|
fs->freereg--;
|
|
lua_assert(reg == fs->freereg);
|
|
lua_assert(reg == fs->freereg);
|
|
}
|
|
}
|
|
@@ -853,7 +858,7 @@ void luaK_exp2val (FuncState *fs, expdesc *e) {
|
|
** Ensures final expression result is in a valid R/K index
|
|
** Ensures final expression result is in a valid R/K index
|
|
** (that is, it is either in a register or in 'k' with an index
|
|
** (that is, it is either in a register or in 'k' with an index
|
|
** in the range of R/K indices).
|
|
** in the range of R/K indices).
|
|
-** Returns R/K index.
|
|
|
|
|
|
+** Returns 1 if expression is K, 0 otherwise.
|
|
*/
|
|
*/
|
|
int luaK_exp2RK (FuncState *fs, expdesc *e) {
|
|
int luaK_exp2RK (FuncState *fs, expdesc *e) {
|
|
luaK_exp2val(fs, e);
|
|
luaK_exp2val(fs, e);
|
|
@@ -867,12 +872,20 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
|
|
vk:
|
|
vk:
|
|
e->k = VK;
|
|
e->k = VK;
|
|
if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */
|
|
if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */
|
|
- return RKASK(e->u.info);
|
|
|
|
|
|
+ return 1;
|
|
else break;
|
|
else break;
|
|
default: break;
|
|
default: break;
|
|
}
|
|
}
|
|
/* not a constant in the right range: put it in a register */
|
|
/* not a constant in the right range: put it in a register */
|
|
- return luaK_exp2anyreg(fs, e);
|
|
|
|
|
|
+ luaK_exp2anyreg(fs, e);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void codeABRK (FuncState *fs, OpCode o, int a, int b,
|
|
|
|
+ expdesc *ec) {
|
|
|
|
+ int k = luaK_exp2RK(fs, ec);
|
|
|
|
+ luaK_codeABCk(fs, o, a, b, ec->u.info, k);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -892,23 +905,19 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case VINDEXUP: {
|
|
case VINDEXUP: {
|
|
- int e = luaK_exp2RK(fs, ex);
|
|
|
|
- luaK_codeABC(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, e);
|
|
|
|
|
|
+ codeABRK(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, ex);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case VINDEXI: {
|
|
case VINDEXI: {
|
|
- int e = luaK_exp2RK(fs, ex);
|
|
|
|
- luaK_codeABC(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, e);
|
|
|
|
|
|
+ codeABRK(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, ex);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case VINDEXSTR: {
|
|
case VINDEXSTR: {
|
|
- int e = luaK_exp2RK(fs, ex);
|
|
|
|
- luaK_codeABC(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, e);
|
|
|
|
|
|
+ codeABRK(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, ex);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case VINDEXED: {
|
|
case VINDEXED: {
|
|
- int e = luaK_exp2RK(fs, ex);
|
|
|
|
- luaK_codeABC(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, e);
|
|
|
|
|
|
+ codeABRK(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, ex);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
default: lua_assert(0); /* invalid var kind to store */
|
|
default: lua_assert(0); /* invalid var kind to store */
|
|
@@ -928,7 +937,7 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
|
|
e->u.info = fs->freereg; /* base register for op_self */
|
|
e->u.info = fs->freereg; /* base register for op_self */
|
|
e->k = VNONRELOC; /* self expression has a fixed register */
|
|
e->k = VNONRELOC; /* self expression has a fixed register */
|
|
luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */
|
|
luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */
|
|
- luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key));
|
|
|
|
|
|
+ codeABRK(fs, OP_SELF, e->u.info, ereg, key);
|
|
freeexp(fs, key);
|
|
freeexp(fs, key);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1064,11 +1073,21 @@ static int isKstr (FuncState *fs, expdesc *e) {
|
|
|
|
|
|
/*
|
|
/*
|
|
** Check whether expression 'e' is a literal integer in
|
|
** Check whether expression 'e' is a literal integer in
|
|
-** proper range
|
|
|
|
|
|
+** proper range to fit in register C
|
|
|
|
+*/
|
|
|
|
+static int isCint (expdesc *e) {
|
|
|
|
+ return (e->k == VKINT && !hasjumps(e) &&
|
|
|
|
+ l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+** Check whether expression 'e' is a literal integer in
|
|
|
|
+** proper range to fit in register sC
|
|
*/
|
|
*/
|
|
-static int isKint (expdesc *e) {
|
|
|
|
|
|
+static int isSCint (expdesc *e) {
|
|
return (e->k == VKINT && !hasjumps(e) &&
|
|
return (e->k == VKINT && !hasjumps(e) &&
|
|
- l_castS2U(e->u.ival) <= l_castS2U(MAXARG_Cr));
|
|
|
|
|
|
+ l_castS2U(e->u.ival + MAXARG_sC) <= l_castS2U(MAXARG_C));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1091,7 +1110,7 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
|
|
t->u.ind.idx = k->u.info; /* literal string */
|
|
t->u.ind.idx = k->u.info; /* literal string */
|
|
t->k = VINDEXSTR;
|
|
t->k = VINDEXSTR;
|
|
}
|
|
}
|
|
- else if (isKint(k)) {
|
|
|
|
|
|
+ else if (isCint(k)) {
|
|
t->u.ind.idx = k->u.ival; /* integer constant */
|
|
t->u.ind.idx = k->u.ival; /* integer constant */
|
|
t->k = VINDEXI;
|
|
t->k = VINDEXI;
|
|
}
|
|
}
|
|
@@ -1187,16 +1206,14 @@ static void codebinexpval (FuncState *fs, OpCode op,
|
|
*/
|
|
*/
|
|
static void codearith (FuncState *fs, OpCode op,
|
|
static void codearith (FuncState *fs, OpCode op,
|
|
expdesc *e1, expdesc *e2, int flip, int line) {
|
|
expdesc *e1, expdesc *e2, int flip, int line) {
|
|
- if (!isKint(e2))
|
|
|
|
|
|
+ if (!isSCint(e2))
|
|
codebinexpval(fs, op, e1, e2, line); /* use standard operators */
|
|
codebinexpval(fs, op, e1, e2, line); /* use standard operators */
|
|
else { /* use immediate operators */
|
|
else { /* use immediate operators */
|
|
int v2 = cast_int(e2->u.ival); /* immediate operand */
|
|
int v2 = cast_int(e2->u.ival); /* immediate operand */
|
|
int v1 = luaK_exp2anyreg(fs, e1);
|
|
int v1 = luaK_exp2anyreg(fs, e1);
|
|
- if (flip)
|
|
|
|
- v2 |= BITRK; /* signal that operands were flipped */
|
|
|
|
op = cast(OpCode, op - OP_ADD + OP_ADDI);
|
|
op = cast(OpCode, op - OP_ADD + OP_ADDI);
|
|
freeexp(fs, e1);
|
|
freeexp(fs, e1);
|
|
- e1->u.info = luaK_codeABC(fs, op, 0, v1, v2); /* generate opcode */
|
|
|
|
|
|
+ e1->u.info = codeABsC(fs, op, 0, v1, v2, flip); /* generate opcode */
|
|
e1->k = VRELOCABLE; /* all those operations are relocatable */
|
|
e1->k = VRELOCABLE; /* all those operations are relocatable */
|
|
luaK_fixline(fs, line);
|
|
luaK_fixline(fs, line);
|
|
}
|
|
}
|
|
@@ -1210,7 +1227,7 @@ static void codearith (FuncState *fs, OpCode op,
|
|
static void codecommutative (FuncState *fs, OpCode op,
|
|
static void codecommutative (FuncState *fs, OpCode op,
|
|
expdesc *e1, expdesc *e2, int line) {
|
|
expdesc *e1, expdesc *e2, int line) {
|
|
int flip = 0;
|
|
int flip = 0;
|
|
- if (isKint(e1)) {
|
|
|
|
|
|
+ if (isSCint(e1)) {
|
|
expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */
|
|
expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */
|
|
flip = 1;
|
|
flip = 1;
|
|
}
|
|
}
|
|
@@ -1223,8 +1240,7 @@ static void codecommutative (FuncState *fs, OpCode op,
|
|
** 'e1' was already put in register by 'luaK_infix'.
|
|
** 'e1' was already put in register by 'luaK_infix'.
|
|
*/
|
|
*/
|
|
static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
|
|
static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
|
|
- int rk1 = (e1->k == VK) ? RKASK(e1->u.info)
|
|
|
|
- : check_exp(e1->k == VNONRELOC, e1->u.info);
|
|
|
|
|
|
+ int rk1 = check_exp(e1->k == VNONRELOC, e1->u.info);
|
|
int rk2 = luaK_exp2anyreg(fs, e2);
|
|
int rk2 = luaK_exp2anyreg(fs, e2);
|
|
freeexps(fs, e1, e2);
|
|
freeexps(fs, e1, e2);
|
|
switch (opr) {
|
|
switch (opr) {
|