diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 26 |
1 files changed, 15 insertions, 11 deletions
@@ -1339,19 +1339,23 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { | |||
1339 | ** Expression to produce final result will be encoded in 'e1'. | 1339 | ** Expression to produce final result will be encoded in 'e1'. |
1340 | */ | 1340 | */ |
1341 | static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, | 1341 | static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, |
1342 | OpCode op, int v2, int k, int line, | 1342 | OpCode op, int v2, int flip, int line, |
1343 | OpCode mmop, TMS event) { | 1343 | OpCode mmop, TMS event) { |
1344 | int v1 = luaK_exp2anyreg(fs, e1); | 1344 | int v1 = luaK_exp2anyreg(fs, e1); |
1345 | int pc = luaK_codeABCk(fs, op, 0, v1, v2, k); | 1345 | int pc = luaK_codeABCk(fs, op, 0, v1, v2, flip); |
1346 | freeexps(fs, e1, e2); | 1346 | freeexps(fs, e1, e2); |
1347 | e1->u.info = pc; | 1347 | e1->u.info = pc; |
1348 | e1->k = VRELOC; /* all those operations are relocatable */ | 1348 | e1->k = VRELOC; /* all those operations are relocatable */ |
1349 | luaK_fixline(fs, line); | 1349 | luaK_fixline(fs, line); |
1350 | if (event != TM_SHL && event != TM_SHR) { | 1350 | if (op == OP_SHRI && flip) { |
1351 | luaK_codeABCk(fs, mmop, v1, v2, event, k); /* to call metamethod */ | 1351 | /* For the metamethod, undo the "changedir" did by 'codeshift' */ |
1352 | event = TM_SHL; | ||
1353 | v2 = -(v2 - OFFSET_sC) + OFFSET_sC; | ||
1354 | flip = 0; | ||
1355 | } | ||
1356 | luaK_codeABCk(fs, mmop, v1, v2, event, flip); /* to call metamethod */ | ||
1352 | luaK_fixline(fs, line); | 1357 | luaK_fixline(fs, line); |
1353 | } | 1358 | } |
1354 | } | ||
1355 | 1359 | ||
1356 | 1360 | ||
1357 | /* | 1361 | /* |
@@ -1371,10 +1375,10 @@ static void codebinexpval (FuncState *fs, OpCode op, | |||
1371 | ** Code binary operators ('+', '-', ...) with immediate operands. | 1375 | ** Code binary operators ('+', '-', ...) with immediate operands. |
1372 | */ | 1376 | */ |
1373 | static void codebini (FuncState *fs, OpCode op, | 1377 | static void codebini (FuncState *fs, OpCode op, |
1374 | expdesc *e1, expdesc *e2, int k, int line, | 1378 | expdesc *e1, expdesc *e2, int flip, int line, |
1375 | TMS event) { | 1379 | TMS event) { |
1376 | int v2 = cast_int(e2->u.ival) + OFFSET_sC; /* immediate operand */ | 1380 | int v2 = cast_int(e2->u.ival) + OFFSET_sC; /* immediate operand */ |
1377 | finishbinexpval(fs, e1, e2, op, v2, k, line, OP_MMBINI, event); | 1381 | finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINI, event); |
1378 | } | 1382 | } |
1379 | 1383 | ||
1380 | 1384 | ||
@@ -1429,12 +1433,12 @@ static void codecommutative (FuncState *fs, BinOpr op, | |||
1429 | */ | 1433 | */ |
1430 | static void codebitwise (FuncState *fs, BinOpr opr, | 1434 | static void codebitwise (FuncState *fs, BinOpr opr, |
1431 | expdesc *e1, expdesc *e2, int line) { | 1435 | expdesc *e1, expdesc *e2, int line) { |
1432 | int inv = 0; | 1436 | int flip = 0; |
1433 | int v2; | 1437 | int v2; |
1434 | OpCode op; | 1438 | OpCode op; |
1435 | if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { | 1439 | if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { |
1436 | swapexps(e1, e2); /* 'e2' will be the constant operand */ | 1440 | swapexps(e1, e2); /* 'e2' will be the constant operand */ |
1437 | inv = 1; | 1441 | flip = 1; |
1438 | } | 1442 | } |
1439 | else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ | 1443 | else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ |
1440 | op = cast(OpCode, opr + OP_ADD); | 1444 | op = cast(OpCode, opr + OP_ADD); |
@@ -1444,7 +1448,7 @@ static void codebitwise (FuncState *fs, BinOpr opr, | |||
1444 | v2 = e2->u.info; /* index in K array */ | 1448 | v2 = e2->u.info; /* index in K array */ |
1445 | op = cast(OpCode, opr + OP_ADDK); | 1449 | op = cast(OpCode, opr + OP_ADDK); |
1446 | lua_assert(ttisinteger(&fs->f->k[v2])); | 1450 | lua_assert(ttisinteger(&fs->f->k[v2])); |
1447 | finishbinexpval(fs, e1, e2, op, v2, inv, line, OP_MMBINK, | 1451 | finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, |
1448 | cast(TMS, opr + TM_ADD)); | 1452 | cast(TMS, opr + TM_ADD)); |
1449 | } | 1453 | } |
1450 | 1454 | ||
@@ -1461,7 +1465,7 @@ static void codeshift (FuncState *fs, OpCode op, | |||
1461 | changedir = 1; | 1465 | changedir = 1; |
1462 | e2->u.ival = -(e2->u.ival); | 1466 | e2->u.ival = -(e2->u.ival); |
1463 | } | 1467 | } |
1464 | codebini(fs, OP_SHRI, e1, e2, changedir, line, TM_SHL); | 1468 | codebini(fs, OP_SHRI, e1, e2, changedir, line, TM_SHR); |
1465 | } | 1469 | } |
1466 | else | 1470 | else |
1467 | codebinexpval(fs, op, e1, e2, line); | 1471 | codebinexpval(fs, op, e1, e2, line); |