diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 42 |
1 files changed, 23 insertions, 19 deletions
@@ -179,8 +179,8 @@ void luaK_ret (FuncState *fs, int first, int nret) { | |||
179 | ** Code a "conditional jump", that is, a test or comparison opcode | 179 | ** Code a "conditional jump", that is, a test or comparison opcode |
180 | ** followed by a jump. Return jump position. | 180 | ** followed by a jump. Return jump position. |
181 | */ | 181 | */ |
182 | static int condjump (FuncState *fs, OpCode op, int A, int B, int k) { | 182 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) { |
183 | luaK_codeABCk(fs, op, A, B, 0, k); | 183 | luaK_codeABCk(fs, op, A, B, C, k); |
184 | return luaK_jump(fs); | 184 | return luaK_jump(fs); |
185 | } | 185 | } |
186 | 186 | ||
@@ -799,7 +799,7 @@ static int need_value (FuncState *fs, int list) { | |||
799 | 799 | ||
800 | /* | 800 | /* |
801 | ** Ensures final expression result (which includes results from its | 801 | ** Ensures final expression result (which includes results from its |
802 | ** jump ** lists) is in register 'reg'. | 802 | ** jump lists) is in register 'reg'. |
803 | ** If expression has jumps, need to patch these jumps either to | 803 | ** If expression has jumps, need to patch these jumps either to |
804 | ** its final position or to "load" instructions (for those tests | 804 | ** its final position or to "load" instructions (for those tests |
805 | ** that do not produce values). | 805 | ** that do not produce values). |
@@ -814,8 +814,9 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { | |||
814 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ | 814 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ |
815 | if (need_value(fs, e->t) || need_value(fs, e->f)) { | 815 | if (need_value(fs, e->t) || need_value(fs, e->f)) { |
816 | int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); | 816 | int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); |
817 | p_f = code_loadbool(fs, reg, 0, 1); | 817 | p_f = code_loadbool(fs, reg, 0, 1); /* load false and skip next i. */ |
818 | p_t = code_loadbool(fs, reg, 1, 0); | 818 | p_t = code_loadbool(fs, reg, 1, 0); /* load true */ |
819 | /* jump around these booleans if 'e' is not a test */ | ||
819 | luaK_patchtohere(fs, fj); | 820 | luaK_patchtohere(fs, fj); |
820 | } | 821 | } |
821 | final = luaK_getlabel(fs); | 822 | final = luaK_getlabel(fs); |
@@ -1005,13 +1006,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
1005 | Instruction ie = getinstruction(fs, e); | 1006 | Instruction ie = getinstruction(fs, e); |
1006 | if (GET_OPCODE(ie) == OP_NOT) { | 1007 | if (GET_OPCODE(ie) == OP_NOT) { |
1007 | removelastinstruction(fs); /* remove previous OP_NOT */ | 1008 | removelastinstruction(fs); /* remove previous OP_NOT */ |
1008 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); | 1009 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond); |
1009 | } | 1010 | } |
1010 | /* else go through */ | 1011 | /* else go through */ |
1011 | } | 1012 | } |
1012 | discharge2anyreg(fs, e); | 1013 | discharge2anyreg(fs, e); |
1013 | freeexp(fs, e); | 1014 | freeexp(fs, e); |
1014 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); | 1015 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond); |
1015 | } | 1016 | } |
1016 | 1017 | ||
1017 | 1018 | ||
@@ -1139,13 +1140,15 @@ static int isSCint (expdesc *e) { | |||
1139 | 1140 | ||
1140 | /* | 1141 | /* |
1141 | ** Check whether expression 'e' is a literal integer or float in | 1142 | ** Check whether expression 'e' is a literal integer or float in |
1142 | ** proper range to fit in register sC | 1143 | ** proper range to fit in a register (sB or sC). |
1143 | */ | 1144 | */ |
1144 | static int isSCnumber (expdesc *e, lua_Integer *i) { | 1145 | static int isSCnumber (expdesc *e, lua_Integer *i, int *isfloat) { |
1145 | if (e->k == VKINT) | 1146 | if (e->k == VKINT) |
1146 | *i = e->u.ival; | 1147 | *i = e->u.ival; |
1147 | else if (!(e->k == VKFLT && floatI(e->u.nval, i))) | 1148 | else if (!(e->k == VKFLT && floatI(e->u.nval, i))) |
1148 | return 0; /* not a number */ | 1149 | return 0; /* not a number */ |
1150 | else | ||
1151 | *isfloat = 1; | ||
1149 | if (!hasjumps(e) && fitsC(*i)) { | 1152 | if (!hasjumps(e) && fitsC(*i)) { |
1150 | *i += OFFSET_sC; | 1153 | *i += OFFSET_sC; |
1151 | return 1; | 1154 | return 1; |
@@ -1372,21 +1375,20 @@ static void codeshift (FuncState *fs, OpCode op, | |||
1372 | 1375 | ||
1373 | 1376 | ||
1374 | /* | 1377 | /* |
1375 | ** Emit code for order comparisons. | 1378 | ** Emit code for order comparisons. When using an immediate operand, |
1376 | ** When the first operand A is an integral value in the proper range, | 1379 | ** 'isfloat' tells whether the original value was a float. |
1377 | ** change (A < B) to (B > A) and (A <= B) to (B >= A) so that | ||
1378 | ** it can use an immediate operand. | ||
1379 | */ | 1380 | */ |
1380 | static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | 1381 | static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { |
1381 | int r1, r2; | 1382 | int r1, r2; |
1382 | lua_Integer im; | 1383 | lua_Integer im; |
1383 | if (isSCnumber(e2, &im)) { | 1384 | int isfloat = 0; |
1385 | if (isSCnumber(e2, &im, &isfloat)) { | ||
1384 | /* use immediate operand */ | 1386 | /* use immediate operand */ |
1385 | r1 = luaK_exp2anyreg(fs, e1); | 1387 | r1 = luaK_exp2anyreg(fs, e1); |
1386 | r2 = cast_int(im); | 1388 | r2 = cast_int(im); |
1387 | op = cast(OpCode, (op - OP_LT) + OP_LTI); | 1389 | op = cast(OpCode, (op - OP_LT) + OP_LTI); |
1388 | } | 1390 | } |
1389 | else if (isSCnumber(e1, &im)) { | 1391 | else if (isSCnumber(e1, &im, &isfloat)) { |
1390 | /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ | 1392 | /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ |
1391 | r1 = luaK_exp2anyreg(fs, e2); | 1393 | r1 = luaK_exp2anyreg(fs, e2); |
1392 | r2 = cast_int(im); | 1394 | r2 = cast_int(im); |
@@ -1397,7 +1399,7 @@ static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | |||
1397 | r2 = luaK_exp2anyreg(fs, e2); | 1399 | r2 = luaK_exp2anyreg(fs, e2); |
1398 | } | 1400 | } |
1399 | freeexps(fs, e1, e2); | 1401 | freeexps(fs, e1, e2); |
1400 | e1->u.info = condjump(fs, op, r1, r2, 1); | 1402 | e1->u.info = condjump(fs, op, r1, r2, isfloat, 1); |
1401 | e1->k = VJMP; | 1403 | e1->k = VJMP; |
1402 | } | 1404 | } |
1403 | 1405 | ||
@@ -1409,13 +1411,14 @@ static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | |||
1409 | static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | 1411 | static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { |
1410 | int r1, r2; | 1412 | int r1, r2; |
1411 | lua_Integer im; | 1413 | lua_Integer im; |
1414 | int isfloat = 0; /* not needed here, but kept for symmetry */ | ||
1412 | OpCode op; | 1415 | OpCode op; |
1413 | if (e1->k != VNONRELOC) { | 1416 | if (e1->k != VNONRELOC) { |
1414 | lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT); | 1417 | lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT); |
1415 | swapexps(e1, e2); | 1418 | swapexps(e1, e2); |
1416 | } | 1419 | } |
1417 | r1 = luaK_exp2anyreg(fs, e1); /* 1nd expression must be in register */ | 1420 | r1 = luaK_exp2anyreg(fs, e1); /* 1nd expression must be in register */ |
1418 | if (isSCnumber(e2, &im)) { | 1421 | if (isSCnumber(e2, &im, &isfloat)) { |
1419 | op = OP_EQI; | 1422 | op = OP_EQI; |
1420 | r2 = cast_int(im); /* immediate operand */ | 1423 | r2 = cast_int(im); /* immediate operand */ |
1421 | } | 1424 | } |
@@ -1428,7 +1431,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | |||
1428 | r2 = luaK_exp2anyreg(fs, e2); | 1431 | r2 = luaK_exp2anyreg(fs, e2); |
1429 | } | 1432 | } |
1430 | freeexps(fs, e1, e2); | 1433 | freeexps(fs, e1, e2); |
1431 | e1->u.info = condjump(fs, op, r1, r2, (opr == OPR_EQ)); | 1434 | e1->u.info = condjump(fs, op, r1, r2, isfloat, (opr == OPR_EQ)); |
1432 | e1->k = VJMP; | 1435 | e1->k = VJMP; |
1433 | } | 1436 | } |
1434 | 1437 | ||
@@ -1489,7 +1492,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
1489 | case OPR_LT: case OPR_LE: | 1492 | case OPR_LT: case OPR_LE: |
1490 | case OPR_GT: case OPR_GE: { | 1493 | case OPR_GT: case OPR_GE: { |
1491 | lua_Integer dummy; | 1494 | lua_Integer dummy; |
1492 | if (!isSCnumber(v, &dummy)) | 1495 | int dummy2; |
1496 | if (!isSCnumber(v, &dummy, &dummy2)) | ||
1493 | luaK_exp2anyreg(fs, v); | 1497 | luaK_exp2anyreg(fs, v); |
1494 | /* else keep numeral, which may be an immediate operand */ | 1498 | /* else keep numeral, which may be an immediate operand */ |
1495 | break; | 1499 | break; |