** try to find last instruction before 'lastpc' that modified register 'reg' */
| 352 | ** try to find last instruction before 'lastpc' that modified register 'reg' |
| 353 | */ |
| 354 | static int findsetreg (Proto *p, int lastpc, int reg) { |
| 355 | int pc; |
| 356 | int setreg = -1; /* keep last instruction that changed 'reg' */ |
| 357 | int jmptarget = 0; /* any code before this address is conditional */ |
| 358 | for (pc = 0; pc < lastpc; pc++) { |
| 359 | Instruction i = p->code[pc]; |
| 360 | OpCode op = GET_OPCODE(i); |
| 361 | int a = GETARG_A(i); |
| 362 | switch (op) { |
| 363 | case OP_LOADNIL: { |
| 364 | int b = GETARG_B(i); |
| 365 | if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ |
| 366 | setreg = filterpc(pc, jmptarget); |
| 367 | break; |
| 368 | } |
| 369 | case OP_TFORCALL: { |
| 370 | if (reg >= a + 2) /* affect all regs above its base */ |
| 371 | setreg = filterpc(pc, jmptarget); |
| 372 | break; |
| 373 | } |
| 374 | case OP_CALL: |
| 375 | case OP_TAILCALL: { |
| 376 | if (reg >= a) /* affect all registers above base */ |
| 377 | setreg = filterpc(pc, jmptarget); |
| 378 | break; |
| 379 | } |
| 380 | case OP_JMP: { |
| 381 | int b = GETARG_sBx(i); |
| 382 | int dest = pc + 1 + b; |
| 383 | /* jump is forward and do not skip `lastpc'? */ |
| 384 | if (pc < dest && dest <= lastpc) { |
| 385 | if (dest > jmptarget) |
| 386 | jmptarget = dest; /* update 'jmptarget' */ |
| 387 | } |
| 388 | break; |
| 389 | } |
| 390 | case OP_TEST: { |
| 391 | if (reg == a) /* jumped code can change 'a' */ |
| 392 | setreg = filterpc(pc, jmptarget); |
| 393 | break; |
| 394 | } |
| 395 | default: |
| 396 | if (testAMode(op) && reg == a) /* any instruction that set A */ |
| 397 | setreg = filterpc(pc, jmptarget); |
| 398 | break; |
| 399 | } |
| 400 | } |
| 401 | return setreg; |
| 402 | } |
| 403 | |
| 404 | |
| 405 | static const char *getobjname (Proto *p, int lastpc, int reg, |
no test coverage detected