diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-28 10:58:18 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-28 10:58:18 -0200 |
| commit | ff5fe5104413cf2a5156f86479d4b9b130bad7a6 (patch) | |
| tree | 7ab4b89eafe1d39962c1aca42d47b40159416854 /lcode.c | |
| parent | dfd188ba12f22db8d31cb80426d568e97345e1e2 (diff) | |
| download | lua-ff5fe5104413cf2a5156f86479d4b9b130bad7a6.tar.gz lua-ff5fe5104413cf2a5156f86479d4b9b130bad7a6.tar.bz2 lua-ff5fe5104413cf2a5156f86479d4b9b130bad7a6.zip | |
using register 'k' for conditions in tests (we only need one bit there)
Diffstat (limited to 'lcode.c')
| -rw-r--r-- | lcode.c | 94 |
1 files changed, 58 insertions, 36 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 2.135 2017/11/22 19:15:44 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.136 2017/11/23 19:29:04 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 | */ |
| @@ -160,8 +160,8 @@ void luaK_ret (FuncState *fs, int first, int nret) { | |||
| 160 | ** Code a "conditional jump", that is, a test or comparison opcode | 160 | ** Code a "conditional jump", that is, a test or comparison opcode |
| 161 | ** followed by a jump. Return jump position. | 161 | ** followed by a jump. Return jump position. |
| 162 | */ | 162 | */ |
| 163 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { | 163 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) { |
| 164 | luaK_codeABC(fs, op, A, B, C); | 164 | luaK_codeABCk(fs, op, A, B, C, k); |
| 165 | return luaK_jump(fs); | 165 | return luaK_jump(fs); |
| 166 | } | 166 | } |
| 167 | 167 | ||
| @@ -206,7 +206,7 @@ static int patchtestreg (FuncState *fs, int node, int reg) { | |||
| 206 | else { | 206 | else { |
| 207 | /* no register to put value or register already has the value; | 207 | /* no register to put value or register already has the value; |
| 208 | change instruction to simple test */ | 208 | change instruction to simple test */ |
| 209 | *i = CREATE_ABCk(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i), 0); | 209 | *i = CREATE_ABCk(OP_TEST, GETARG_B(*i), 0, 0, GETARG_k(*i)); |
| 210 | } | 210 | } |
| 211 | return 1; | 211 | return 1; |
| 212 | } | 212 | } |
| @@ -969,7 +969,7 @@ static void negatecondition (FuncState *fs, expdesc *e) { | |||
| 969 | Instruction *pc = getjumpcontrol(fs, e->u.info); | 969 | Instruction *pc = getjumpcontrol(fs, e->u.info); |
| 970 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && | 970 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
| 971 | GET_OPCODE(*pc) != OP_TEST); | 971 | GET_OPCODE(*pc) != OP_TEST); |
| 972 | SETARG_B(*pc, !(GETARG_B(*pc))); | 972 | SETARG_k(*pc, (GETARG_k(*pc) ^ 1)); |
| 973 | } | 973 | } |
| 974 | 974 | ||
| 975 | 975 | ||
| @@ -984,13 +984,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
| 984 | Instruction ie = getinstruction(fs, e); | 984 | Instruction ie = getinstruction(fs, e); |
| 985 | if (GET_OPCODE(ie) == OP_NOT) { | 985 | if (GET_OPCODE(ie) == OP_NOT) { |
| 986 | fs->pc--; /* remove previous OP_NOT */ | 986 | fs->pc--; /* remove previous OP_NOT */ |
| 987 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); | 987 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond); |
| 988 | } | 988 | } |
| 989 | /* else go through */ | 989 | /* else go through */ |
| 990 | } | 990 | } |
| 991 | discharge2anyreg(fs, e); | 991 | discharge2anyreg(fs, e); |
| 992 | freeexp(fs, e); | 992 | freeexp(fs, e); |
| 993 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); | 993 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond); |
| 994 | } | 994 | } |
| 995 | 995 | ||
| 996 | 996 | ||
| @@ -1276,25 +1276,37 @@ static void codecommutative (FuncState *fs, OpCode op, | |||
| 1276 | 1276 | ||
| 1277 | /* | 1277 | /* |
| 1278 | ** Emit code for order comparisons. | 1278 | ** Emit code for order comparisons. |
| 1279 | ** 'e1' was already put in register by 'luaK_infix'. | 1279 | ** When the first operand is an integral value in the proper range, |
| 1280 | ** change (A < B) to (!(B <= A)) and (A <= B) to (!(B < A)) so that | ||
| 1281 | ** it can use an immediate operand. In this case, C indicates this | ||
| 1282 | ** change, for cases that cannot assume a total order (NaN and | ||
| 1283 | ** metamethods). | ||
| 1280 | */ | 1284 | */ |
| 1281 | static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | 1285 | static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { |
| 1282 | int rk1 = check_exp(e1->k == VNONRELOC, e1->u.info); | 1286 | int r1, r2; |
| 1283 | int rk2 = luaK_exp2anyreg(fs, e2); | 1287 | int cond = 1; |
| 1284 | freeexps(fs, e1, e2); | 1288 | int C = 0; |
| 1285 | switch (opr) { | 1289 | lua_Integer im; |
| 1286 | case OPR_GT: case OPR_GE: { | 1290 | if (isSCnumber(e2, &im)) { |
| 1287 | /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ | 1291 | /* use immediate operand */ |
| 1288 | OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); | 1292 | r1 = luaK_exp2anyreg(fs, e1); |
| 1289 | e1->u.info = condjump(fs, op, rk2, 1, rk1); /* invert operands */ | 1293 | r2 = cast_int(im); |
| 1290 | break; | 1294 | op = cast(OpCode, (op - OP_LT) + OP_LTI); |
| 1291 | } | 1295 | } |
| 1292 | default: { /* '==', '<', '<=' use their own opcodes */ | 1296 | else if (isSCnumber(e1, &im)) { |
| 1293 | OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); | 1297 | /* transform (A < B) to (!(B <= A)) and (A <= B) to (!(B < A)) */ |
| 1294 | e1->u.info = condjump(fs, op, rk1, 1, rk2); | 1298 | r1 = luaK_exp2anyreg(fs, e2); |
| 1295 | break; | 1299 | r2 = cast_int(im); |
| 1296 | } | 1300 | op = (op == OP_LT) ? OP_LEI : OP_LTI; |
| 1301 | cond = 0; /* negate original test */ | ||
| 1302 | C = 1; /* indication that it used the transformations */ | ||
| 1297 | } | 1303 | } |
| 1304 | else { /* regular case, compare two registers */ | ||
| 1305 | r1 = luaK_exp2anyreg(fs, e1); | ||
| 1306 | r2 = luaK_exp2anyreg(fs, e2); | ||
| 1307 | } | ||
| 1308 | freeexps(fs, e1, e2); | ||
| 1309 | e1->u.info = condjump(fs, op, r1, r2, C, cond); | ||
| 1298 | e1->k = VJMP; | 1310 | e1->k = VJMP; |
| 1299 | } | 1311 | } |
| 1300 | 1312 | ||
| @@ -1325,7 +1337,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | |||
| 1325 | r2 = luaK_exp2anyreg(fs, e2); | 1337 | r2 = luaK_exp2anyreg(fs, e2); |
| 1326 | } | 1338 | } |
| 1327 | freeexps(fs, e1, e2); | 1339 | freeexps(fs, e1, e2); |
| 1328 | e1->u.info = condjump(fs, op, r1, (opr == OPR_EQ), r2); | 1340 | e1->u.info = condjump(fs, op, r1, r2, 0, (opr == OPR_EQ)); |
| 1329 | e1->k = VJMP; | 1341 | e1->k = VJMP; |
| 1330 | } | 1342 | } |
| 1331 | 1343 | ||
| @@ -1385,7 +1397,10 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
| 1385 | } | 1397 | } |
| 1386 | case OPR_LT: case OPR_LE: | 1398 | case OPR_LT: case OPR_LE: |
| 1387 | case OPR_GT: case OPR_GE: { | 1399 | case OPR_GT: case OPR_GE: { |
| 1388 | luaK_exp2anyreg(fs, v); | 1400 | lua_Integer dummy; |
| 1401 | if (!isSCnumber(v, &dummy)) | ||
| 1402 | luaK_exp2RK(fs, v); | ||
| 1403 | /* else keep numeral, which may be an immediate operand */ | ||
| 1389 | break; | 1404 | break; |
| 1390 | } | 1405 | } |
| 1391 | default: lua_assert(0); | 1406 | default: lua_assert(0); |
| @@ -1399,9 +1414,9 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
| 1399 | ** concatenation is right associative), merge second CONCAT into first | 1414 | ** concatenation is right associative), merge second CONCAT into first |
| 1400 | ** one. | 1415 | ** one. |
| 1401 | */ | 1416 | */ |
| 1402 | void luaK_posfix (FuncState *fs, BinOpr op, | 1417 | void luaK_posfix (FuncState *fs, BinOpr opr, |
| 1403 | expdesc *e1, expdesc *e2, int line) { | 1418 | expdesc *e1, expdesc *e2, int line) { |
| 1404 | switch (op) { | 1419 | switch (opr) { |
| 1405 | case OPR_AND: { | 1420 | case OPR_AND: { |
| 1406 | lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ | 1421 | lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ |
| 1407 | luaK_dischargevars(fs, e2); | 1422 | luaK_dischargevars(fs, e2); |
| @@ -1432,28 +1447,35 @@ void luaK_posfix (FuncState *fs, BinOpr op, | |||
| 1432 | break; | 1447 | break; |
| 1433 | } | 1448 | } |
| 1434 | case OPR_ADD: case OPR_MUL: { | 1449 | case OPR_ADD: case OPR_MUL: { |
| 1435 | if (!constfolding(fs, op + LUA_OPADD, e1, e2)) | 1450 | if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) |
| 1436 | codecommutative(fs, cast(OpCode, op + OP_ADD), e1, e2, line); | 1451 | codecommutative(fs, cast(OpCode, opr + OP_ADD), e1, e2, line); |
| 1437 | break; | 1452 | break; |
| 1438 | } | 1453 | } |
| 1439 | case OPR_SUB: case OPR_DIV: | 1454 | case OPR_SUB: case OPR_DIV: |
| 1440 | case OPR_IDIV: case OPR_MOD: case OPR_POW: { | 1455 | case OPR_IDIV: case OPR_MOD: case OPR_POW: { |
| 1441 | if (!constfolding(fs, op + LUA_OPADD, e1, e2)) | 1456 | if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) |
| 1442 | codearith(fs, cast(OpCode, op + OP_ADD), e1, e2, 0, line); | 1457 | codearith(fs, cast(OpCode, opr + OP_ADD), e1, e2, 0, line); |
| 1443 | break; | 1458 | break; |
| 1444 | } | 1459 | } |
| 1445 | case OPR_BAND: case OPR_BOR: case OPR_BXOR: | 1460 | case OPR_BAND: case OPR_BOR: case OPR_BXOR: |
| 1446 | case OPR_SHL: case OPR_SHR: { | 1461 | case OPR_SHL: case OPR_SHR: { |
| 1447 | if (!constfolding(fs, op + LUA_OPADD, e1, e2)) | 1462 | if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) |
| 1448 | codebinexpval(fs, cast(OpCode, op + OP_ADD), e1, e2, line); | 1463 | codebinexpval(fs, cast(OpCode, opr + OP_ADD), e1, e2, line); |
| 1449 | break; | 1464 | break; |
| 1450 | } | 1465 | } |
| 1451 | case OPR_EQ: case OPR_NE: { | 1466 | case OPR_EQ: case OPR_NE: { |
| 1452 | codeeq(fs, op, e1, e2); | 1467 | codeeq(fs, opr, e1, e2); |
| 1468 | break; | ||
| 1469 | } | ||
| 1470 | case OPR_LT: case OPR_LE: { | ||
| 1471 | OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); | ||
| 1472 | codeorder(fs, op, e1, e2); | ||
| 1453 | break; | 1473 | break; |
| 1454 | } | 1474 | } |
| 1455 | case OPR_LT: case OPR_LE: | ||
| 1456 | case OPR_GT: case OPR_GE: { | 1475 | case OPR_GT: case OPR_GE: { |
| 1476 | /* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */ | ||
| 1477 | OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); | ||
| 1478 | swapexps(e1, e2); | ||
| 1457 | codeorder(fs, op, e1, e2); | 1479 | codeorder(fs, op, e1, e2); |
| 1458 | break; | 1480 | break; |
| 1459 | } | 1481 | } |
