diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-11 12:53:23 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-11 12:53:23 -0300 |
| commit | 4d5de1c1fb2decb39d74dfb092ca5643ce47176f (patch) | |
| tree | 6d211899db43994b5d421a8a7e59dcb2ecccc0db /lcode.c | |
| parent | 9a825f6bb9a141023ac519a73f6a9958c113659e (diff) | |
| download | lua-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.
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 | ||
