| 529 | |
| 530 | |
| 531 | static const char *getobjname (const Proto *p, int lastpc, int reg, |
| 532 | const char **name) { |
| 533 | int pc; |
| 534 | *name = luaF_getlocalname(p, reg + 1, lastpc); |
| 535 | if (*name) /* is a local? */ |
| 536 | return "local"; |
| 537 | /* else try symbolic execution */ |
| 538 | pc = findsetreg(p, lastpc, reg); |
| 539 | if (pc != -1) { /* could find instruction? */ |
| 540 | Instruction i = p->code[pc]; |
| 541 | OpCode op = GET_OPCODE(i); |
| 542 | switch (op) { |
| 543 | case OP_MOVE: { |
| 544 | int b = GETARG_B(i); /* move from 'b' to 'a' */ |
| 545 | if (b < GETARG_A(i)) |
| 546 | return getobjname(p, pc, b, name); /* get name for 'b' */ |
| 547 | break; |
| 548 | } |
| 549 | case OP_GETTABUP: { |
| 550 | int k = GETARG_C(i); /* key index */ |
| 551 | kname(p, k, name); |
| 552 | return gxf(p, pc, i, 1); |
| 553 | } |
| 554 | case OP_GETTABLE: { |
| 555 | int k = GETARG_C(i); /* key index */ |
| 556 | rname(p, pc, k, name); |
| 557 | return gxf(p, pc, i, 0); |
| 558 | } |
| 559 | case OP_GETI: { |
| 560 | *name = "integer index"; |
| 561 | return "field"; |
| 562 | } |
| 563 | case OP_GETFIELD: { |
| 564 | int k = GETARG_C(i); /* key index */ |
| 565 | kname(p, k, name); |
| 566 | return gxf(p, pc, i, 0); |
| 567 | } |
| 568 | case OP_GETUPVAL: { |
| 569 | *name = upvalname(p, GETARG_B(i)); |
| 570 | return "upvalue"; |
| 571 | } |
| 572 | case OP_LOADK: |
| 573 | case OP_LOADKX: { |
| 574 | int b = (op == OP_LOADK) ? GETARG_Bx(i) |
| 575 | : GETARG_Ax(p->code[pc + 1]); |
| 576 | if (ttisstring(&p->k[b])) { |
| 577 | *name = svalue(&p->k[b]); |
| 578 | return "constant"; |
| 579 | } |
| 580 | break; |
| 581 | } |
| 582 | case OP_SELF: { |
| 583 | rkname(p, pc, i, name); |
| 584 | return "method"; |
| 585 | } |
| 586 | default: break; /* go through to return NULL */ |
| 587 | } |
| 588 | } |
no test coverage detected