diff options
-rw-r--r-- | lcode.c | 73 | ||||
-rw-r--r-- | lopcodes.c | 4 | ||||
-rw-r--r-- | lopcodes.h | 3 | ||||
-rw-r--r-- | lvm.c | 13 |
4 files changed, 68 insertions, 25 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.132 2017/11/08 14:50:23 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.133 2017/11/16 12:59:14 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 | */ |
@@ -607,12 +607,17 @@ void luaK_int (FuncState *fs, int reg, lua_Integer i) { | |||
607 | } | 607 | } |
608 | 608 | ||
609 | 609 | ||
610 | static void luaK_float (FuncState *fs, int reg, lua_Number f) { | 610 | static int floatI (lua_Number f, lua_Integer *fi) { |
611 | TValue v; | 611 | TValue v; |
612 | lua_Integer fi; | ||
613 | setfltvalue(&v, f); | 612 | setfltvalue(&v, f); |
614 | if (luaV_flttointeger(&v, &fi, 0) && | 613 | return (luaV_flttointeger(&v, fi, 0) && |
615 | l_castS2U(fi) + MAXARG_sBx <= l_castS2U(MAXARG_Bx)) | 614 | l_castS2U(*fi) + MAXARG_sBx <= l_castS2U(MAXARG_Bx)); |
615 | } | ||
616 | |||
617 | |||
618 | static void luaK_float (FuncState *fs, int reg, lua_Number f) { | ||
619 | lua_Integer fi; | ||
620 | if (floatI(f, &fi)) | ||
616 | luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); | 621 | luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); |
617 | else | 622 | else |
618 | luaK_codek(fs, reg, luaK_numberK(fs, f)); | 623 | luaK_codek(fs, reg, luaK_numberK(fs, f)); |
@@ -1107,6 +1112,20 @@ static int isSCint (expdesc *e) { | |||
1107 | 1112 | ||
1108 | 1113 | ||
1109 | /* | 1114 | /* |
1115 | ** Check whether expression 'e' is a literal integer or float in | ||
1116 | ** proper range to fit in register sC | ||
1117 | */ | ||
1118 | static int isSCnumber (expdesc *e, lua_Integer *i) { | ||
1119 | if (e->k == VKINT) | ||
1120 | *i = e->u.ival; | ||
1121 | else if (!(e->k == VKFLT && floatI(e->u.nval, i))) | ||
1122 | return 0; /* not a number */ | ||
1123 | *i += MAXARG_sC; | ||
1124 | return (!hasjumps(e) && l_castS2U(*i) <= l_castS2U(MAXARG_C)); | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | /* | ||
1110 | ** Create expression 't[k]'. 't' must have its final result already in a | 1129 | ** Create expression 't[k]'. 't' must have its final result already in a |
1111 | ** register or upvalue. Upvalues can only be indexed by literal strings. | 1130 | ** register or upvalue. Upvalues can only be indexed by literal strings. |
1112 | ** Keys can be literal strings in the constant table or arbitrary | 1131 | ** Keys can be literal strings in the constant table or arbitrary |
@@ -1235,6 +1254,11 @@ static void codearith (FuncState *fs, OpCode op, | |||
1235 | } | 1254 | } |
1236 | 1255 | ||
1237 | 1256 | ||
1257 | static void swapexps (expdesc *e1, expdesc *e2) { | ||
1258 | expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ | ||
1259 | } | ||
1260 | |||
1261 | |||
1238 | /* | 1262 | /* |
1239 | ** Code commutative operators ('+', '*'). If first operand is a | 1263 | ** Code commutative operators ('+', '*'). If first operand is a |
1240 | ** constant, change order of operands to use immediate operator. | 1264 | ** constant, change order of operands to use immediate operator. |
@@ -1243,7 +1267,7 @@ static void codecommutative (FuncState *fs, OpCode op, | |||
1243 | expdesc *e1, expdesc *e2, int line) { | 1267 | expdesc *e1, expdesc *e2, int line) { |
1244 | int flip = 0; | 1268 | int flip = 0; |
1245 | if (isSCint(e1)) { | 1269 | if (isSCint(e1)) { |
1246 | expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ | 1270 | swapexps(e1, e2); |
1247 | flip = 1; | 1271 | flip = 1; |
1248 | } | 1272 | } |
1249 | codearith(fs, op, e1, e2, flip, line); | 1273 | codearith(fs, op, e1, e2, flip, line); |
@@ -1259,10 +1283,6 @@ static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | |||
1259 | int rk2 = luaK_exp2anyreg(fs, e2); | 1283 | int rk2 = luaK_exp2anyreg(fs, e2); |
1260 | freeexps(fs, e1, e2); | 1284 | freeexps(fs, e1, e2); |
1261 | switch (opr) { | 1285 | switch (opr) { |
1262 | case OPR_NE: { /* '(a ~= b)' ==> 'not (a == b)' */ | ||
1263 | e1->u.info = condjump(fs, OP_EQ, 0, rk1, rk2); | ||
1264 | break; | ||
1265 | } | ||
1266 | case OPR_GT: case OPR_GE: { | 1286 | case OPR_GT: case OPR_GE: { |
1267 | /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ | 1287 | /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ |
1268 | OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); | 1288 | OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); |
@@ -1284,21 +1304,28 @@ static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | |||
1284 | ** 'e1' was already put as RK by 'luaK_infix'. | 1304 | ** 'e1' was already put as RK by 'luaK_infix'. |
1285 | */ | 1305 | */ |
1286 | static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | 1306 | static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { |
1287 | int r1, rk2; | 1307 | int r1, r2; |
1288 | OpCode op = OP_EQK; /* will try first to use a constant */ | 1308 | lua_Integer im; |
1289 | if (e1->k == VK) { /* 1st expression is constant? */ | 1309 | OpCode op; |
1290 | rk2 = e1->u.info; /* constant index */ | 1310 | if (e1->k != VNONRELOC) { |
1291 | r1 = luaK_exp2anyreg(fs, e2); /* 2nd expression must be in register */ | 1311 | lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT); |
1312 | swapexps(e1, e2); | ||
1313 | } | ||
1314 | r1 = luaK_exp2anyreg(fs, e1); /* 1nd expression must be in register */ | ||
1315 | if (isSCnumber(e2, &im)) { | ||
1316 | op = OP_EQI; | ||
1317 | r2 = cast_int(im); /* immediate operand */ | ||
1318 | } | ||
1319 | else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */ | ||
1320 | op = OP_EQK; | ||
1321 | r2 = e2->u.info; /* constant index */ | ||
1292 | } | 1322 | } |
1293 | else { | 1323 | else { |
1294 | lua_assert(e1->k == VNONRELOC); /* 1st expression is in a register */ | 1324 | op = OP_EQ; /* will compare two registers */ |
1295 | r1 = e1->u.info; | 1325 | r2 = luaK_exp2anyreg(fs, e2); |
1296 | if (!luaK_exp2RK(fs, e2)) /* 2nd expression is not constant? */ | ||
1297 | op = OP_EQ; /* will compare two registers */ | ||
1298 | rk2 = e2->u.info; /* constant/register index */ | ||
1299 | } | 1326 | } |
1300 | freeexps(fs, e1, e2); | 1327 | freeexps(fs, e1, e2); |
1301 | e1->u.info = condjump(fs, op, (opr == OPR_EQ), r1, rk2); | 1328 | e1->u.info = condjump(fs, op, (opr == OPR_EQ), r1, r2); |
1302 | e1->k = VJMP; | 1329 | e1->k = VJMP; |
1303 | } | 1330 | } |
1304 | 1331 | ||
@@ -1351,7 +1378,9 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
1351 | break; | 1378 | break; |
1352 | } | 1379 | } |
1353 | case OPR_EQ: case OPR_NE: { | 1380 | case OPR_EQ: case OPR_NE: { |
1354 | luaK_exp2RK(fs, v); | 1381 | if (!tonumeral(v, NULL)) |
1382 | luaK_exp2RK(fs, v); | ||
1383 | /* else keep numeral, which may be an immediate operand */ | ||
1355 | break; | 1384 | break; |
1356 | } | 1385 | } |
1357 | case OPR_LT: case OPR_LE: | 1386 | case OPR_LT: case OPR_LE: |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.67 2017/11/07 17:20:42 roberto Exp roberto $ | 2 | ** $Id: lopcodes.c,v 1.68 2017/11/16 12:59:14 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -67,6 +67,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { | |||
67 | "LT", | 67 | "LT", |
68 | "LE", | 68 | "LE", |
69 | "EQK", | 69 | "EQK", |
70 | "EQI", | ||
70 | "TEST", | 71 | "TEST", |
71 | "TESTSET", | 72 | "TESTSET", |
72 | "CALL", | 73 | "CALL", |
@@ -135,6 +136,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
135 | ,opmode(1, 0, iABC) /* OP_LT */ | 136 | ,opmode(1, 0, iABC) /* OP_LT */ |
136 | ,opmode(1, 0, iABC) /* OP_LE */ | 137 | ,opmode(1, 0, iABC) /* OP_LE */ |
137 | ,opmode(1, 0, iABC) /* OP_EQK */ | 138 | ,opmode(1, 0, iABC) /* OP_EQK */ |
139 | ,opmode(1, 0, iABC) /* OP_EQI */ | ||
138 | ,opmode(1, 0, iABC) /* OP_TEST */ | 140 | ,opmode(1, 0, iABC) /* OP_TEST */ |
139 | ,opmode(1, 1, iABC) /* OP_TESTSET */ | 141 | ,opmode(1, 1, iABC) /* OP_TESTSET */ |
140 | ,opmode(0, 1, iABC) /* OP_CALL */ | 142 | ,opmode(0, 1, iABC) /* OP_CALL */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.167 2017/11/07 17:20:42 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.168 2017/11/16 12:59:14 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -241,6 +241,7 @@ OP_LT,/* A B C if ((R(B) < R(C)) ~= A) then pc++ */ | |||
241 | OP_LE,/* A B C if ((R(B) <= R(C)) ~= A) then pc++ */ | 241 | OP_LE,/* A B C if ((R(B) <= R(C)) ~= A) then pc++ */ |
242 | 242 | ||
243 | OP_EQK,/* A B C if ((R(B) == K(C)) ~= A) then pc++ */ | 243 | OP_EQK,/* A B C if ((R(B) == K(C)) ~= A) then pc++ */ |
244 | OP_EQI,/* A B C if ((R(B) == C) ~= A) then pc++ */ | ||
244 | 245 | ||
245 | OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ | 246 | OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ |
246 | OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ | 247 | OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.312 2017/11/20 12:57:39 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.313 2017/11/21 14:17:35 roberto Exp $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -1392,6 +1392,17 @@ void luaV_execute (lua_State *L) { | |||
1392 | donextjump(ci); | 1392 | donextjump(ci); |
1393 | vmbreak; | 1393 | vmbreak; |
1394 | } | 1394 | } |
1395 | vmcase(OP_EQI) { | ||
1396 | TValue *rb = vRB(i); | ||
1397 | int ic = GETARG_sC(i); | ||
1398 | if ((ttisinteger(rb) ? (ivalue(rb) == ic) | ||
1399 | :ttisfloat(rb) ? luai_numeq(fltvalue(rb), cast_num(ic)) | ||
1400 | : 0) != GETARG_A(i)) | ||
1401 | pc++; | ||
1402 | else | ||
1403 | donextjump(ci); | ||
1404 | vmbreak; | ||
1405 | } | ||
1395 | vmcase(OP_TEST) { | 1406 | vmcase(OP_TEST) { |
1396 | if (GETARG_C(i) ? l_isfalse(s2v(ra)) : !l_isfalse(s2v(ra))) | 1407 | if (GETARG_C(i) ? l_isfalse(s2v(ra)) : !l_isfalse(s2v(ra))) |
1397 | pc++; | 1408 | pc++; |