aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-07-11 12:53:23 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-07-11 12:53:23 -0300
commit4d5de1c1fb2decb39d74dfb092ca5643ce47176f (patch)
tree6d211899db43994b5d421a8a7e59dcb2ecccc0db
parent9a825f6bb9a141023ac519a73f6a9958c113659e (diff)
downloadlua-4d5de1c1fb2decb39d74dfb092ca5643ce47176f.tar.gz
lua-4d5de1c1fb2decb39d74dfb092ca5643ce47176f.tar.bz2
lua-4d5de1c1fb2decb39d74dfb092ca5643ce47176f.zip
Fixed bug in line info. when using 'not' operator
When creating code for a jump on a 'not' condition, the code generator was removing an instruction (the OP_NOT) without adjusting its corresponding line information. This fix also added tests for this case and extra functionality in the test library to debug line info. structures.
-rw-r--r--lcode.c76
-rw-r--r--ltests.c22
-rw-r--r--testes/errors.lua21
3 files changed, 93 insertions, 26 deletions
diff --git a/lcode.c b/lcode.c
index ab91561c..d00038dd 100644
--- a/lcode.c
+++ b/lcode.c
@@ -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*/
323static void savelineinfo (FuncState *fs, Proto *f, int pc, int line) { 332static 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*/
356static 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*/
375static 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*/
1581void luaK_fixline (FuncState *fs, int line) { 1619void 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
diff --git a/ltests.c b/ltests.c
index ac548a95..13717da9 100644
--- a/ltests.c
+++ b/ltests.c
@@ -526,7 +526,8 @@ static char *buildop (Proto *p, int pc, char *buff) {
526 OpCode o = GET_OPCODE(i); 526 OpCode o = GET_OPCODE(i);
527 const char *name = opnames[o]; 527 const char *name = opnames[o];
528 int line = luaG_getfuncline(p, pc); 528 int line = luaG_getfuncline(p, pc);
529 sprintf(buff, "(%4d) %4d - ", line, pc); 529 int lineinfo = (p->lineinfo != NULL) ? p->lineinfo[pc] : 0;
530 sprintf(buff, "(%2d - %4d) %4d - ", lineinfo, line, pc);
530 switch (getOpMode(o)) { 531 switch (getOpMode(o)) {
531 case iABC: 532 case iABC:
532 sprintf(buff+strlen(buff), "%-12s%4d %4d %4d%s", name, 533 sprintf(buff+strlen(buff), "%-12s%4d %4d %4d%s", name,
@@ -621,6 +622,24 @@ static int listk (lua_State *L) {
621} 622}
622 623
623 624
625static int listabslineinfo (lua_State *L) {
626 Proto *p;
627 int i;
628 luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
629 1, "Lua function expected");
630 p = getproto(obj_at(L, 1));
631 luaL_argcheck(L, p->abslineinfo != NULL, 1, "function has no debug info");
632 lua_createtable(L, 2 * p->sizeabslineinfo, 0);
633 for (i=0; i < p->sizeabslineinfo; i++) {
634 lua_pushinteger(L, p->abslineinfo[i].pc);
635 lua_rawseti(L, -2, 2 * i + 1);
636 lua_pushinteger(L, p->abslineinfo[i].line);
637 lua_rawseti(L, -2, 2 * i + 2);
638 }
639 return 1;
640}
641
642
624static int listlocals (lua_State *L) { 643static int listlocals (lua_State *L) {
625 Proto *p; 644 Proto *p;
626 int pc = cast_int(luaL_checkinteger(L, 2)) - 1; 645 int pc = cast_int(luaL_checkinteger(L, 2)) - 1;
@@ -1682,6 +1701,7 @@ static const struct luaL_Reg tests_funcs[] = {
1682 {"listcode", listcode}, 1701 {"listcode", listcode},
1683 {"printcode", printcode}, 1702 {"printcode", printcode},
1684 {"listk", listk}, 1703 {"listk", listk},
1704 {"listabslineinfo", listabslineinfo},
1685 {"listlocals", listlocals}, 1705 {"listlocals", listlocals},
1686 {"loadlib", loadlib}, 1706 {"loadlib", loadlib},
1687 {"checkpanic", checkpanic}, 1707 {"checkpanic", checkpanic},
diff --git a/testes/errors.lua b/testes/errors.lua
index 63a7b740..19a7b6fa 100644
--- a/testes/errors.lua
+++ b/testes/errors.lua
@@ -1,4 +1,4 @@
1-- $Id: errors.lua,v 1.97 2017/11/28 15:31:56 roberto Exp $ 1-- $Id: errors.lua $
2-- See Copyright Notice in file all.lua 2-- See Copyright Notice in file all.lua
3 3
4print("testing errors") 4print("testing errors")
@@ -299,7 +299,7 @@ end
299local function lineerror (s, l) 299local function lineerror (s, l)
300 local err,msg = pcall(load(s)) 300 local err,msg = pcall(load(s))
301 local line = string.match(msg, ":(%d+):") 301 local line = string.match(msg, ":(%d+):")
302 assert((line and line+0) == l) 302 assert(tonumber(line) == l)
303end 303end
304 304
305lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2) 305lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2)
@@ -350,6 +350,23 @@ X=1;lineerror((p), 2)
350X=2;lineerror((p), 1) 350X=2;lineerror((p), 1)
351 351
352 352
353lineerror([[
354local b = false
355if not b then
356 error 'test'
357end]], 3)
358
359lineerror([[
360local b = false
361if not b then
362 if not b then
363 if not b then
364 error 'test'
365 end
366 end
367end]], 5)
368
369
353if not _soft then 370if not _soft then
354 -- several tests that exaust the Lua stack 371 -- several tests that exaust the Lua stack
355 collectgarbage() 372 collectgarbage()