diff options
Diffstat (limited to 'lcode.c')
| -rw-r--r-- | lcode.c | 57 |
1 files changed, 37 insertions, 20 deletions
| @@ -842,6 +842,12 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
| 842 | e->k = VRELOC; | 842 | e->k = VRELOC; |
| 843 | break; | 843 | break; |
| 844 | } | 844 | } |
| 845 | case VVARGIND: { | ||
| 846 | freeregs(fs, e->u.ind.t, e->u.ind.idx); | ||
| 847 | e->u.info = luaK_codeABC(fs, OP_GETVARG, 0, e->u.ind.t, e->u.ind.idx); | ||
| 848 | e->k = VRELOC; | ||
| 849 | break; | ||
| 850 | } | ||
| 845 | case VVARARG: case VCALL: { | 851 | case VVARARG: case VCALL: { |
| 846 | luaK_setoneret(fs, e); | 852 | luaK_setoneret(fs, e); |
| 847 | break; | 853 | break; |
| @@ -1004,11 +1010,11 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | |||
| 1004 | 1010 | ||
| 1005 | 1011 | ||
| 1006 | /* | 1012 | /* |
| 1007 | ** Ensures final expression result is either in a register | 1013 | ** Ensures final expression result is either in a register, |
| 1008 | ** or in an upvalue. | 1014 | ** in an upvalue, or it is the vararg parameter. |
| 1009 | */ | 1015 | */ |
| 1010 | void luaK_exp2anyregup (FuncState *fs, expdesc *e) { | 1016 | void luaK_exp2anyregup (FuncState *fs, expdesc *e) { |
| 1011 | if (e->k != VUPVAL || hasjumps(e)) | 1017 | if ((e->k != VUPVAL && e->k != VVARGVAR) || hasjumps(e)) |
| 1012 | luaK_exp2anyreg(fs, e); | 1018 | luaK_exp2anyreg(fs, e); |
| 1013 | } | 1019 | } |
| 1014 | 1020 | ||
| @@ -1314,6 +1320,13 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | |||
| 1314 | } | 1320 | } |
| 1315 | 1321 | ||
| 1316 | 1322 | ||
| 1323 | /* auxiliary function to define indexing expressions */ | ||
| 1324 | static void fillidxk (expdesc *t, int idx, expkind k) { | ||
| 1325 | t->u.ind.idx = cast_byte(idx); | ||
| 1326 | t->k = k; | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | |||
| 1317 | /* | 1330 | /* |
| 1318 | ** Create expression 't[k]'. 't' must have its final result already in a | 1331 | ** Create expression 't[k]'. 't' must have its final result already in a |
| 1319 | ** register or upvalue. Upvalues can only be indexed by literal strings. | 1332 | ** register or upvalue. Upvalues can only be indexed by literal strings. |
| @@ -1325,31 +1338,30 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | |||
| 1325 | if (k->k == VKSTR) | 1338 | if (k->k == VKSTR) |
| 1326 | keystr = str2K(fs, k); | 1339 | keystr = str2K(fs, k); |
| 1327 | lua_assert(!hasjumps(t) && | 1340 | lua_assert(!hasjumps(t) && |
| 1328 | (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); | 1341 | (t->k == VLOCAL || t->k == VVARGVAR || |
| 1342 | t->k == VNONRELOC || t->k == VUPVAL)); | ||
| 1329 | if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ | 1343 | if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ |
| 1330 | luaK_exp2anyreg(fs, t); /* put it in a register */ | 1344 | luaK_exp2anyreg(fs, t); /* put it in a register */ |
| 1331 | if (t->k == VUPVAL) { | 1345 | if (t->k == VUPVAL) { |
| 1332 | lu_byte temp = cast_byte(t->u.info); /* upvalue index */ | 1346 | lu_byte temp = cast_byte(t->u.info); /* upvalue index */ |
| 1333 | t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */ | 1347 | t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */ |
| 1334 | lua_assert(isKstr(fs, k)); | 1348 | lua_assert(isKstr(fs, k)); |
| 1335 | t->u.ind.idx = cast_short(k->u.info); /* literal short string */ | 1349 | fillidxk(t, k->u.info, VINDEXUP); /* literal short string */ |
| 1336 | t->k = VINDEXUP; | 1350 | } |
| 1351 | else if (t->k == VVARGVAR) { /* indexing the vararg parameter? */ | ||
| 1352 | lua_assert(t->u.ind.t == fs->f->numparams); | ||
| 1353 | t->u.ind.t = cast_byte(t->u.var.ridx); | ||
| 1354 | fillidxk(t, luaK_exp2anyreg(fs, k), VVARGIND); /* register */ | ||
| 1337 | } | 1355 | } |
| 1338 | else { | 1356 | else { |
| 1339 | /* register index of the table */ | 1357 | /* register index of the table */ |
| 1340 | t->u.ind.t = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info); | 1358 | t->u.ind.t = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info); |
| 1341 | if (isKstr(fs, k)) { | 1359 | if (isKstr(fs, k)) |
| 1342 | t->u.ind.idx = cast_short(k->u.info); /* literal short string */ | 1360 | fillidxk(t, k->u.info, VINDEXSTR); /* literal short string */ |
| 1343 | t->k = VINDEXSTR; | 1361 | else if (isCint(k)) /* int. constant in proper range? */ |
| 1344 | } | 1362 | fillidxk(t, cast_int(k->u.ival), VINDEXI); |
| 1345 | else if (isCint(k)) { /* int. constant in proper range? */ | 1363 | else |
| 1346 | t->u.ind.idx = cast_short(k->u.ival); | 1364 | fillidxk(t, luaK_exp2anyreg(fs, k), VINDEXED); /* register */ |
| 1347 | t->k = VINDEXI; | ||
| 1348 | } | ||
| 1349 | else { | ||
| 1350 | t->u.ind.idx = cast_short(luaK_exp2anyreg(fs, k)); /* register */ | ||
| 1351 | t->k = VINDEXED; | ||
| 1352 | } | ||
| 1353 | } | 1365 | } |
| 1354 | t->u.ind.keystr = keystr; /* string index in 'k' */ | 1366 | t->u.ind.keystr = keystr; /* string index in 'k' */ |
| 1355 | t->u.ind.ro = 0; /* by default, not read-only */ | 1367 | t->u.ind.ro = 0; /* by default, not read-only */ |
| @@ -1913,9 +1925,14 @@ void luaK_finish (FuncState *fs) { | |||
| 1913 | SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ | 1925 | SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ |
| 1914 | break; | 1926 | break; |
| 1915 | } | 1927 | } |
| 1916 | case OP_JMP: { | 1928 | case OP_GETVARG: { |
| 1929 | if (p->flag & PF_VATAB) /* function has a vararg table? */ | ||
| 1930 | SET_OPCODE(*pc, OP_GETTABLE); /* must get vararg there */ | ||
| 1931 | break; | ||
| 1932 | } | ||
| 1933 | case OP_JMP: { /* to optimize jumps to jumps */ | ||
| 1917 | int target = finaltarget(p->code, i); | 1934 | int target = finaltarget(p->code, i); |
| 1918 | fixjump(fs, i, target); | 1935 | fixjump(fs, i, target); /* jump directly to final target */ |
| 1919 | break; | 1936 | break; |
| 1920 | } | 1937 | } |
| 1921 | default: break; | 1938 | default: break; |
