summaryrefslogtreecommitdiff
path: root/lcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcode.c')
-rw-r--r--lcode.c91
1 files changed, 53 insertions, 38 deletions
diff --git a/lcode.c b/lcode.c
index 8f9fa408..d1585193 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.138 2017/11/28 15:26:15 roberto Exp roberto $ 2** $Id: lcode.c,v 2.140 2017/11/30 13:17:06 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*/
@@ -134,17 +134,10 @@ void luaK_concat (FuncState *fs, int *l1, int l2) {
134 134
135/* 135/*
136** Create a jump instruction and return its position, so its destination 136** Create a jump instruction and return its position, so its destination
137** can be fixed later (with 'fixjump'). If there are jumps to 137** can be fixed later (with 'fixjump').
138** this position (kept in 'jpc'), link them all together so that
139** 'patchlistaux' will fix all them directly to the final destination.
140*/ 138*/
141int luaK_jump (FuncState *fs) { 139int luaK_jump (FuncState *fs) {
142 int jpc = fs->jpc; /* save list of jumps to here */ 140 return codesJ(fs, OP_JMP, NO_JUMP, 0);
143 int j;
144 fs->jpc = NO_JUMP; /* no more jumps to here */
145 j = codesJ(fs, OP_JMP, NO_JUMP, 0);
146 luaK_concat(fs, &j, jpc); /* keep them on hold */
147 return j;
148} 141}
149 142
150 143
@@ -250,38 +243,19 @@ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
250 243
251 244
252/* 245/*
253** Ensure all pending jumps to current position are fixed (jumping
254** to current position with no values) and reset list of pending
255** jumps
256*/
257static void dischargejpc (FuncState *fs) {
258 patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
259 fs->jpc = NO_JUMP;
260}
261
262
263/*
264** Add elements in 'list' to list of pending jumps to "here"
265** (current position)
266*/
267void luaK_patchtohere (FuncState *fs, int list) {
268 luaK_getlabel(fs); /* mark "here" as a jump target */
269 luaK_concat(fs, &fs->jpc, list);
270}
271
272
273/*
274** Path all jumps in 'list' to jump to 'target'. 246** Path all jumps in 'list' to jump to 'target'.
275** (The assert means that we cannot fix a jump to a forward address 247** (The assert means that we cannot fix a jump to a forward address
276** because we only know addresses once code is generated.) 248** because we only know addresses once code is generated.)
277*/ 249*/
278void luaK_patchlist (FuncState *fs, int list, int target) { 250void luaK_patchlist (FuncState *fs, int list, int target) {
279 if (target == fs->pc) /* 'target' is current position? */ 251 lua_assert(target <= fs->pc);
280 luaK_patchtohere(fs, list); /* add list to pending jumps */ 252 patchlistaux(fs, list, target, NO_REG, target);
281 else { 253}
282 lua_assert(target < fs->pc); 254
283 patchlistaux(fs, list, target, NO_REG, target); 255
284 } 256void luaK_patchtohere (FuncState *fs, int list) {
257 int hr = luaK_getlabel(fs); /* mark "here" as a jump target */
258 luaK_patchlist(fs, list, hr);
285} 259}
286 260
287 261
@@ -365,7 +339,6 @@ static void savelineinfo (FuncState *fs, Proto *f, int pc, int line) {
365*/ 339*/
366static int luaK_code (FuncState *fs, Instruction i) { 340static int luaK_code (FuncState *fs, Instruction i) {
367 Proto *f = fs->f; 341 Proto *f = fs->f;
368 dischargejpc(fs); /* 'pc' will change */
369 /* put new instruction in code array */ 342 /* put new instruction in code array */
370 luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, 343 luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
371 MAX_INT, "opcodes"); 344 MAX_INT, "opcodes");
@@ -1537,3 +1510,45 @@ void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
1537 fs->freereg = base + 1; /* free registers with list values */ 1510 fs->freereg = base + 1; /* free registers with list values */
1538} 1511}
1539 1512
1513
1514/*
1515** return the final target of a jump (skipping jumps to jumps)
1516*/
1517static int finaltarget (Instruction *code, int i) {
1518 int count;
1519 for (count = 0; count < 100; count++) { /* avoid infinite loops */
1520 Instruction pc = code[i];
1521 if (GET_OPCODE(pc) != OP_JMP)
1522 break;
1523 else
1524 i += GETARG_sJ(pc) + 1;
1525 }
1526 return i;
1527}
1528
1529
1530/*
1531** Do a final pass over the code of a function, doing small peephole
1532** optimizations and adjustments.
1533*/
1534void luaK_finish (FuncState *fs) {
1535 int i;
1536 Proto *p = fs->f;
1537 for (i = 0; i < fs->pc; i++) {
1538 Instruction *pc = &p->code[i];
1539 switch (GET_OPCODE(*pc)) {
1540 case OP_RETURN: case OP_RETURN0: case OP_RETURN1:
1541 case OP_TAILCALL: {
1542 if (p->sizep > 0)
1543 SETARG_k(*pc, 1); /* signal that they must close upvalues */
1544 break;
1545 }
1546 case OP_JMP: {
1547 int target = finaltarget(p->code, i);
1548 fixjump(fs, i, target);
1549 break;
1550 }
1551 default: break;
1552 }
1553 }
1554}