diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 126 |
1 files changed, 73 insertions, 53 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 | ||