diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 46 |
1 files changed, 27 insertions, 19 deletions
@@ -1337,18 +1337,20 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { | |||
1337 | ** (everything but logical operators 'and'/'or' and comparison | 1337 | ** (everything but logical operators 'and'/'or' and comparison |
1338 | ** operators). | 1338 | ** operators). |
1339 | ** Expression to produce final result will be encoded in 'e1'. | 1339 | ** Expression to produce final result will be encoded in 'e1'. |
1340 | ** Because 'luaK_exp2anyreg' can free registers, its calls must be | ||
1341 | ** in "stack order" (that is, first on 'e2', which may have more | ||
1342 | ** recent registers to be released). | ||
1343 | */ | 1340 | */ |
1344 | static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, | 1341 | static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, |
1345 | OpCode op, int v2, int k, int line) { | 1342 | OpCode op, int v2, int k, int line, |
1343 | OpCode mmop, TMS event) { | ||
1346 | int v1 = luaK_exp2anyreg(fs, e1); | 1344 | int v1 = luaK_exp2anyreg(fs, e1); |
1347 | int pc = luaK_codeABCk(fs, op, 0, v1, v2, k); | 1345 | int pc = luaK_codeABCk(fs, op, 0, v1, v2, k); |
1348 | freeexps(fs, e1, e2); | 1346 | freeexps(fs, e1, e2); |
1349 | e1->u.info = pc; | 1347 | e1->u.info = pc; |
1350 | e1->k = VRELOC; /* all those operations are relocatable */ | 1348 | e1->k = VRELOC; /* all those operations are relocatable */ |
1351 | luaK_fixline(fs, line); | 1349 | luaK_fixline(fs, line); |
1350 | if (event != TM_SHL && event != TM_SHR) { | ||
1351 | luaK_codeABCk(fs, mmop, v1, v2, event, k); /* to call metamethod */ | ||
1352 | luaK_fixline(fs, line); | ||
1353 | } | ||
1352 | } | 1354 | } |
1353 | 1355 | ||
1354 | 1356 | ||
@@ -1359,7 +1361,9 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, | |||
1359 | static void codebinexpval (FuncState *fs, OpCode op, | 1361 | static void codebinexpval (FuncState *fs, OpCode op, |
1360 | expdesc *e1, expdesc *e2, int line) { | 1362 | expdesc *e1, expdesc *e2, int line) { |
1361 | int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ | 1363 | int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ |
1362 | finishbinexpval(fs, e1, e2, op, v2, 0, line); | 1364 | lua_assert(OP_ADD <= op && op <= OP_SHR); |
1365 | finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, | ||
1366 | cast(TMS, (op - OP_ADD) + TM_ADD)); | ||
1363 | } | 1367 | } |
1364 | 1368 | ||
1365 | 1369 | ||
@@ -1367,9 +1371,10 @@ static void codebinexpval (FuncState *fs, OpCode op, | |||
1367 | ** Code binary operators ('+', '-', ...) with immediate operands. | 1371 | ** Code binary operators ('+', '-', ...) with immediate operands. |
1368 | */ | 1372 | */ |
1369 | static void codebini (FuncState *fs, OpCode op, | 1373 | static void codebini (FuncState *fs, OpCode op, |
1370 | expdesc *e1, expdesc *e2, int k, int line) { | 1374 | expdesc *e1, expdesc *e2, int k, int line, |
1375 | TMS event) { | ||
1371 | int v2 = cast_int(e2->u.ival) + OFFSET_sC; /* immediate operand */ | 1376 | int v2 = cast_int(e2->u.ival) + OFFSET_sC; /* immediate operand */ |
1372 | finishbinexpval(fs, e1, e2, op, v2, k, line); | 1377 | finishbinexpval(fs, e1, e2, op, v2, k, line, OP_MMBINI, event); |
1373 | } | 1378 | } |
1374 | 1379 | ||
1375 | 1380 | ||
@@ -1383,16 +1388,18 @@ static void swapexps (expdesc *e1, expdesc *e2) { | |||
1383 | ** constant in the proper range, use variant opcodes with immediate | 1388 | ** constant in the proper range, use variant opcodes with immediate |
1384 | ** operands or K operands. | 1389 | ** operands or K operands. |
1385 | */ | 1390 | */ |
1386 | static void codearith (FuncState *fs, OpCode op, | 1391 | static void codearith (FuncState *fs, BinOpr opr, |
1387 | expdesc *e1, expdesc *e2, int flip, int line) { | 1392 | expdesc *e1, expdesc *e2, int flip, int line) { |
1393 | TMS event = cast(TMS, opr + TM_ADD); | ||
1388 | if (isSCint(e2)) /* immediate operand? */ | 1394 | if (isSCint(e2)) /* immediate operand? */ |
1389 | codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line); | 1395 | codebini(fs, cast(OpCode, opr + OP_ADDI), e1, e2, flip, line, event); |
1390 | else if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ | 1396 | else if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ |
1391 | int v2 = e2->u.info; /* K index */ | 1397 | int v2 = e2->u.info; /* K index */ |
1392 | op = cast(OpCode, op - OP_ADD + OP_ADDK); | 1398 | OpCode op = cast(OpCode, opr + OP_ADDK); |
1393 | finishbinexpval(fs, e1, e2, op, v2, flip, line); | 1399 | finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); |
1394 | } | 1400 | } |
1395 | else { /* 'e2' is neither an immediate nor a K operand */ | 1401 | else { /* 'e2' is neither an immediate nor a K operand */ |
1402 | OpCode op = cast(OpCode, opr + OP_ADD); | ||
1396 | if (flip) | 1403 | if (flip) |
1397 | swapexps(e1, e2); /* back to original order */ | 1404 | swapexps(e1, e2); /* back to original order */ |
1398 | codebinexpval(fs, op, e1, e2, line); /* use standard operators */ | 1405 | codebinexpval(fs, op, e1, e2, line); /* use standard operators */ |
@@ -1405,7 +1412,7 @@ static void codearith (FuncState *fs, OpCode op, | |||
1405 | ** numeric constant, change order of operands to try to use an | 1412 | ** numeric constant, change order of operands to try to use an |
1406 | ** immediate or K operator. | 1413 | ** immediate or K operator. |
1407 | */ | 1414 | */ |
1408 | static void codecommutative (FuncState *fs, OpCode op, | 1415 | static void codecommutative (FuncState *fs, BinOpr op, |
1409 | expdesc *e1, expdesc *e2, int line) { | 1416 | expdesc *e1, expdesc *e2, int line) { |
1410 | int flip = 0; | 1417 | int flip = 0; |
1411 | if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ | 1418 | if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ |
@@ -1430,14 +1437,15 @@ static void codebitwise (FuncState *fs, BinOpr opr, | |||
1430 | inv = 1; | 1437 | inv = 1; |
1431 | } | 1438 | } |
1432 | else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ | 1439 | else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ |
1433 | op = cast(OpCode, opr - OPR_BAND + OP_BAND); | 1440 | op = cast(OpCode, opr + OP_ADD); |
1434 | codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ | 1441 | codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ |
1435 | return; | 1442 | return; |
1436 | } | 1443 | } |
1437 | v2 = e2->u.info; /* index in K array */ | 1444 | v2 = e2->u.info; /* index in K array */ |
1438 | op = cast(OpCode, opr - OPR_BAND + OP_BANDK); | 1445 | op = cast(OpCode, opr + OP_ADDK); |
1439 | lua_assert(ttisinteger(&fs->f->k[v2])); | 1446 | lua_assert(ttisinteger(&fs->f->k[v2])); |
1440 | finishbinexpval(fs, e1, e2, op, v2, inv, line); | 1447 | finishbinexpval(fs, e1, e2, op, v2, inv, line, OP_MMBINK, |
1448 | cast(TMS, opr + TM_ADD)); | ||
1441 | } | 1449 | } |
1442 | 1450 | ||
1443 | 1451 | ||
@@ -1453,7 +1461,7 @@ static void codeshift (FuncState *fs, OpCode op, | |||
1453 | changedir = 1; | 1461 | changedir = 1; |
1454 | e2->u.ival = -(e2->u.ival); | 1462 | e2->u.ival = -(e2->u.ival); |
1455 | } | 1463 | } |
1456 | codebini(fs, OP_SHRI, e1, e2, changedir, line); | 1464 | codebini(fs, OP_SHRI, e1, e2, changedir, line, TM_SHL); |
1457 | } | 1465 | } |
1458 | else | 1466 | else |
1459 | codebinexpval(fs, op, e1, e2, line); | 1467 | codebinexpval(fs, op, e1, e2, line); |
@@ -1638,13 +1646,13 @@ void luaK_posfix (FuncState *fs, BinOpr opr, | |||
1638 | } | 1646 | } |
1639 | case OPR_ADD: case OPR_MUL: { | 1647 | case OPR_ADD: case OPR_MUL: { |
1640 | if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) | 1648 | if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) |
1641 | codecommutative(fs, cast(OpCode, opr + OP_ADD), e1, e2, line); | 1649 | codecommutative(fs, opr, e1, e2, line); |
1642 | break; | 1650 | break; |
1643 | } | 1651 | } |
1644 | case OPR_SUB: case OPR_DIV: | 1652 | case OPR_SUB: case OPR_DIV: |
1645 | case OPR_IDIV: case OPR_MOD: case OPR_POW: { | 1653 | case OPR_IDIV: case OPR_MOD: case OPR_POW: { |
1646 | if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) | 1654 | if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) |
1647 | codearith(fs, cast(OpCode, opr + OP_ADD), e1, e2, 0, line); | 1655 | codearith(fs, opr, e1, e2, 0, line); |
1648 | break; | 1656 | break; |
1649 | } | 1657 | } |
1650 | case OPR_BAND: case OPR_BOR: case OPR_BXOR: { | 1658 | case OPR_BAND: case OPR_BOR: case OPR_BXOR: { |
@@ -1656,7 +1664,7 @@ void luaK_posfix (FuncState *fs, BinOpr opr, | |||
1656 | if (!constfolding(fs, LUA_OPSHL, e1, e2)) { | 1664 | if (!constfolding(fs, LUA_OPSHL, e1, e2)) { |
1657 | if (isSCint(e1)) { | 1665 | if (isSCint(e1)) { |
1658 | swapexps(e1, e2); | 1666 | swapexps(e1, e2); |
1659 | codebini(fs, OP_SHLI, e1, e2, 1, line); | 1667 | codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); |
1660 | } | 1668 | } |
1661 | else | 1669 | else |
1662 | codeshift(fs, OP_SHL, e1, e2, line); | 1670 | codeshift(fs, OP_SHL, e1, e2, line); |