diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 76 |
1 files changed, 53 insertions, 23 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.160 2018/03/16 14:22:09 roberto Exp roberto $ | 2 | ** $Id: lcode.c $ |
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 | */ |
@@ -309,10 +309,19 @@ void luaK_patchclose (FuncState *fs, int list) { | |||
309 | } | 309 | } |
310 | 310 | ||
311 | 311 | ||
312 | /* | ||
313 | ** MAXimum number of successive Instructions WiTHout ABSolute line | ||
314 | ** information. | ||
315 | */ | ||
312 | #if !defined(MAXIWTHABS) | 316 | #if !defined(MAXIWTHABS) |
313 | #define MAXIWTHABS 120 | 317 | #define MAXIWTHABS 120 |
314 | #endif | 318 | #endif |
315 | 319 | ||
320 | |||
321 | /* limit for difference between lines in relative line info. */ | ||
322 | #define LIMLINEDIFF 0x80 | ||
323 | |||
324 | |||
316 | /* | 325 | /* |
317 | ** Save line info for a new instruction. If difference from last line | 326 | ** Save line info for a new instruction. If difference from last line |
318 | ** does not fit in a byte, of after that many instructions, save a new | 327 | ** does not fit in a byte, of after that many instructions, save a new |
@@ -320,14 +329,15 @@ void luaK_patchclose (FuncState *fs, int list) { | |||
320 | ** in 'lineinfo' signals the existence of this absolute information.) | 329 | ** in 'lineinfo' signals the existence of this absolute information.) |
321 | ** Otherwise, store the difference from last line in 'lineinfo'. | 330 | ** Otherwise, store the difference from last line in 'lineinfo'. |
322 | */ | 331 | */ |
323 | static void savelineinfo (FuncState *fs, Proto *f, int pc, int line) { | 332 | static void savelineinfo (FuncState *fs, Proto *f, int line) { |
324 | int linedif = line - fs->previousline; | 333 | int linedif = line - fs->previousline; |
325 | if (abs(linedif) >= 0x80 || fs->iwthabs++ > MAXIWTHABS) { | 334 | int pc = fs->pc - 1; /* last instruction coded */ |
335 | if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ > MAXIWTHABS) { | ||
326 | luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo, | 336 | luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo, |
327 | f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines"); | 337 | f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines"); |
328 | f->abslineinfo[fs->nabslineinfo].pc = pc; | 338 | f->abslineinfo[fs->nabslineinfo].pc = pc; |
329 | f->abslineinfo[fs->nabslineinfo++].line = line; | 339 | f->abslineinfo[fs->nabslineinfo++].line = line; |
330 | linedif = ABSLINEINFO; /* signal there is absolute information */ | 340 | linedif = ABSLINEINFO; /* signal that there is absolute information */ |
331 | fs->iwthabs = 0; /* restart counter */ | 341 | fs->iwthabs = 0; /* restart counter */ |
332 | } | 342 | } |
333 | luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte, | 343 | luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte, |
@@ -338,6 +348,37 @@ static void savelineinfo (FuncState *fs, Proto *f, int pc, int line) { | |||
338 | 348 | ||
339 | 349 | ||
340 | /* | 350 | /* |
351 | ** Remove line information from the last instruction. | ||
352 | ** If line information for that instruction is absolute, set 'iwthabs' | ||
353 | ** above its max to force the new (replacing) instruction to have | ||
354 | ** absolute line info, too. | ||
355 | */ | ||
356 | static void removelastlineinfo (FuncState *fs) { | ||
357 | Proto *f = fs->f; | ||
358 | int pc = fs->pc - 1; /* last instruction coded */ | ||
359 | if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ | ||
360 | fs->previousline -= f->lineinfo[pc]; /* last line saved */ | ||
361 | fs->iwthabs--; | ||
362 | } | ||
363 | else { /* absolute line information */ | ||
364 | fs->nabslineinfo--; /* remove it */ | ||
365 | lua_assert(f->abslineinfo[fs->nabslineinfo].pc = pc); | ||
366 | fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ | ||
367 | } | ||
368 | } | ||
369 | |||
370 | |||
371 | /* | ||
372 | ** Remove the last instruction created, correcting line information | ||
373 | ** accordingly. | ||
374 | */ | ||
375 | static void removelastinstruction (FuncState *fs) { | ||
376 | removelastlineinfo(fs); | ||
377 | fs->pc--; | ||
378 | } | ||
379 | |||
380 | |||
381 | /* | ||
341 | ** Emit instruction 'i', checking for array sizes and saving also its | 382 | ** Emit instruction 'i', checking for array sizes and saving also its |
342 | ** line information. Return 'i' position. | 383 | ** line information. Return 'i' position. |
343 | */ | 384 | */ |
@@ -346,9 +387,9 @@ static int luaK_code (FuncState *fs, Instruction i) { | |||
346 | /* put new instruction in code array */ | 387 | /* put new instruction in code array */ |
347 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, | 388 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, |
348 | MAX_INT, "opcodes"); | 389 | MAX_INT, "opcodes"); |
349 | f->code[fs->pc] = i; | 390 | f->code[fs->pc++] = i; |
350 | savelineinfo(fs, f, fs->pc, fs->ls->lastline); | 391 | savelineinfo(fs, f, fs->ls->lastline); |
351 | return fs->pc++; | 392 | return fs->pc - 1; /* index of new instruction */ |
352 | } | 393 | } |
353 | 394 | ||
354 | 395 | ||
@@ -986,7 +1027,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
986 | if (e->k == VRELOC) { | 1027 | if (e->k == VRELOC) { |
987 | Instruction ie = getinstruction(fs, e); | 1028 | Instruction ie = getinstruction(fs, e); |
988 | if (GET_OPCODE(ie) == OP_NOT) { | 1029 | if (GET_OPCODE(ie) == OP_NOT) { |
989 | fs->pc--; /* remove previous OP_NOT */ | 1030 | removelastinstruction(fs); /* remove previous OP_NOT */ |
990 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); | 1031 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); |
991 | } | 1032 | } |
992 | /* else go through */ | 1033 | /* else go through */ |
@@ -1572,23 +1613,12 @@ void luaK_posfix (FuncState *fs, BinOpr opr, | |||
1572 | 1613 | ||
1573 | 1614 | ||
1574 | /* | 1615 | /* |
1575 | ** Change line information associated with current position. If that | 1616 | ** Change line information associated with current position, by removing |
1576 | ** information is absolute, just change it and correct 'previousline'. | 1617 | ** previous info and adding it again with new line. |
1577 | ** Otherwise, restore 'previousline' to its value before saving the | ||
1578 | ** current position and than saves the line information again, with the | ||
1579 | ** new line. | ||
1580 | */ | 1618 | */ |
1581 | void luaK_fixline (FuncState *fs, int line) { | 1619 | void luaK_fixline (FuncState *fs, int line) { |
1582 | Proto *f = fs->f; | 1620 | removelastlineinfo(fs); |
1583 | if (f->lineinfo[fs->pc - 1] == ABSLINEINFO) { | 1621 | savelineinfo(fs, fs->f, line); |
1584 | lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == fs->pc - 1); | ||
1585 | f->abslineinfo[fs->nabslineinfo - 1].line = line; | ||
1586 | fs->previousline = line; | ||
1587 | } | ||
1588 | else { | ||
1589 | fs->previousline -= f->lineinfo[fs->pc - 1]; /* undo previous info. */ | ||
1590 | savelineinfo(fs, f, fs->pc - 1, line); /* redo it */ | ||
1591 | } | ||
1592 | } | 1622 | } |
1593 | 1623 | ||
1594 | 1624 | ||