const char* raviP_instruction_to_str(char *buf, size_t n, Instruction i) { OpCode o = GET_OPCODE(i); int a = GETARG_A(i); int b = GETARG_B(i); int c = GETARG_C(i); int ax = GETARG_Ax(i); int bx = GETARG_Bx(i); int sbx = GETARG_sBx(i); snprintf(buf, n, "%s ", luaP_opnames[o]); switch (getOpMode(o)) { case iABC: snprintf(buf+strlen(buf), n-strlen(buf), "A=%d", a); if (getBMode(o) != OpArgN) snprintf(buf + strlen(buf), n - strlen(buf), " B=%d", (getBMode(o) == OpArgK && ISK(b)) ? (MYK(INDEXK(b))) : b); if (getCMode(o) != OpArgN) snprintf(buf + strlen(buf), n - strlen(buf), " C=%d", (getCMode(o) == OpArgK && ISK(c)) ? (MYK(INDEXK(c))) : c); break; case iABx: snprintf(buf + strlen(buf), n - strlen(buf), "A=%d", a); if (getBMode(o) == OpArgK) snprintf(buf + strlen(buf), n - strlen(buf), " Bx=%d", MYK(bx)); if (getBMode(o) == OpArgU) snprintf(buf + strlen(buf), n - strlen(buf), " Bx=%d", bx); break; case iAsBx: snprintf(buf + strlen(buf), n - strlen(buf), "As=%d Bx=%d", a, sbx); break; case iAx: snprintf(buf + strlen(buf), n - strlen(buf), "Ax=%d", MYK(ax)); break; } return buf; }
/* ** Format and emit an 'iABC' instruction. (Assertions check consistency ** of parameters versus opcode.) */ int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { lua_assert(getOpMode(o) == iABC); lua_assert(getBMode(o) != OpArgN || b == 0); lua_assert(getCMode(o) != OpArgN || c == 0); lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); return luaK_code(fs, CREATE_ABC(o, a, b, c)); }
int codegen_codeABx(FuncState *fs, OpCode o, int a, unsigned int bc) { ktap_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); ktap_assert(getCMode(o) == OpArgN); ktap_assert(a <= MAXARG_A && bc <= MAXARG_Bx); return codegen_code(fs, CREATE_ABx(o, a, bc)); }
static int do_getinstruction(lua_State *L) /** getinstruction(f,i) */ { const Proto* f=Pget(L,1); int pc=luaL_checkinteger(L,2); if (pc<=0 || pc>f->sizecode || f->code==NULL) return 0; pc--; { const Instruction* code=f->code; Instruction i=code[pc]; OpCode o=GET_OPCODE(i); int a=GETARG_A(i); int b=GETARG_B(i); int c=GETARG_C(i); int ax=GETARG_Ax(i); int bx=GETARG_Bx(i); int sbx=GETARG_sBx(i); int line=getfuncline(f,pc); if (line>0) lua_pushinteger(L,line); else lua_pushnil(L); lua_pushstring(L,luaP_opnames[o]); switch (getOpMode(o)) { case iABC: lua_pushinteger(L,a); if (getBMode(o)!=OpArgN) lua_pushinteger(L,ISK(b) ? (MYK(INDEXK(b))) : b); else lua_pushnil(L); if (getCMode(o)!=OpArgN) lua_pushinteger(L,ISK(c) ? (MYK(INDEXK(c))) : c); else lua_pushnil(L); break; case iABx: lua_pushinteger(L,a); if (getBMode(o)==OpArgK) lua_pushinteger(L,MYK(bx)); else lua_pushinteger(L,bx); lua_pushnil(L); break; case iAsBx: lua_pushinteger(L,a); lua_pushinteger(L,sbx); lua_pushnil(L); break; case iAx: lua_pushinteger(L,MYK(ax)); lua_pushnil(L); lua_pushnil(L); break; } switch (o) { case OP_JMP: case OP_FORLOOP: case OP_FORPREP: case OP_TFORLOOP: lua_pop(L,1); lua_pushinteger(L,sbx+pc+2); break; default: break; } } return 5; }
/* local op, a, b, c, test = jit.util.bytecode(func, pc) */ static int ju_bytecode(lua_State *L) { Proto *pt = check_LCL(L)->l.p; int pc = luaL_checkint(L, 2); if (pc >= 1 && pc <= pt->sizecode) { Instruction ins = pt->code[pc-1]; OpCode op = GET_OPCODE(ins); if (pc > 1 && (((int)OP_SETLIST) << POS_OP) == (pt->code[pc-2] & (MASK1(SIZE_OP,POS_OP) | MASK1(SIZE_C,POS_C)))) { lua_pushstring(L, luaP_opnames[OP_SETLIST]); lua_pushnumber(L, (lua_Number)ins); /* Fake extended op. */ return 1; } if (op >= NUM_OPCODES) return 0; /* Just in case. */ lua_pushstring(L, luaP_opnames[op]); lua_pushinteger(L, GETARG_A(ins)); switch (getOpMode(op)) { case iABC: { int b = GETARG_B(ins), c = GETARG_C(ins); switch (getBMode(op)) { case OpArgN: lua_pushnil(L); break; case OpArgK: if (ISK(b)) b = -1-INDEXK(b); case OpArgR: case OpArgU: lua_pushinteger(L, b); break; } switch (getCMode(op)) { case OpArgN: lua_pushnil(L); break; case OpArgK: if (ISK(c)) c = -1-INDEXK(c); case OpArgR: case OpArgU: lua_pushinteger(L, c); break; } lua_pushboolean(L, testTMode(op)); return 5; } case iABx: { int bx = GETARG_Bx(ins); lua_pushinteger(L, getBMode(op) == OpArgK ? -1-bx : bx); return 3; } case iAsBx: lua_pushinteger(L, GETARG_sBx(ins)); return 3; } } return 0; }
static void PrintCode(const Proto* f) { const Instruction* code=f->code; int pc,n=f->sizecode; for (pc=0; pc<n; pc++) { Instruction i=code[pc]; OpCode o=GET_OPCODE(i); int a=GETARG_A(i); int b=GETARG_B(i); int c=GETARG_C(i); int ax=GETARG_Ax(i); int bx=GETARG_Bx(i); int sbx=GETARG_sBx(i); int line=getfuncline(f,pc); printf("\t%d\t",pc+1); if (line>0) printf("[%d]\t",line); else printf("[-]\t"); printf("%-9s\t",luaP_opnames[o]); switch (getOpMode(o)) { case iABC: printf("%d",a); if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); break; case iABx: printf("%d",a); if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); if (getBMode(o)==OpArgU) printf(" %d",bx); break; case iAsBx: printf("%d %d",a,sbx); break; case iAx: printf("%d",MYK(ax)); break; } switch (o) { case OP_LOADK: printf("\t; "); PrintConstant(f,bx); break; case OP_GETUPVAL: case OP_SETUPVAL: printf("\t; %s",UPVALNAME(b)); break; case OP_GETTABUP: printf("\t; %s",UPVALNAME(b)); if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } break; case OP_SETTABUP: printf("\t; %s",UPVALNAME(a)); if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } break; case OP_GETTABLE: case OP_SELF: if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } break; case OP_SETTABLE: case OP_ADD: case OP_SUB: case OP_MUL: case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: case OP_EQ: case OP_LT: case OP_LE: if (ISK(b) || ISK(c)) { printf("\t; "); if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); printf(" "); if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); } break; case OP_JMP: case OP_FORLOOP: case OP_FORPREP: case OP_TFORLOOP: printf("\t; to %d",sbx+pc+2); break; case OP_CLOSURE: printf("\t; %p",VOID(f->p[bx])); break; case OP_SETLIST: if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); break; case OP_EXTRAARG: printf("\t; "); PrintConstant(f,ax); break; default: break; } printf("\n"); } }
static Instruction symbexec(const Proto* pt, int lastpc, int reg) { int pc; int last; /* stores position of last instruction that changed `reg' */ last = pt->sizecode - 1; /* points to final return (a `neutral' instruction) */ check(precheck(pt)); for (pc = 0; pc < lastpc; pc++) { Instruction i = pt->code[pc]; OpCode op = GET_OPCODE(i); int a = GETARG_A(i); int b = 0; int c = 0; check(op < NUM_OPCODES); checkreg(pt, a); switch (getOpMode(op)) { case iABC: { b = GETARG_B(i); c = GETARG_C(i); check(checkArgMode(pt, b, getBMode(op))); check(checkArgMode(pt, c, getCMode(op))); break; } case iABx: { b = GETARG_Bx(i); if (getBMode(op) == OpArgK) check(b < pt->sizek); break; } case iAsBx: { b = GETARG_sBx(i); if (getBMode(op) == OpArgR) { int dest = pc + 1 + b; check(0 <= dest && dest < pt->sizecode); if (dest > 0) { int j; /* check that it does not jump to a setlist count; this is tricky, because the count from a previous setlist may have the same value of an invalid setlist; so, we must go all the way back to the first of them (if any) */ for (j = 0; j < dest; j++) { Instruction d = pt->code[dest - 1 - j]; if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; } /* if 'j' is even, previous value is not a setlist (even if it looks like one) */ check((j & 1) == 0); } } break; } } if (testAMode(op)) { if (a == reg) last = pc; /* change register `a' */ } if (testTMode(op)) { check(pc + 2 < pt->sizecode); /* check skip */ check(GET_OPCODE(pt->code[pc + 1]) == OP_JMP); } switch (op) { case OP_LOADBOOL: { if (c == 1) /* does it jump? */ { check(pc + 2 < pt->sizecode); /* check its jump */ check(GET_OPCODE(pt->code[pc + 1]) != OP_SETLIST || GETARG_C(pt->code[pc + 1]) != 0); } break; } case OP_LOADNIL: { if (a <= reg && reg <= b) last = pc; /* set registers from `a' to `b' */ break; } case OP_GETUPVAL: case OP_SETUPVAL: { check(b < pt->nups); break; } case OP_GETGLOBAL: case OP_SETGLOBAL: { check(ttisstring(&pt->k[b])); break; } case OP_SELF: { checkreg(pt, a + 1); if (reg == a + 1) last = pc; break; } case OP_CONCAT: { check(b < c); /* at least two operands */ break; } case OP_TFORLOOP: { check(c >= 1); /* at least one result (control variable) */ checkreg(pt, a + 2 + c); /* space for results */ if (reg >= a + 2) last = pc; /* affect all regs above its base */ break; } case OP_FORLOOP: case OP_FORPREP: checkreg(pt, a + 3); /* go through */ case OP_JMP: { int dest = pc + 1 + b; /* not full check and jump is forward and do not skip `lastpc'? */ if (reg != NO_REG && pc < dest && dest <= lastpc) pc += b; /* do the jump */ break; } case OP_CALL: case OP_TAILCALL: { if (b != 0) { checkreg(pt, a + b - 1); } c--; /* c = num. returns */ if (c == LUA_MULTRET) { check(checkopenop(pt, pc)); } else if (c != 0) checkreg(pt, a + c - 1); if (reg >= a) last = pc; /* affect all registers above base */ break; } case OP_RETURN: { b--; /* b = num. returns */ if (b > 0) checkreg(pt, a + b - 1); break; } case OP_SETLIST: { if (b > 0) checkreg(pt, a + b); if (c == 0) { pc++; check(pc < pt->sizecode - 1); } break; } case OP_CLOSURE: { int nup, j; check(b < pt->sizep); nup = pt->p[b]->nups; check(pc + nup < pt->sizecode); for (j = 1; j <= nup; j++) { OpCode op1 = GET_OPCODE(pt->code[pc + j]); check(op1 == OP_GETUPVAL || op1 == OP_MOVE); } if (reg != NO_REG) /* tracing? */ pc += nup; /* do not 'execute' these pseudo-instructions */ break; } case OP_VARARG: { check((pt->is_vararg & VARARG_ISVARARG) && !(pt->is_vararg & VARARG_NEEDSARG)); b--; if (b == LUA_MULTRET) check(checkopenop(pt, pc)); checkreg(pt, a + b - 1); break; } default: break; } } return pt->code[last]; }
static Instruction symbexec (const Proto *pt, int lastpc, int reg) { int pc; int last; /* stores position of last instruction that changed `reg' */ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ check(precheck(pt)); for (pc = 0; pc < lastpc; pc++) { Instruction i = pt->code[pc]; OpCode op = GET_OPCODE(i); int a = GETARG_A(i); int b = 0; int c = 0; check(op < NUM_OPCODES); checkreg(pt, a); switch (getOpMode(op)) { case iABC: { b = GETARG_B(i); c = GETARG_C(i); check(checkArgMode(pt, b, getBMode(op))); check(checkArgMode(pt, c, getCMode(op))); break; } case iABx: { b = GETARG_Bx(i); if (getBMode(op) == OpArgK) check(b < pt->sizek); break; } case iAsBx: { b = GETARG_sBx(i); if (getBMode(op) == OpArgR) { int dest = pc+1+b; check(0 <= dest && dest < pt->sizecode); if (dest > 0) { /* cannot jump to a setlist count */ Instruction d = pt->code[dest-1]; check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)); } } break; } } if (testAMode(op)) { if (a == reg) last = pc; /* change register `a' */ } if (testTMode(op)) { check(pc+2 < pt->sizecode); /* check skip */ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); } switch (op) { case OP_LOADBOOL: { check(c == 0 || pc+2 < pt->sizecode); /* check its jump */ break; } case OP_LOADNIL: { if (a <= reg && reg <= b) last = pc; /* set registers from `a' to `b' */ break; } case OP_GETUPVAL: case OP_SETUPVAL: { check(b < pt->nups); break; } case OP_GETGLOBAL: case OP_SETGLOBAL: { check(ttisstring(&pt->k[b])); break; } case OP_SELF: { checkreg(pt, a+1); if (reg == a+1) last = pc; break; } case OP_CONCAT: { check(b < c); /* at least two operands */ break; } case OP_TFORLOOP: { check(c >= 1); /* at least one result (control variable) */ checkreg(pt, a+2+c); /* space for results */ if (reg >= a+2) last = pc; /* affect all regs above its base */ break; } case OP_FORLOOP: case OP_FORPREP: checkreg(pt, a+3); /* go through */ case OP_JMP: { int dest = pc+1+b; /* not full check and jump is forward and do not skip `lastpc'? */ if (reg != NO_REG && pc < dest && dest <= lastpc) pc += b; /* do the jump */ break; } case OP_CALL: case OP_TAILCALL: { if (b != 0) { checkreg(pt, a+b-1); } c--; /* c = num. returns */ if (c == LUA_MULTRET) { check(checkopenop(pt, pc)); } else if (c != 0) checkreg(pt, a+c-1); if (reg >= a) last = pc; /* affect all registers above base */ break; } case OP_RETURN: { b--; /* b = num. returns */ if (b > 0) checkreg(pt, a+b-1); break; } case OP_SETLIST: { if (b > 0) checkreg(pt, a + b); if (c == 0) pc++; break; } case OP_CLOSURE: { int nup; check(b < pt->sizep); nup = pt->p[b]->nups; check(pc + nup < pt->sizecode); for (; nup>0; nup--) { OpCode op1 = GET_OPCODE(pt->code[pc+nup]); check(op1 == OP_GETUPVAL || op1 == OP_MOVE); } break; } case OP_VARARG: { check((pt->is_vararg & VARARG_ISVARARG) && !(pt->is_vararg & VARARG_NEEDSARG)); b--; if (b == LUA_MULTRET) check(checkopenop(pt, pc)); checkreg(pt, a+b-1); break; } default: break; } } return pt->code[last]; }
static void PrintCode(const Proto* f) { const Instruction* code=f->code; int pc,n=f->sizecode; for (pc=0; pc<n; pc++) { Instruction i=code[pc]; OpCode o=GET_OPCODE(i); int a=GETARG_A(i); int b=GETARG_B(i); int c=GETARG_C(i); int bx=GETARG_Bx(i); int sbx=GETARG_sBx(i); int line=getline(f,pc); printf("\t%d\t",pc+1); if (line>0) printf("[%d]\t",line); else printf("[-]\t"); printf("%-9s\t",luaP_opnames[o]); switch (getOpMode(o)) { case iABC: printf("%d",a); if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b); if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c); break; case iABx: if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx); break; case iAsBx: if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx); break; } switch (o) { case OP_LOADK: printf("\t; "); PrintConstant(f,bx); break; case OP_GETUPVAL: case OP_SETUPVAL: printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-"); break; case OP_GETGLOBAL: case OP_SETGLOBAL: printf("\t; %s",svalue(&f->k[bx])); break; case OP_GETTABLE: case OP_SELF: if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } break; case OP_SETTABLE: case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_POW: case OP_EQ: case OP_LT: case OP_LE: if (ISK(b) || ISK(c)) { printf("\t; "); if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); printf(" "); if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); } break; case OP_JMP: case OP_FORLOOP: case OP_FORPREP: printf("\t; to %d",sbx+pc+2); break; case OP_CLOSURE: printf("\t; %p",VOID(f->p[bx])); break; case OP_SETLIST: if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); break; default: break; } printf("\n"); } }
int FuncState::luaK_codeABx (/*FuncState *fs,*/ OpCode o, int a, unsigned int bc) { lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); lua_assert(getCMode(o) == OpArgN); lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); return luaK_code(CREATE_ABx(o, a, bc)); }