void codegen_dischargevars(FuncState *fs, expdesc *e) { switch (e->k) { case VLOCAL: { e->k = VNONRELOC; break; } case VUPVAL: { e->u.info = codegen_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); e->k = VRELOCABLE; break; } case VINDEXED: { OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ freereg(fs, e->u.ind.idx); if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ freereg(fs, e->u.ind.t); op = OP_GETTABLE; } e->u.info = codegen_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; break; } case VVARARG: case VCALL: { codegen_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ } }
void codegen_nil(FuncState *fs, int from, int n) { Instruction *previous; int l = from + n - 1; /* last register to set nil */ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ previous = &fs->f->code[fs->pc-1]; if (GET_OPCODE(*previous) == OP_LOADNIL) { int pfrom = GETARG_A(*previous); int pl = pfrom + GETARG_B(*previous); if ((pfrom <= from && from <= pl + 1) || (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ if (pl > l) l = pl; /* l = max(l, pl) */ SETARG_A(*previous, from); SETARG_B(*previous, l - from); return; } } /* else go through */ } codegen_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ }
static void discharge2reg(ktap_funcstate *fs, ktap_expdesc *e, int reg) { codegen_dischargevars(fs, e); switch (e->k) { case VNIL: { codegen_nil(fs, reg, 1); break; } case VFALSE: case VTRUE: { codegen_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); break; } case VEVENT: codegen_codeABC(fs, OP_EVENT, reg, 0, 0); break; case VEVENTNAME: codegen_codeABC(fs, OP_EVENTNAME, reg, 0, 0); break; case VEVENTARG: codegen_codeABC(fs, OP_EVENTARG, reg, e->u.info, 0); break; case VK: { codegen_codek(fs, reg, e->u.info); break; } case VKNUM: { codegen_codek(fs, reg, codegen_numberK(fs, e->u.nval)); break; } case VRELOCABLE: { ktap_instruction *pc = &getcode(fs, e); SETARG_A(*pc, reg); break; } case VNONRELOC: { if (reg != e->u.info) codegen_codeABC(fs, OP_MOVE, reg, e->u.info, 0); break; } default: ktap_assert(e->k == VVOID || e->k == VJMP); return; /* nothing to do... */ } e->u.info = reg; e->k = VNONRELOC; }
static int condjump(FuncState *fs, OpCode op, int A, int B, int C) { codegen_codeABC(fs, op, A, B, C); return codegen_jump(fs); }
void codegen_ret(FuncState *fs, int first, int nret) { codegen_codeABC(fs, OP_RETURN, first, nret+1, 0); }
static int code_label(FuncState *fs, int A, int b, int jump) { codegen_getlabel(fs); /* those instructions may be jump targets */ return codegen_codeABC(fs, OP_LOADBOOL, A, b, jump); }
void codegen_ret(ktap_funcstate *fs, int first, int nret) { codegen_codeABC(fs, OP_RETURN, first, nret+1, 0); }