diff options
-rw-r--r-- | lcode.c | 126 | ||||
-rw-r--r-- | ldebug.c | 10 | ||||
-rw-r--r-- | ljumptab.h | 7 | ||||
-rw-r--r-- | lopcodes.c | 7 | ||||
-rw-r--r-- | lopcodes.h | 10 | ||||
-rw-r--r-- | lopnames.h | 7 | ||||
-rw-r--r-- | ltests.h | 1 | ||||
-rw-r--r-- | lvm.c | 61 | ||||
-rw-r--r-- | testes/code.lua | 82 | ||||
-rw-r--r-- | testes/db.lua | 2 | ||||
-rw-r--r-- | testes/events.lua | 2 |
11 files changed, 228 insertions, 87 deletions
@@ -371,10 +371,6 @@ int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) { | |||
371 | } | 371 | } |
372 | 372 | ||
373 | 373 | ||
374 | #define codeABsC(fs,o,a,b,c,k) luaK_codeABCk(fs,o,a,b,((c) + OFFSET_sC),k) | ||
375 | |||
376 | |||
377 | |||
378 | /* | 374 | /* |
379 | ** Format and emit an 'iABx' instruction. | 375 | ** Format and emit an 'iABx' instruction. |
380 | */ | 376 | */ |
@@ -885,30 +881,45 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { | |||
885 | 881 | ||
886 | 882 | ||
887 | /* | 883 | /* |
884 | ** Try to make 'e' a K expression with an index in the range of R/K | ||
885 | ** indices. Return true iff succeeded. | ||
886 | */ | ||
887 | static int luaK_exp2K (FuncState *fs, expdesc *e) { | ||
888 | if (!hasjumps(e)) { | ||
889 | int info; | ||
890 | switch (e->k) { /* move constants to 'k' */ | ||
891 | case VTRUE: info = boolK(fs, 1); break; | ||
892 | case VFALSE: info = boolK(fs, 0); break; | ||
893 | case VNIL: info = nilK(fs); break; | ||
894 | case VKINT: info = luaK_intK(fs, e->u.ival); break; | ||
895 | case VKFLT: info = luaK_numberK(fs, e->u.nval); break; | ||
896 | case VK: info = e->u.info; break; | ||
897 | default: return 0; /* not a constant */ | ||
898 | } | ||
899 | if (info <= MAXINDEXRK) { /* does constant fit in 'argC'? */ | ||
900 | e->k = VK; /* make expression a 'K' expression */ | ||
901 | e->u.info = info; | ||
902 | return 1; | ||
903 | } | ||
904 | } | ||
905 | /* else, expression doesn't fit; leave it unchanged */ | ||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | |||
910 | /* | ||
888 | ** Ensures final expression result is in a valid R/K index | 911 | ** Ensures final expression result is in a valid R/K index |
889 | ** (that is, it is either in a register or in 'k' with an index | 912 | ** (that is, it is either in a register or in 'k' with an index |
890 | ** in the range of R/K indices). | 913 | ** in the range of R/K indices). |
891 | ** Returns 1 if expression is K, 0 otherwise. | 914 | ** Returns 1 iff expression is K. |
892 | */ | 915 | */ |
893 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | 916 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
894 | luaK_exp2val(fs, e); | 917 | if (luaK_exp2K(fs, e)) |
895 | switch (e->k) { /* move constants to 'k' */ | 918 | return 1; |
896 | case VTRUE: e->u.info = boolK(fs, 1); goto vk; | 919 | else { /* not a constant in the right range: put it in a register */ |
897 | case VFALSE: e->u.info = boolK(fs, 0); goto vk; | 920 | luaK_exp2anyreg(fs, e); |
898 | case VNIL: e->u.info = nilK(fs); goto vk; | 921 | return 0; |
899 | case VKINT: e->u.info = luaK_intK(fs, e->u.ival); goto vk; | ||
900 | case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); goto vk; | ||
901 | case VK: | ||
902 | vk: | ||
903 | e->k = VK; | ||
904 | if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ | ||
905 | return 1; | ||
906 | else break; | ||
907 | default: break; | ||
908 | } | 922 | } |
909 | /* not a constant in the right range: put it in a register */ | ||
910 | luaK_exp2anyreg(fs, e); | ||
911 | return 0; | ||
912 | } | 923 | } |
913 | 924 | ||
914 | 925 | ||
@@ -1232,8 +1243,19 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { | |||
1232 | } | 1243 | } |
1233 | 1244 | ||
1234 | 1245 | ||
1246 | /* | ||
1247 | ** Emit code for binary expressions that "produce values" | ||
1248 | ** (everything but logical operators 'and'/'or' and comparison | ||
1249 | ** operators). | ||
1250 | ** Expression to produce final result will be encoded in 'e1'. | ||
1251 | ** Because 'luaK_exp2anyreg' can free registers, its calls must be | ||
1252 | ** in "stack order" (that is, first on 'e2', which may have more | ||
1253 | ** recent registers to be released). | ||
1254 | */ | ||
1235 | static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, | 1255 | static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, |
1236 | int pc, int line) { | 1256 | OpCode op, int v2, int k, int line) { |
1257 | int v1 = luaK_exp2anyreg(fs, e1); | ||
1258 | int pc = luaK_codeABCk(fs, op, 0, v1, v2, k); | ||
1237 | freeexps(fs, e1, e2); | 1259 | freeexps(fs, e1, e2); |
1238 | e1->u.info = pc; | 1260 | e1->u.info = pc; |
1239 | e1->k = VRELOC; /* all those operations are relocatable */ | 1261 | e1->k = VRELOC; /* all those operations are relocatable */ |
@@ -1242,20 +1264,13 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, | |||
1242 | 1264 | ||
1243 | 1265 | ||
1244 | /* | 1266 | /* |
1245 | ** Emit code for binary expressions that "produce values" | 1267 | ** Emit code for binary expressions that "produce values" over |
1246 | ** (everything but logical operators 'and'/'or' and comparison | 1268 | ** two registers. |
1247 | ** operators). | ||
1248 | ** Expression to produce final result will be encoded in 'e1'. | ||
1249 | ** Because 'luaK_exp2anyreg' can free registers, its calls must be | ||
1250 | ** in "stack order" (that is, first on 'e2', which may have more | ||
1251 | ** recent registers to be released). | ||
1252 | */ | 1269 | */ |
1253 | static void codebinexpval (FuncState *fs, OpCode op, | 1270 | static void codebinexpval (FuncState *fs, OpCode op, |
1254 | expdesc *e1, expdesc *e2, int line) { | 1271 | expdesc *e1, expdesc *e2, int line) { |
1255 | int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ | 1272 | int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ |
1256 | int v1 = luaK_exp2anyreg(fs, e1); | 1273 | finishbinexpval(fs, e1, e2, op, v2, 0, line); |
1257 | int pc = luaK_codeABC(fs, op, 0, v1, v2); /* generate opcode */ | ||
1258 | finishbinexpval(fs, e1, e2, pc, line); | ||
1259 | } | 1274 | } |
1260 | 1275 | ||
1261 | 1276 | ||
@@ -1264,41 +1279,48 @@ static void codebinexpval (FuncState *fs, OpCode op, | |||
1264 | */ | 1279 | */ |
1265 | static void codebini (FuncState *fs, OpCode op, | 1280 | static void codebini (FuncState *fs, OpCode op, |
1266 | expdesc *e1, expdesc *e2, int k, int line) { | 1281 | expdesc *e1, expdesc *e2, int k, int line) { |
1267 | int v2 = cast_int(e2->u.ival); /* immediate operand */ | 1282 | int v2 = cast_int(e2->u.ival) + OFFSET_sC; /* immediate operand */ |
1268 | int v1 = luaK_exp2anyreg(fs, e1); | 1283 | finishbinexpval(fs, e1, e2, op, v2, k, line); |
1269 | int pc = codeABsC(fs, op, 0, v1, v2, k); /* generate opcode */ | 1284 | } |
1270 | finishbinexpval(fs, e1, e2, pc, line); | 1285 | |
1286 | |||
1287 | static void swapexps (expdesc *e1, expdesc *e2) { | ||
1288 | expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ | ||
1271 | } | 1289 | } |
1272 | 1290 | ||
1273 | 1291 | ||
1274 | /* | 1292 | /* |
1275 | ** Code arithmetic operators ('+', '-', ...). If second operand is a | 1293 | ** Code arithmetic operators ('+', '-', ...). If second operand is a |
1276 | ** constant in the proper range, use variant opcodes with immediate | 1294 | ** constant in the proper range, use variant opcodes with immediate |
1277 | ** operands. | 1295 | ** operands or K operands. |
1278 | */ | 1296 | */ |
1279 | static void codearith (FuncState *fs, OpCode op, | 1297 | static void codearith (FuncState *fs, OpCode op, |
1280 | expdesc *e1, expdesc *e2, int flip, int line) { | 1298 | expdesc *e1, expdesc *e2, int flip, int line) { |
1281 | if (!isSCint(e2)) | 1299 | if (isSCint(e2)) /* immediate operand? */ |
1282 | codebinexpval(fs, op, e1, e2, line); /* use standard operators */ | ||
1283 | else /* use immediate operators */ | ||
1284 | codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line); | 1300 | codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line); |
1285 | } | 1301 | else if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ |
1286 | 1302 | int v2 = e2->u.info; /* K index */ | |
1287 | 1303 | op = cast(OpCode, op - OP_ADD + OP_ADDK); | |
1288 | static void swapexps (expdesc *e1, expdesc *e2) { | 1304 | finishbinexpval(fs, e1, e2, op, v2, flip, line); |
1289 | expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ | 1305 | } |
1306 | else { /* 'e2' is neither an immediate nor a K operand */ | ||
1307 | if (flip) | ||
1308 | swapexps(e1, e2); /* back to original order */ | ||
1309 | codebinexpval(fs, op, e1, e2, line); /* use standard operators */ | ||
1310 | } | ||
1290 | } | 1311 | } |
1291 | 1312 | ||
1292 | 1313 | ||
1293 | /* | 1314 | /* |
1294 | ** Code commutative operators ('+', '*'). If first operand is a | 1315 | ** Code commutative operators ('+', '*'). If first operand is a |
1295 | ** constant, change order of operands to use immediate operator. | 1316 | ** numeric constant, change order of operands to try to use an |
1317 | ** immediate or K operator. | ||
1296 | */ | 1318 | */ |
1297 | static void codecommutative (FuncState *fs, OpCode op, | 1319 | static void codecommutative (FuncState *fs, OpCode op, |
1298 | expdesc *e1, expdesc *e2, int line) { | 1320 | expdesc *e1, expdesc *e2, int line) { |
1299 | int flip = 0; | 1321 | int flip = 0; |
1300 | if (isSCint(e1)) { | 1322 | if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ |
1301 | swapexps(e1, e2); | 1323 | swapexps(e1, e2); /* change order */ |
1302 | flip = 1; | 1324 | flip = 1; |
1303 | } | 1325 | } |
1304 | codearith(fs, op, e1, e2, flip, line); | 1326 | codearith(fs, op, e1, e2, flip, line); |
@@ -1312,7 +1334,7 @@ static void codecommutative (FuncState *fs, OpCode op, | |||
1312 | static void codebitwise (FuncState *fs, BinOpr opr, | 1334 | static void codebitwise (FuncState *fs, BinOpr opr, |
1313 | expdesc *e1, expdesc *e2, int line) { | 1335 | expdesc *e1, expdesc *e2, int line) { |
1314 | int inv = 0; | 1336 | int inv = 0; |
1315 | int v1, v2, pc; | 1337 | int v2; |
1316 | OpCode op; | 1338 | OpCode op; |
1317 | if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { | 1339 | if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { |
1318 | swapexps(e1, e2); /* 'e2' will be the constant operand */ | 1340 | swapexps(e1, e2); /* 'e2' will be the constant operand */ |
@@ -1323,12 +1345,10 @@ static void codebitwise (FuncState *fs, BinOpr opr, | |||
1323 | codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ | 1345 | codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ |
1324 | return; | 1346 | return; |
1325 | } | 1347 | } |
1326 | v1 = luaK_exp2anyreg(fs, e1); | ||
1327 | v2 = e2->u.info; /* index in K array */ | 1348 | v2 = e2->u.info; /* index in K array */ |
1328 | op = cast(OpCode, opr - OPR_BAND + OP_BANDK); | 1349 | op = cast(OpCode, opr - OPR_BAND + OP_BANDK); |
1329 | lua_assert(ttisinteger(&fs->f->k[v2])); | 1350 | lua_assert(ttisinteger(&fs->f->k[v2])); |
1330 | pc = luaK_codeABCk(fs, op, 0, v1, v2, inv); | 1351 | finishbinexpval(fs, e1, e2, op, v2, inv, line); |
1331 | finishbinexpval(fs, e1, e2, pc, line); | ||
1332 | } | 1352 | } |
1333 | 1353 | ||
1334 | 1354 | ||
@@ -610,12 +610,18 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | |||
610 | tm = TM_NEWINDEX; | 610 | tm = TM_NEWINDEX; |
611 | break; | 611 | break; |
612 | case OP_ADDI: case OP_SUBI: case OP_MULI: case OP_MODI: | 612 | case OP_ADDI: case OP_SUBI: case OP_MULI: case OP_MODI: |
613 | case OP_POWI: case OP_DIVI: case OP_IDIVI: | 613 | case OP_POWI: case OP_DIVI: case OP_IDIVI: { |
614 | case OP_BANDK: case OP_BORK: case OP_BXORK: { | ||
615 | int offset = GET_OPCODE(i) - OP_ADDI; /* ORDER OP */ | 614 | int offset = GET_OPCODE(i) - OP_ADDI; /* ORDER OP */ |
616 | tm = cast(TMS, offset + TM_ADD); /* ORDER TM */ | 615 | tm = cast(TMS, offset + TM_ADD); /* ORDER TM */ |
617 | break; | 616 | break; |
618 | } | 617 | } |
618 | case OP_ADDK: case OP_SUBK: case OP_MULK: case OP_MODK: | ||
619 | case OP_POWK: case OP_DIVK: case OP_IDIVK: | ||
620 | case OP_BANDK: case OP_BORK: case OP_BXORK: { | ||
621 | int offset = GET_OPCODE(i) - OP_ADDK; /* ORDER OP */ | ||
622 | tm = cast(TMS, offset + TM_ADD); /* ORDER TM */ | ||
623 | break; | ||
624 | } | ||
619 | case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD: | 625 | case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD: |
620 | case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: | 626 | case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: |
621 | case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: { | 627 | case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: { |
@@ -51,6 +51,13 @@ static void *disptab[] = { | |||
51 | &&L_OP_POWI, | 51 | &&L_OP_POWI, |
52 | &&L_OP_DIVI, | 52 | &&L_OP_DIVI, |
53 | &&L_OP_IDIVI, | 53 | &&L_OP_IDIVI, |
54 | &&L_OP_ADDK, | ||
55 | &&L_OP_SUBK, | ||
56 | &&L_OP_MULK, | ||
57 | &&L_OP_MODK, | ||
58 | &&L_OP_POWK, | ||
59 | &&L_OP_DIVK, | ||
60 | &&L_OP_IDIVK, | ||
54 | &&L_OP_BANDK, | 61 | &&L_OP_BANDK, |
55 | &&L_OP_BORK, | 62 | &&L_OP_BORK, |
56 | &&L_OP_BXORK, | 63 | &&L_OP_BXORK, |
@@ -45,6 +45,13 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
45 | ,opmode(0, 0, 0, 1, iABC) /* OP_POWI */ | 45 | ,opmode(0, 0, 0, 1, iABC) /* OP_POWI */ |
46 | ,opmode(0, 0, 0, 1, iABC) /* OP_DIVI */ | 46 | ,opmode(0, 0, 0, 1, iABC) /* OP_DIVI */ |
47 | ,opmode(0, 0, 0, 1, iABC) /* OP_IDIVI */ | 47 | ,opmode(0, 0, 0, 1, iABC) /* OP_IDIVI */ |
48 | ,opmode(0, 0, 0, 1, iABC) /* OP_ADDK */ | ||
49 | ,opmode(0, 0, 0, 1, iABC) /* OP_SUBK */ | ||
50 | ,opmode(0, 0, 0, 1, iABC) /* OP_MULK */ | ||
51 | ,opmode(0, 0, 0, 1, iABC) /* OP_MODK */ | ||
52 | ,opmode(0, 0, 0, 1, iABC) /* OP_POWK */ | ||
53 | ,opmode(0, 0, 0, 1, iABC) /* OP_DIVK */ | ||
54 | ,opmode(0, 0, 0, 1, iABC) /* OP_IDIVK */ | ||
48 | ,opmode(0, 0, 0, 1, iABC) /* OP_BANDK */ | 55 | ,opmode(0, 0, 0, 1, iABC) /* OP_BANDK */ |
49 | ,opmode(0, 0, 0, 1, iABC) /* OP_BORK */ | 56 | ,opmode(0, 0, 0, 1, iABC) /* OP_BORK */ |
50 | ,opmode(0, 0, 0, 1, iABC) /* OP_BXORK */ | 57 | ,opmode(0, 0, 0, 1, iABC) /* OP_BXORK */ |
@@ -221,6 +221,14 @@ OP_POWI,/* A B sC R(A) := R(B) ^ C */ | |||
221 | OP_DIVI,/* A B sC R(A) := R(B) / C */ | 221 | OP_DIVI,/* A B sC R(A) := R(B) / C */ |
222 | OP_IDIVI,/* A B sC R(A) := R(B) // C */ | 222 | OP_IDIVI,/* A B sC R(A) := R(B) // C */ |
223 | 223 | ||
224 | OP_ADDK,/* A B C R(A) := R(B) + K(C) */ | ||
225 | OP_SUBK,/* A B C R(A) := R(B) - K(C) */ | ||
226 | OP_MULK,/* A B C R(A) := R(B) * K(C) */ | ||
227 | OP_MODK,/* A B C R(A) := R(B) % K(C) */ | ||
228 | OP_POWK,/* A B C R(A) := R(B) ^ K(C) */ | ||
229 | OP_DIVK,/* A B C R(A) := R(B) / K(C) */ | ||
230 | OP_IDIVK,/* A B C R(A) := R(B) // K(C) */ | ||
231 | |||
224 | OP_BANDK,/* A B C R(A) := R(B) & K(C):integer */ | 232 | OP_BANDK,/* A B C R(A) := R(B) & K(C):integer */ |
225 | OP_BORK,/* A B C R(A) := R(B) | K(C):integer */ | 233 | OP_BORK,/* A B C R(A) := R(B) | K(C):integer */ |
226 | OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */ | 234 | OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */ |
@@ -235,11 +243,13 @@ OP_MOD,/* A B C R(A) := R(B) % R(C) */ | |||
235 | OP_POW,/* A B C R(A) := R(B) ^ R(C) */ | 243 | OP_POW,/* A B C R(A) := R(B) ^ R(C) */ |
236 | OP_DIV,/* A B C R(A) := R(B) / R(C) */ | 244 | OP_DIV,/* A B C R(A) := R(B) / R(C) */ |
237 | OP_IDIV,/* A B C R(A) := R(B) // R(C) */ | 245 | OP_IDIV,/* A B C R(A) := R(B) // R(C) */ |
246 | |||
238 | OP_BAND,/* A B C R(A) := R(B) & R(C) */ | 247 | OP_BAND,/* A B C R(A) := R(B) & R(C) */ |
239 | OP_BOR,/* A B C R(A) := R(B) | R(C) */ | 248 | OP_BOR,/* A B C R(A) := R(B) | R(C) */ |
240 | OP_BXOR,/* A B C R(A) := R(B) ~ R(C) */ | 249 | OP_BXOR,/* A B C R(A) := R(B) ~ R(C) */ |
241 | OP_SHL,/* A B C R(A) := R(B) << R(C) */ | 250 | OP_SHL,/* A B C R(A) := R(B) << R(C) */ |
242 | OP_SHR,/* A B C R(A) := R(B) >> R(C) */ | 251 | OP_SHR,/* A B C R(A) := R(B) >> R(C) */ |
252 | |||
243 | OP_UNM,/* A B R(A) := -R(B) */ | 253 | OP_UNM,/* A B R(A) := -R(B) */ |
244 | OP_BNOT,/* A B R(A) := ~R(B) */ | 254 | OP_BNOT,/* A B R(A) := ~R(B) */ |
245 | OP_NOT,/* A B R(A) := not R(B) */ | 255 | OP_NOT,/* A B R(A) := not R(B) */ |
@@ -36,6 +36,13 @@ static const char *const opnames[] = { | |||
36 | "POWI", | 36 | "POWI", |
37 | "DIVI", | 37 | "DIVI", |
38 | "IDIVI", | 38 | "IDIVI", |
39 | "ADDK", | ||
40 | "SUBK", | ||
41 | "MULK", | ||
42 | "MODK", | ||
43 | "POWK", | ||
44 | "DIVK", | ||
45 | "IDIVK", | ||
39 | "BANDK", | 46 | "BANDK", |
40 | "BORK", | 47 | "BORK", |
41 | "BXORK", | 48 | "BXORK", |
@@ -119,7 +119,6 @@ LUA_API void *debug_realloc (void *ud, void *block, | |||
119 | #undef LUAL_BUFFERSIZE | 119 | #undef LUAL_BUFFERSIZE |
120 | #define LUAL_BUFFERSIZE 23 | 120 | #define LUAL_BUFFERSIZE 23 |
121 | #define MINSTRTABSIZE 2 | 121 | #define MINSTRTABSIZE 2 |
122 | #define MAXINDEXRK 1 | ||
123 | #define MAXIWTHABS 3 | 122 | #define MAXIWTHABS 3 |
124 | 123 | ||
125 | 124 | ||
@@ -856,6 +856,39 @@ void luaV_finishOp (lua_State *L) { | |||
856 | 856 | ||
857 | 857 | ||
858 | /* | 858 | /* |
859 | ** Arithmetic operations with K operands. | ||
860 | */ | ||
861 | #define op_arithK(L,iop,fop,tm,flip) { \ | ||
862 | TValue *v1 = vRB(i); \ | ||
863 | TValue *v2 = KC(i); \ | ||
864 | if (ttisinteger(v1) && ttisinteger(v2)) { \ | ||
865 | lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \ | ||
866 | setivalue(s2v(ra), iop(L, i1, i2)); \ | ||
867 | } \ | ||
868 | else { \ | ||
869 | lua_Number n1; lua_Number n2; \ | ||
870 | if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \ | ||
871 | setfltvalue(s2v(ra), fop(L, n1, n2)); \ | ||
872 | } \ | ||
873 | else \ | ||
874 | Protect(luaT_trybinassocTM(L, v1, v2, ra, flip, tm)); } } | ||
875 | |||
876 | |||
877 | /* | ||
878 | ** Arithmetic operations with K operands for floats. | ||
879 | */ | ||
880 | #define op_arithfK(L,fop,tm) { \ | ||
881 | TValue *v1 = vRB(i); \ | ||
882 | TValue *v2 = KC(i); \ | ||
883 | lua_Number n1; lua_Number n2; \ | ||
884 | if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \ | ||
885 | setfltvalue(s2v(ra), fop(L, n1, n2)); \ | ||
886 | } \ | ||
887 | else \ | ||
888 | Protect(luaT_trybinTM(L, v1, v2, ra, tm)); } | ||
889 | |||
890 | |||
891 | /* | ||
859 | ** Bitwise operations with constant operand. | 892 | ** Bitwise operations with constant operand. |
860 | */ | 893 | */ |
861 | #define op_bitwiseK(L,op,tm) { \ | 894 | #define op_bitwiseK(L,op,tm) { \ |
@@ -1219,6 +1252,34 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1219 | op_arithI(L, luaV_idiv, luai_numidiv, TM_IDIV, 0); | 1252 | op_arithI(L, luaV_idiv, luai_numidiv, TM_IDIV, 0); |
1220 | vmbreak; | 1253 | vmbreak; |
1221 | } | 1254 | } |
1255 | vmcase(OP_ADDK) { | ||
1256 | op_arithK(L, l_addi, luai_numadd, TM_ADD, GETARG_k(i)); | ||
1257 | vmbreak; | ||
1258 | } | ||
1259 | vmcase(OP_SUBK) { | ||
1260 | op_arithK(L, l_subi, luai_numsub, TM_SUB, 0); | ||
1261 | vmbreak; | ||
1262 | } | ||
1263 | vmcase(OP_MULK) { | ||
1264 | op_arithK(L, l_muli, luai_nummul, TM_MUL, GETARG_k(i)); | ||
1265 | vmbreak; | ||
1266 | } | ||
1267 | vmcase(OP_MODK) { | ||
1268 | op_arithK(L, luaV_mod, luaV_modf, TM_MOD, 0); | ||
1269 | vmbreak; | ||
1270 | } | ||
1271 | vmcase(OP_POWK) { | ||
1272 | op_arithfK(L, luai_numpow, TM_POW); | ||
1273 | vmbreak; | ||
1274 | } | ||
1275 | vmcase(OP_DIVK) { | ||
1276 | op_arithfK(L, luai_numdiv, TM_DIV); | ||
1277 | vmbreak; | ||
1278 | } | ||
1279 | vmcase(OP_IDIVK) { | ||
1280 | op_arithK(L, luaV_idiv, luai_numidiv, TM_IDIV, 0); | ||
1281 | vmbreak; | ||
1282 | } | ||
1222 | vmcase(OP_ADD) { | 1283 | vmcase(OP_ADD) { |
1223 | op_arith(L, l_addi, luai_numadd, TM_ADD); | 1284 | op_arith(L, l_addi, luai_numadd, TM_ADD); |
1224 | vmbreak; | 1285 | vmbreak; |
diff --git a/testes/code.lua b/testes/code.lua index 4d44fa6a..834ff5e2 100644 --- a/testes/code.lua +++ b/testes/code.lua | |||
@@ -40,6 +40,7 @@ checkKlist(foo, {3.78/4, -3.78/4, -3.79/4}) | |||
40 | 40 | ||
41 | -- testing opcodes | 41 | -- testing opcodes |
42 | 42 | ||
43 | -- check that 'f' opcodes match '...' | ||
43 | function check (f, ...) | 44 | function check (f, ...) |
44 | local arg = {...} | 45 | local arg = {...} |
45 | local c = T.listcode(f) | 46 | local c = T.listcode(f) |
@@ -52,9 +53,19 @@ function check (f, ...) | |||
52 | end | 53 | end |
53 | 54 | ||
54 | 55 | ||
56 | -- check that 'f' opcodes match '...' and that 'f(p) == r'. | ||
57 | function checkR (f, p, r, ...) | ||
58 | local r1 = f(p) | ||
59 | assert(r == r1 and math.type(r) == math.type(r1)) | ||
60 | check(f, ...) | ||
61 | end | ||
62 | |||
63 | |||
64 | -- check that 'a' and 'b' has the same opcodes | ||
55 | function checkequal (a, b) | 65 | function checkequal (a, b) |
56 | a = T.listcode(a) | 66 | a = T.listcode(a) |
57 | b = T.listcode(b) | 67 | b = T.listcode(b) |
68 | assert(#a == #b) | ||
58 | for i = 1, #a do | 69 | for i = 1, #a do |
59 | a[i] = string.gsub(a[i], '%b()', '') -- remove line number | 70 | a[i] = string.gsub(a[i], '%b()', '') -- remove line number |
60 | b[i] = string.gsub(b[i], '%b()', '') -- remove line number | 71 | b[i] = string.gsub(b[i], '%b()', '') -- remove line number |
@@ -165,65 +176,64 @@ end, | |||
165 | 176 | ||
166 | 177 | ||
167 | -- equalities | 178 | -- equalities |
168 | check(function (a) if a == 1 then return 2 end end, | 179 | checkR(function (a) if a == 1 then return 2 end end, 1, 2, |
169 | 'EQI', 'JMP', 'LOADI', 'RETURN1') | 180 | 'EQI', 'JMP', 'LOADI', 'RETURN1') |
170 | 181 | ||
171 | check(function (a) if -4.0 == a then return 2 end end, | 182 | checkR(function (a) if -4.0 == a then return 2 end end, -4, 2, |
172 | 'EQI', 'JMP', 'LOADI', 'RETURN1') | 183 | 'EQI', 'JMP', 'LOADI', 'RETURN1') |
173 | 184 | ||
174 | check(function (a) if a == "hi" then return 2 end end, | 185 | checkR(function (a) if a == "hi" then return 2 end end, 10, nil, |
175 | 'EQK', 'JMP', 'LOADI', 'RETURN1') | 186 | 'EQK', 'JMP', 'LOADI', 'RETURN1') |
176 | 187 | ||
177 | check(function (a) if a == 10000 then return 2 end end, | 188 | checkR(function (a) if a == 10000 then return 2 end end, 1, nil, |
178 | 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large | 189 | 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large |
179 | 190 | ||
180 | check(function (a) if -10000 == a then return 2 end end, | 191 | checkR(function (a) if -10000 == a then return 2 end end, -10000, 2, |
181 | 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large | 192 | 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large |
182 | 193 | ||
183 | -- comparisons | 194 | -- comparisons |
184 | 195 | ||
185 | check(function (a) if -10 <= a then return 2 end end, | 196 | checkR(function (a) if -10 <= a then return 2 end end, -10, 2, |
186 | 'GEI', 'JMP', 'LOADI', 'RETURN1') | 197 | 'GEI', 'JMP', 'LOADI', 'RETURN1') |
187 | 198 | ||
188 | check(function (a) if 128.0 > a then return 2 end end, | 199 | checkR(function (a) if 128.0 > a then return 2 end end, 129, nil, |
189 | 'LTI', 'JMP', 'LOADI', 'RETURN1') | 200 | 'LTI', 'JMP', 'LOADI', 'RETURN1') |
190 | 201 | ||
191 | check(function (a) if -127.0 < a then return 2 end end, | 202 | checkR(function (a) if -127.0 < a then return 2 end end, -127, nil, |
192 | 'GTI', 'JMP', 'LOADI', 'RETURN1') | 203 | 'GTI', 'JMP', 'LOADI', 'RETURN1') |
193 | 204 | ||
194 | check(function (a) if 10 < a then return 2 end end, | 205 | checkR(function (a) if 10 < a then return 2 end end, 11, 2, |
195 | 'GTI', 'JMP', 'LOADI', 'RETURN1') | 206 | 'GTI', 'JMP', 'LOADI', 'RETURN1') |
196 | 207 | ||
197 | check(function (a) if 129 < a then return 2 end end, | 208 | checkR(function (a) if 129 < a then return 2 end end, 130, 2, |
198 | 'LOADI', 'LT', 'JMP', 'LOADI', 'RETURN1') | 209 | 'LOADI', 'LT', 'JMP', 'LOADI', 'RETURN1') |
199 | 210 | ||
200 | check(function (a) if a >= 23.0 then return 2 end end, | 211 | checkR(function (a) if a >= 23.0 then return 2 end end, 25, 2, |
201 | 'GEI', 'JMP', 'LOADI', 'RETURN1') | 212 | 'GEI', 'JMP', 'LOADI', 'RETURN1') |
202 | 213 | ||
203 | check(function (a) if a >= 23.1 then return 2 end end, | 214 | checkR(function (a) if a >= 23.1 then return 2 end end, 0, nil, |
204 | 'LOADK', 'LE', 'JMP', 'LOADI', 'RETURN1') | 215 | 'LOADK', 'LE', 'JMP', 'LOADI', 'RETURN1') |
205 | 216 | ||
206 | check(function (a) if a > 2300.0 then return 2 end end, | 217 | checkR(function (a) if a > 2300.0 then return 2 end end, 0, nil, |
207 | 'LOADF', 'LT', 'JMP', 'LOADI', 'RETURN1') | 218 | 'LOADF', 'LT', 'JMP', 'LOADI', 'RETURN1') |
208 | 219 | ||
209 | 220 | ||
210 | -- constant folding | 221 | -- constant folding |
211 | local function checkK (func, val) | 222 | local function checkK (func, val) |
212 | check(func, 'LOADK', 'RETURN1') | 223 | check(func, 'LOADK', 'RETURN1') |
213 | local k = T.listk(func) | 224 | checkKlist(func, {val}) |
214 | assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val)) | ||
215 | assert(func() == val) | 225 | assert(func() == val) |
216 | end | 226 | end |
217 | 227 | ||
218 | local function checkI (func, val) | 228 | local function checkI (func, val) |
219 | check(func, 'LOADI', 'RETURN1') | 229 | check(func, 'LOADI', 'RETURN1') |
220 | assert(#T.listk(func) == 0) | 230 | checkKlist(func, {}) |
221 | assert(func() == val) | 231 | assert(func() == val) |
222 | end | 232 | end |
223 | 233 | ||
224 | local function checkF (func, val) | 234 | local function checkF (func, val) |
225 | check(func, 'LOADF', 'RETURN1') | 235 | check(func, 'LOADF', 'RETURN1') |
226 | assert(#T.listk(func) == 0) | 236 | checkKlist(func, {}) |
227 | assert(func() == val) | 237 | assert(func() == val) |
228 | end | 238 | end |
229 | 239 | ||
@@ -258,20 +268,30 @@ checkK(function () return -65536.0 end, -(sbx + 1.0)) | |||
258 | 268 | ||
259 | 269 | ||
260 | -- immediate operands | 270 | -- immediate operands |
261 | check(function (x) return x + 1 end, 'ADDI', 'RETURN1') | 271 | checkR(function (x) return x + 1 end, 10, 11, 'ADDI', 'RETURN1') |
262 | check(function (x) return 128 + x end, 'ADDI', 'RETURN1') | 272 | checkR(function (x) return 128 + x end, 0.0, 128.0, 'ADDI', 'RETURN1') |
263 | check(function (x) return x * -127 end, 'MULI', 'RETURN1') | 273 | checkR(function (x) return x * -127 end, -1.0, 127.0, 'MULI', 'RETURN1') |
264 | check(function (x) return 20 * x end, 'MULI', 'RETURN1') | 274 | checkR(function (x) return 20 * x end, 2, 40, 'MULI', 'RETURN1') |
265 | check(function (x) return x ^ -2 end, 'POWI', 'RETURN1') | 275 | checkR(function (x) return x ^ -2 end, 2, 0.25, 'POWI', 'RETURN1') |
266 | check(function (x) return x / 40 end, 'DIVI', 'RETURN1') | 276 | checkR(function (x) return x / 40 end, 40, 1.0, 'DIVI', 'RETURN1') |
267 | check(function (x) return x // 1 end, 'IDIVI', 'RETURN1') | 277 | checkR(function (x) return x // 1 end, 10.0, 10.0, 'IDIVI', 'RETURN1') |
268 | check(function (x) return x % (100 - 10) end, 'MODI', 'RETURN1') | 278 | checkR(function (x) return x % (100 - 10) end, 91, 1, 'MODI', 'RETURN1') |
269 | check(function (x) return 1 << x end, 'SHLI', 'RETURN1') | 279 | checkR(function (x) return 1 << x end, 3, 8, 'SHLI', 'RETURN1') |
270 | check(function (x) return x << 2 end, 'SHRI', 'RETURN1') | 280 | checkR(function (x) return x << 2 end, 10, 40, 'SHRI', 'RETURN1') |
271 | check(function (x) return x >> 2 end, 'SHRI', 'RETURN1') | 281 | checkR(function (x) return x >> 2 end, 8, 2, 'SHRI', 'RETURN1') |
272 | check(function (x) return x & 1 end, 'BANDK', 'RETURN1') | 282 | checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'RETURN1') |
273 | check(function (x) return 10 | x end, 'BORK', 'RETURN1') | 283 | checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'RETURN1') |
274 | check(function (x) return -10 ~ x end, 'BXORK', 'RETURN1') | 284 | checkR(function (x) return -10 ~ x end, -1, 9, 'BXORK', 'RETURN1') |
285 | |||
286 | -- K operands in arithmetic operations | ||
287 | checkR(function (x) return x + 0.0 end, 1, 1.0, 'ADDK', 'RETURN1') | ||
288 | -- check(function (x) return 128 + x end, 'ADDK', 'RETURN1') | ||
289 | checkR(function (x) return x * -10000 end, 2, -20000, 'MULK', 'RETURN1') | ||
290 | -- check(function (x) return 20 * x end, 'MULK', 'RETURN1') | ||
291 | checkR(function (x) return x ^ 0.5 end, 4, 2.0, 'POWK', 'RETURN1') | ||
292 | checkR(function (x) return x / 2.0 end, 4, 2.0, 'DIVK', 'RETURN1') | ||
293 | checkR(function (x) return x // 10000 end, 10000, 1, 'IDIVK', 'RETURN1') | ||
294 | checkR(function (x) return x % (100.0 - 10) end, 91, 1.0, 'MODK', 'RETURN1') | ||
275 | 295 | ||
276 | -- no foldings (and immediate operands) | 296 | -- no foldings (and immediate operands) |
277 | check(function () return -0.0 end, 'LOADF', 'UNM', 'RETURN1') | 297 | check(function () return -0.0 end, 'LOADF', 'UNM', 'RETURN1') |
diff --git a/testes/db.lua b/testes/db.lua index 9da68210..5b243c39 100644 --- a/testes/db.lua +++ b/testes/db.lua | |||
@@ -794,6 +794,8 @@ assert(a[3] == "index" and a^3 == "pow" and a..a == "concat") | |||
794 | assert(a/3 == "div" and 3%a == "mod") | 794 | assert(a/3 == "div" and 3%a == "mod") |
795 | assert(a+3 == "add" and 3-a == "sub" and a*3 == "mul" and | 795 | assert(a+3 == "add" and 3-a == "sub" and a*3 == "mul" and |
796 | -a == "unm" and #a == "len" and a&3 == "band") | 796 | -a == "unm" and #a == "len" and a&3 == "band") |
797 | assert(a + 30000 == "add" and a - 3.0 == "sub" and a * 3.0 == "mul" and | ||
798 | -a == "unm" and #a == "len" and a & 3 == "band") | ||
797 | assert(a|3 == "bor" and 3~a == "bxor" and a<<3 == "shift" and | 799 | assert(a|3 == "bor" and 3~a == "bxor" and a<<3 == "shift" and |
798 | a>>1 == "shift") | 800 | a>>1 == "shift") |
799 | assert (a==b and a.op == "eq") | 801 | assert (a==b and a.op == "eq") |
diff --git a/testes/events.lua b/testes/events.lua index b071c2a3..ac630d89 100644 --- a/testes/events.lua +++ b/testes/events.lua | |||
@@ -144,6 +144,8 @@ t.__bnot = f("bnot") | |||
144 | -- when the constant table is very small. | 144 | -- when the constant table is very small. |
145 | assert(b+5 == b) | 145 | assert(b+5 == b) |
146 | assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==undef) | 146 | assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==undef) |
147 | assert(5.2 + b == 5.2) | ||
148 | assert(cap[0] == "add" and cap[1] == 5.2 and cap[2] == b and cap[3]==undef) | ||
147 | assert(b+'5' == b) | 149 | assert(b+'5' == b) |
148 | assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==undef) | 150 | assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==undef) |
149 | assert(5+b == 5) | 151 | assert(5+b == 5) |