diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-10-01 17:24:37 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-10-01 17:24:37 -0300 |
commit | b2a580bdb1982e45bb37f95b78c2dafec6efa7a6 (patch) | |
tree | 76de58214adff838a26346514a8a6fba459bde9b | |
parent | 89f6a85f034b2535e43e421991098fa05a92cd60 (diff) | |
download | lua-b2a580bdb1982e45bb37f95b78c2dafec6efa7a6.tar.gz lua-b2a580bdb1982e45bb37f95b78c2dafec6efa7a6.tar.bz2 lua-b2a580bdb1982e45bb37f95b78c2dafec6efa7a6.zip |
Janitorial work
- Several details in 'lcode.c'
- A few more tests for code generation
- Bug in assert in 'lcode.c' ("=" x "==")
- Comments in 'lopcodes.h' and 'ltable.c'
-rw-r--r-- | lcode.c | 61 | ||||
-rw-r--r-- | lopcodes.h | 8 | ||||
-rw-r--r-- | ltable.c | 44 | ||||
-rw-r--r-- | testes/code.lua | 7 |
4 files changed, 62 insertions, 58 deletions
@@ -359,12 +359,12 @@ static void removelastlineinfo (FuncState *fs) { | |||
359 | Proto *f = fs->f; | 359 | Proto *f = fs->f; |
360 | int pc = fs->pc - 1; /* last instruction coded */ | 360 | int pc = fs->pc - 1; /* last instruction coded */ |
361 | if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ | 361 | if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ |
362 | fs->previousline -= f->lineinfo[pc]; /* last line saved */ | 362 | fs->previousline -= f->lineinfo[pc]; /* correct last line saved */ |
363 | fs->iwthabs--; | 363 | fs->iwthabs--; /* undo previous increment */ |
364 | } | 364 | } |
365 | else { /* absolute line information */ | 365 | else { /* absolute line information */ |
366 | lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc); | ||
366 | fs->nabslineinfo--; /* remove it */ | 367 | fs->nabslineinfo--; /* remove it */ |
367 | lua_assert(f->abslineinfo[fs->nabslineinfo].pc = pc); | ||
368 | fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ | 368 | fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ |
369 | } | 369 | } |
370 | } | 370 | } |
@@ -626,12 +626,12 @@ static int nilK (FuncState *fs) { | |||
626 | 626 | ||
627 | 627 | ||
628 | /* | 628 | /* |
629 | ** Check whether 'i' can be stored in an 'sC' operand. | 629 | ** Check whether 'i' can be stored in an 'sC' operand. Equivalent to |
630 | ** Equivalent to (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) | 630 | ** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of |
631 | ** but without risk of overflows in the addition. | 631 | ** overflows in the hidden addition inside 'int2sC'. |
632 | */ | 632 | */ |
633 | static int fitsC (lua_Integer i) { | 633 | static int fitsC (lua_Integer i) { |
634 | return (-OFFSET_sC <= i && i <= MAXARG_C - OFFSET_sC); | 634 | return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C)); |
635 | } | 635 | } |
636 | 636 | ||
637 | 637 | ||
@@ -1213,15 +1213,6 @@ static int isSCint (expdesc *e) { | |||
1213 | 1213 | ||
1214 | 1214 | ||
1215 | /* | 1215 | /* |
1216 | ** Check whether expression 'e' and its negation are literal integers | ||
1217 | ** in proper range to fit in register sC | ||
1218 | */ | ||
1219 | static int isSCintN (expdesc *e) { | ||
1220 | return luaK_isKint(e) && fitsC(e->u.ival) && fitsC(-e->u.ival); | ||
1221 | } | ||
1222 | |||
1223 | |||
1224 | /* | ||
1225 | ** Check whether expression 'e' is a literal integer or float in | 1216 | ** Check whether expression 'e' is a literal integer or float in |
1226 | ** proper range to fit in a register (sB or sC). | 1217 | ** proper range to fit in a register (sB or sC). |
1227 | */ | 1218 | */ |
@@ -1382,15 +1373,25 @@ static void codebini (FuncState *fs, OpCode op, | |||
1382 | } | 1373 | } |
1383 | 1374 | ||
1384 | 1375 | ||
1385 | /* Code binary operators negating the immediate operand for the | 1376 | /* Try to code a binary operator negating its second operand. |
1386 | ** opcode. For the metamethod, 'v2' must keep its original value. | 1377 | ** For the metamethod, 2nd operand must keep its original value. |
1387 | */ | 1378 | */ |
1388 | static void finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, | 1379 | static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, |
1389 | OpCode op, int line, TMS event) { | 1380 | OpCode op, int line, TMS event) { |
1390 | int v2 = cast_int(e2->u.ival); | 1381 | if (!luaK_isKint(e2)) |
1391 | finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); | 1382 | return 0; /* not an integer constant */ |
1392 | /* correct metamethod argument */ | 1383 | else { |
1393 | SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); | 1384 | lua_Integer i2 = e2->u.ival; |
1385 | if (!(fitsC(i2) && fitsC(-i2))) | ||
1386 | return 0; /* not in the proper range */ | ||
1387 | else { /* operating a small integer constant */ | ||
1388 | int v2 = cast_int(i2); | ||
1389 | finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); | ||
1390 | /* correct metamethod argument */ | ||
1391 | SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); | ||
1392 | return 1; /* successfully coded */ | ||
1393 | } | ||
1394 | } | ||
1394 | } | 1395 | } |
1395 | 1396 | ||
1396 | 1397 | ||
@@ -1647,11 +1648,8 @@ void luaK_posfix (FuncState *fs, BinOpr opr, | |||
1647 | break; | 1648 | break; |
1648 | } | 1649 | } |
1649 | case OPR_SUB: { | 1650 | case OPR_SUB: { |
1650 | if (isSCintN(e2)) { /* subtracting a small integer constant? */ | 1651 | if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB)) |
1651 | /* code it as (r1 + -I) */ | 1652 | break; /* coded as (r1 + -I) */ |
1652 | finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB); | ||
1653 | break; | ||
1654 | } | ||
1655 | /* ELSE *//* FALLTHROUGH */ | 1653 | /* ELSE *//* FALLTHROUGH */ |
1656 | } | 1654 | } |
1657 | case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { | 1655 | case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { |
@@ -1667,16 +1665,15 @@ void luaK_posfix (FuncState *fs, BinOpr opr, | |||
1667 | swapexps(e1, e2); | 1665 | swapexps(e1, e2); |
1668 | codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */ | 1666 | codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */ |
1669 | } | 1667 | } |
1670 | else if (isSCintN(e2)) { /* shifting by a small integer constant? */ | 1668 | else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) { |
1671 | /* code it as (r1 >> -I) */ | 1669 | /* coded as (r1 >> -I) */; |
1672 | finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL); | ||
1673 | } | 1670 | } |
1674 | else /* regular case (two registers) */ | 1671 | else /* regular case (two registers) */ |
1675 | codebinexpval(fs, OP_SHL, e1, e2, line); | 1672 | codebinexpval(fs, OP_SHL, e1, e2, line); |
1676 | break; | 1673 | break; |
1677 | } | 1674 | } |
1678 | case OPR_SHR: { | 1675 | case OPR_SHR: { |
1679 | if (isSCintN(e2)) | 1676 | if (isSCint(e2)) |
1680 | codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ | 1677 | codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ |
1681 | else /* regular case (two registers) */ | 1678 | else /* regular case (two registers) */ |
1682 | codebinexpval(fs, OP_SHR, e1, e2, line); | 1679 | codebinexpval(fs, OP_SHR, e1, e2, line); |
@@ -221,7 +221,7 @@ OP_NEWTABLE,/* A B C R(A) := {} */ | |||
221 | 221 | ||
222 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */ | 222 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */ |
223 | 223 | ||
224 | OP_ADDI,/* A B sC R(A) := R(B) + C */ | 224 | OP_ADDI,/* A B sC R(A) := R(B) + sC */ |
225 | 225 | ||
226 | OP_ADDK,/* A B C R(A) := R(B) + K(C) */ | 226 | OP_ADDK,/* A B C R(A) := R(B) + K(C) */ |
227 | OP_SUBK,/* A B C R(A) := R(B) - K(C) */ | 227 | OP_SUBK,/* A B C R(A) := R(B) - K(C) */ |
@@ -235,8 +235,8 @@ OP_BANDK,/* A B C R(A) := R(B) & K(C):integer */ | |||
235 | OP_BORK,/* A B C R(A) := R(B) | K(C):integer */ | 235 | OP_BORK,/* A B C R(A) := R(B) | K(C):integer */ |
236 | OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */ | 236 | OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */ |
237 | 237 | ||
238 | OP_SHRI,/* A B sC R(A) := R(B) >> C */ | 238 | OP_SHRI,/* A B sC R(A) := R(B) >> sC */ |
239 | OP_SHLI,/* A B sC R(A) := C << R(B) */ | 239 | OP_SHLI,/* A B sC R(A) := sC << R(B) */ |
240 | 240 | ||
241 | OP_ADD,/* A B C R(A) := R(B) + R(C) */ | 241 | OP_ADD,/* A B C R(A) := R(B) + R(C) */ |
242 | OP_SUB,/* A B C R(A) := R(B) - R(C) */ | 242 | OP_SUB,/* A B C R(A) := R(B) - R(C) */ |
@@ -253,7 +253,7 @@ OP_SHL,/* A B C R(A) := R(B) << R(C) */ | |||
253 | OP_SHR,/* A B C R(A) := R(B) >> R(C) */ | 253 | OP_SHR,/* A B C R(A) := R(B) >> R(C) */ |
254 | 254 | ||
255 | OP_MMBIN,/* A B C call C metamethod over R(A) and R(B) */ | 255 | OP_MMBIN,/* A B C call C metamethod over R(A) and R(B) */ |
256 | OP_MMBINI,/* A B C call C metamethod over R(A) and B */ | 256 | OP_MMBINI,/* A sB C call C metamethod over R(A) and sB */ |
257 | OP_MMBINK,/* A B C call C metamethod over R(A) and K(B) */ | 257 | OP_MMBINK,/* A B C call C metamethod over R(A) and K(B) */ |
258 | 258 | ||
259 | OP_UNM,/* A B R(A) := -R(B) */ | 259 | OP_UNM,/* A B R(A) := -R(B) */ |
@@ -833,39 +833,41 @@ static unsigned int binsearch (const TValue *array, unsigned int i, | |||
833 | ** and 'maxinteger' if t[maxinteger] is present.) | 833 | ** and 'maxinteger' if t[maxinteger] is present.) |
834 | ** (In the next explanation, we use Lua indices, that is, with base 1. | 834 | ** (In the next explanation, we use Lua indices, that is, with base 1. |
835 | ** The code itself uses base 0 when indexing the array part of the table.) | 835 | ** The code itself uses base 0 when indexing the array part of the table.) |
836 | ** The code starts with 'limit', a position in the array part that may | 836 | ** The code starts with 'limit = t->alimit', a position in the array |
837 | ** be a boundary. | 837 | ** part that may be a boundary. |
838 | ** | ||
838 | ** (1) If 't[limit]' is empty, there must be a boundary before it. | 839 | ** (1) If 't[limit]' is empty, there must be a boundary before it. |
839 | ** As a common case (e.g., after 't[#t]=nil'), check whether 'hint-1' | 840 | ** As a common case (e.g., after 't[#t]=nil'), check whether 'limit-1' |
840 | ** is present. If so, it is a boundary. Otherwise, do a binary search | 841 | ** is present. If so, it is a boundary. Otherwise, do a binary search |
841 | ** between 0 and limit to find a boundary. In both cases, try to | 842 | ** between 0 and limit to find a boundary. In both cases, try to |
842 | ** use this boundary as the new 'limit', as a hint for the next call. | 843 | ** use this boundary as the new 'alimit', as a hint for the next call. |
844 | ** | ||
843 | ** (2) If 't[limit]' is not empty and the array has more elements | 845 | ** (2) If 't[limit]' is not empty and the array has more elements |
844 | ** after 'limit', try to find a boundary there. Again, try first | 846 | ** after 'limit', try to find a boundary there. Again, try first |
845 | ** the special case (which should be quite frequent) where 'limit+1' | 847 | ** the special case (which should be quite frequent) where 'limit+1' |
846 | ** is empty, so that 'limit' is a boundary. Otherwise, check the | 848 | ** is empty, so that 'limit' is a boundary. Otherwise, check the |
847 | ** last element of the array part (set it as a new limit). If it is empty, | 849 | ** last element of the array part. If it is empty, there must be a |
848 | ** there must be a boundary between the old limit (present) and the new | 850 | ** boundary between the old limit (present) and the last element |
849 | ** limit (absent), which is found with a binary search. (This boundary | 851 | ** (absent), which is found with a binary search. (This boundary always |
850 | ** always can be a new limit.) | 852 | ** can be a new limit.) |
853 | ** | ||
851 | ** (3) The last case is when there are no elements in the array part | 854 | ** (3) The last case is when there are no elements in the array part |
852 | ** (limit == 0) or its last element (the new limit) is present. | 855 | ** (limit == 0) or its last element (the new limit) is present. |
853 | ** In this case, must check the hash part. If there is no hash part, | 856 | ** In this case, must check the hash part. If there is no hash part |
854 | ** the boundary is 0. Otherwise, if 'limit+1' is absent, 'limit' is | 857 | ** or 'limit+1' is absent, 'limit' is a boundary. Otherwise, call |
855 | ** a boundary. Finally, if 'limit+1' is present, call 'hash_search' | 858 | ** 'hash_search' to find a boundary in the hash part of the table. |
856 | ** to find a boundary in the hash part of the table. (In those | 859 | ** (In those cases, the boundary is not inside the array part, and |
857 | ** cases, the boundary is not inside the array part, and therefore | 860 | ** therefore cannot be used as a new limit.) |
858 | ** cannot be used as a new limit.) | ||
859 | */ | 861 | */ |
860 | lua_Unsigned luaH_getn (Table *t) { | 862 | lua_Unsigned luaH_getn (Table *t) { |
861 | unsigned int limit = t->alimit; | 863 | unsigned int limit = t->alimit; |
862 | if (limit > 0 && isempty(&t->array[limit - 1])) { | 864 | if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */ |
863 | /* (1) there must be a boundary before 'limit' */ | 865 | /* there must be a boundary before 'limit' */ |
864 | if (limit >= 2 && !isempty(&t->array[limit - 2])) { | 866 | if (limit >= 2 && !isempty(&t->array[limit - 2])) { |
865 | /* 'limit - 1' is a boundary; can it be a new limit? */ | 867 | /* 'limit - 1' is a boundary; can it be a new limit? */ |
866 | if (ispow2realasize(t) && !ispow2(limit - 1)) { | 868 | if (ispow2realasize(t) && !ispow2(limit - 1)) { |
867 | t->alimit = limit - 1; | 869 | t->alimit = limit - 1; |
868 | setnorealasize(t); | 870 | setnorealasize(t); /* now 'alimit' is not the real size */ |
869 | } | 871 | } |
870 | return limit - 1; | 872 | return limit - 1; |
871 | } | 873 | } |
@@ -880,8 +882,8 @@ lua_Unsigned luaH_getn (Table *t) { | |||
880 | } | 882 | } |
881 | } | 883 | } |
882 | /* 'limit' is zero or present in table */ | 884 | /* 'limit' is zero or present in table */ |
883 | if (!limitequalsasize(t)) { | 885 | if (!limitequalsasize(t)) { /* (2)? */ |
884 | /* (2) 'limit' > 0 and array has more elements after 'limit' */ | 886 | /* 'limit' > 0 and array has more elements after 'limit' */ |
885 | if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */ | 887 | if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */ |
886 | return limit; /* this is the boundary */ | 888 | return limit; /* this is the boundary */ |
887 | /* else, try last element in the array */ | 889 | /* else, try last element in the array */ |
@@ -899,7 +901,7 @@ lua_Unsigned luaH_getn (Table *t) { | |||
899 | lua_assert(limit == luaH_realasize(t) && | 901 | lua_assert(limit == luaH_realasize(t) && |
900 | (limit == 0 || !isempty(&t->array[limit - 1]))); | 902 | (limit == 0 || !isempty(&t->array[limit - 1]))); |
901 | if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1)))) | 903 | if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1)))) |
902 | return limit; /* 'limit + 1' is absent... */ | 904 | return limit; /* 'limit + 1' is absent */ |
903 | else /* 'limit + 1' is also present */ | 905 | else /* 'limit + 1' is also present */ |
904 | return hash_search(t, limit); | 906 | return hash_search(t, limit); |
905 | } | 907 | } |
@@ -908,6 +910,8 @@ lua_Unsigned luaH_getn (Table *t) { | |||
908 | 910 | ||
909 | #if defined(LUA_DEBUG) | 911 | #if defined(LUA_DEBUG) |
910 | 912 | ||
913 | /* export these functions for the test library */ | ||
914 | |||
911 | Node *luaH_mainposition (const Table *t, const TValue *key) { | 915 | Node *luaH_mainposition (const Table *t, const TValue *key) { |
912 | return mainpositionTV(t, key); | 916 | return mainpositionTV(t, key); |
913 | } | 917 | } |
diff --git a/testes/code.lua b/testes/code.lua index ab531fa8..e12f3f91 100644 --- a/testes/code.lua +++ b/testes/code.lua | |||
@@ -306,8 +306,10 @@ checkR(function (x) return x // 1 end, 10.0, 10.0, | |||
306 | checkR(function (x) return x % (100 - 10) end, 91, 1, | 306 | checkR(function (x) return x % (100 - 10) end, 91, 1, |
307 | 'MODK', 'MMBINK', 'RETURN1') | 307 | 'MODK', 'MMBINK', 'RETURN1') |
308 | checkR(function (x) return k1 << x end, 3, 8, 'SHLI', 'MMBINI', 'RETURN1') | 308 | checkR(function (x) return k1 << x end, 3, 8, 'SHLI', 'MMBINI', 'RETURN1') |
309 | checkR(function (x) return x << 2 end, 10, 40, 'SHRI', 'MMBINI', 'RETURN1') | 309 | checkR(function (x) return x << 127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1') |
310 | checkR(function (x) return x >> 2 end, 8, 2, 'SHRI', 'MMBINI', 'RETURN1') | 310 | checkR(function (x) return x << -127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1') |
311 | checkR(function (x) return x >> 128 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1') | ||
312 | checkR(function (x) return x >> -127 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1') | ||
311 | checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'MMBINK', 'RETURN1') | 313 | checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'MMBINK', 'RETURN1') |
312 | checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'MMBINK', 'RETURN1') | 314 | checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'MMBINK', 'RETURN1') |
313 | checkR(function (x) return -10 ~ x end, -1, 9, 'BXORK', 'MMBINK', 'RETURN1') | 315 | checkR(function (x) return -10 ~ x end, -1, 9, 'BXORK', 'MMBINK', 'RETURN1') |
@@ -331,6 +333,7 @@ check(function () return k3/0 end, 'LOADI', 'DIVK', 'MMBINK', 'RETURN1') | |||
331 | check(function () return 0%0 end, 'LOADI', 'MODK', 'MMBINK', 'RETURN1') | 333 | check(function () return 0%0 end, 'LOADI', 'MODK', 'MMBINK', 'RETURN1') |
332 | check(function () return -4//0 end, 'LOADI', 'IDIVK', 'MMBINK', 'RETURN1') | 334 | check(function () return -4//0 end, 'LOADI', 'IDIVK', 'MMBINK', 'RETURN1') |
333 | check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'MMBIN', 'RETURN1') | 335 | check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'MMBIN', 'RETURN1') |
336 | check(function (x) return x << 128 end, 'LOADI', 'SHL', 'MMBIN', 'RETURN1') | ||
334 | check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'MMBIN', 'RETURN1') | 337 | check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'MMBIN', 'RETURN1') |
335 | 338 | ||
336 | -- basic 'for' loops | 339 | -- basic 'for' loops |