public void Copy(expdesc e) { this.k = e.k; this.u.Copy(e.u); this.t = e.t; this.f = e.f; }
public static void luaK_dischargevars(FuncState fs, expdesc e) { switch (e.k) { case expkind.VLOCAL: { e.k = expkind.VNONRELOC; break; } case expkind.VUPVAL: { e.u.s.info = luaK_codeABC(fs, OpCode.OP_GETUPVAL, 0, e.u.s.info, 0); e.k = expkind.VRELOCABLE; break; } case expkind.VGLOBAL: { e.u.s.info = luaK_codeABxX(fs, OpCode.OP_GETGLOBAL, 0, e.u.s.info); e.k = expkind.VRELOCABLE; break; } case expkind.VINDEXED: { freereg(fs, e.u.s.aux); freereg(fs, e.u.s.info); e.u.s.info = luaK_codeABC(fs, OpCode.OP_GETTABLE, 0, e.u.s.info, e.u.s.aux); e.k = expkind.VRELOCABLE; break; } case expkind.VVARARG: case expkind.VCALL: { luaK_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ } }
public static void luaK_infix(FuncState fs, BinOpr op, expdesc v) { switch (op) { case BinOpr.OPR_AND: luaK_goiftrue(fs, v); break; case BinOpr.OPR_OR: luaK_goiffalse(fs, v); break; case BinOpr.OPR_CONCAT: luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */ break; case BinOpr.OPR_ADD: case BinOpr.OPR_SUB: case BinOpr.OPR_MUL: case BinOpr.OPR_DIV: case BinOpr.OPR_MOD: case BinOpr.OPR_POW: case BinOpr.OPR_RSHIFT: case BinOpr.OPR_LSHIFT: case BinOpr.OPR_BITAND: case BinOpr.OPR_BITOR: if ((isnumeral(v) == 0)) { luaK_exp2RK(fs, v); } break; default: luaK_exp2RK(fs, v); break; } }
private static void luaK_goiffalse(FuncState fs, expdesc e) { int pc; /* pc of last jump */ luaK_dischargevars(fs, e); switch (e.k) { case expkind.VNIL: case expkind.VFALSE: { pc = NO_JUMP; /* always false; do nothing */ break; } case expkind.VJMP: { pc = e.u.info; break; } case expkind.VTRUE: { if (!hasjumps(e)) { pc = luaK_jump(fs); /* always jump */ break; } /* else go through */ goto default; //FIXME:added } default: { pc = jumponcond(fs, e, 1); break; } } luaK_concat(fs, ref e.t, pc); /* insert last jump in `t' list */ luaK_patchtohere(fs, e.f); e.f = NO_JUMP; }
/* ** Code for binary and unary expressions that "produce values" ** (arithmetic operations, bitwise operations, concat, length). First ** try to do constant folding (only for numeric [arithmetic and ** bitwise] operations, which is what 'lua_arith' accepts). ** Expression to produce final result will be encoded in 'e1'. */ private static void codeexpval(FuncState fs, OpCode op, expdesc e1, expdesc e2, int line) { lua_assert(op >= OpCode.OP_ADD); if (op <= OpCode.OP_BNOT && 0 != constfolding(fs, op - OpCode.OP_ADD + LUA_OPADD, e1, e2)) { return; /* result has been folded */ } else { int o1, o2; /* move operands to registers (if needed) */ if (op == OpCode.OP_UNM || op == OpCode.OP_BNOT || op == OpCode.OP_LEN) /* unary op? */ { o2 = 0; /* no second expression */ o1 = luaK_exp2anyreg(fs, e1); /* cannot operate on constants */ } else /* regular case (binary operators) */ { o2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */ o1 = luaK_exp2RK(fs, e1); } if (o1 > o2) /* free registers in proper order */ { freeexp(fs, e1); freeexp(fs, e2); } else { freeexp(fs, e2); freeexp(fs, e1); } e1.u.info = luaK_codeABC(fs, op, 0, o1, o2); /* generate opcode */ e1.k = expkind.VRELOCABLE; /* all those operations are relocable */ luaK_fixline(fs, line); } }
public static void luaK_dischargevars(FuncState fs, expdesc e) { switch (e.k) { case expkind.VLOCAL: { e.k = expkind.VNONRELOC; break; } case expkind.VUPVAL: { e.u.info = luaK_codeABC(fs, OpCode.OP_GETUPVAL, 0, e.u.info, 0); e.k = expkind.VRELOCABLE; break; } case expkind.VINDEXED: { OpCode op = OpCode.OP_GETTABUP; /* assume 't' is in an upvalue */ freereg(fs, e.u.ind.idx); if (e.u.ind.vt == (byte)expkind.VLOCAL) /* 't' is in a register? */ //FIXME:changed, (byte) { freereg(fs, e.u.ind.t); op = OpCode.OP_GETTABLE; } e.u.info = luaK_codeABC(fs, op, 0, e.u.ind.t, e.u.ind.idx); e.k = expkind.VRELOCABLE; break; } case expkind.VVARARG: case expkind.VCALL: { luaK_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ } }
private static int constfolding(OpCode op, expdesc e1, expdesc e2) { TValue v1 = new TValue(); TValue v2 = new TValue(); TValue res = new TValue(); lua_Integer i = 0; if (0 == tonumeral(e1, v1) || 0 == tonumeral(e2, v2)) { return(0); } if (op == OpCode.OP_IDIV && (0 == tointeger(ref v1, ref i) || 0 == tointeger(ref v2, ref i) || i == 0)) { return(0); /* avoid division by 0 and conversion errors */ } if (op == OpCode.OP_MOD && ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0) { return(0); /* avoid module by 0 at compile time */ } luaO_arith(null, op - OpCode.OP_ADD + LUA_OPADD, v1, v2, res); if (ttisinteger(res)) { e1.k = expkind.VKINT; e1.u.ival = ivalue(res); } else { lua_Number n = fltvalue(res); if (luai_numisnan(null, n) || isminuszero(n)) { return(0); /* folds neither NaN nor -0 */ } e1.k = expkind.VKFLT; e1.u.nval = n; } return(1); }
/* ** Aplly prefix operation 'op' to expression 'e'. */ public static void luaK_prefix(FuncState fs, UnOpr op, expdesc e, int line) { //static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; switch (op) { case UnOpr.OPR_MINUS: case UnOpr.OPR_BNOT: /* use 'ef' as fake 2nd operand */ if (0 != constfolding(fs, (int)op + LUA_OPUNM, e, luaK_prefix_ef)) { break; } /* FALLTHROUGH */ goto case UnOpr.OPR_LEN; case UnOpr.OPR_LEN: codeunexpval(fs, (OpCode)((int)op + OpCode.OP_UNM), e, line); break; case UnOpr.OPR_NOT: codenot(fs, e); break; default: lua_assert(0); break; } }
public static void luaK_goiftrue(FuncState fs, expdesc e) { int pc; /* pc of last jump */ luaK_dischargevars(fs, e); switch (e.k) { case expkind.VK: case expkind.VKNUM: case expkind.VTRUE: { pc = NO_JUMP; /* always true; do nothing */ break; } //case expkind.VFALSE: { // pc = luaK_jump(fs); /* always jump */ // break; //} case expkind.VJMP: { invertjump(fs, e); pc = e.u.s.info; break; } default: { pc = jumponcond(fs, e, 0); break; } } luaK_concat(fs, ref e.f, pc); /* insert last jump in `f' list */ luaK_patchtohere(fs, e.t); e.t = NO_JUMP; }
private static void codearith(FuncState fs, OpCode op, expdesc e1, expdesc e2) { if (constfolding(op, e1, e2) != 0) { return; } else { int o2 = (op != OpCode.OP_UNM && op != OpCode.OP_LEN) ? luaK_exp2RK(fs, e2) : 0; int o1 = luaK_exp2RK(fs, e1); if (o1 > o2) { freeexp(fs, e1); freeexp(fs, e2); } else { freeexp(fs, e2); freeexp(fs, e1); } e1.u.s.info = luaK_codeABC(fs, op, 0, o1, o2); e1.k = expkind.VRELOCABLE; } }
private static void CodeArith(FuncState fs, OpCode op, expdesc e1, expdesc e2) { if (ConstFolding(op, e1, e2) != 0) { return; } else { int o2 = (op != OpCode.OP_UNM && op != OpCode.OP_LEN) ? LuaKExp2RK(fs, e2) : 0; int o1 = LuaKExp2RK(fs, e1); if (o1 > o2) { FreeExp(fs, e1); FreeExp(fs, e2); } else { FreeExp(fs, e2); FreeExp(fs, e1); } e1.u.s.info = LuaKCodeABC(fs, op, 0, o1, o2); e1.k = expkind.VRELOCABLE; } }
private static void CodeNot (FuncState fs, expdesc e) { LuaKDischargeVars(fs, e); switch (e.k) { case expkind.VNIL: case expkind.VFALSE: { e.k = expkind.VTRUE; break; } case expkind.VK: case expkind.VKNUM: case expkind.VTRUE: { e.k = expkind.VFALSE; break; } case expkind.VJMP: { InvertJump(fs, e); break; } case expkind.VRELOCABLE: case expkind.VNONRELOC: { Discharge2AnyReg(fs, e); FreeExp(fs, e); e.u.s.info = LuaKCodeABC(fs, OpCode.OP_NOT, 0, e.u.s.info, 0); e.k = expkind.VRELOCABLE; break; } default: { LuaAssert(0); /* cannot happen */ break; } } /* interchange true and false lists */ { int temp = e.f; e.f = e.t; e.t = temp; } RemoveValues(fs, e.f); RemoveValues(fs, e.t); }
public static void LuaKGoIfTrue (FuncState fs, expdesc e) { int pc; /* pc of last jump */ LuaKDischargeVars(fs, e); switch (e.k) { case expkind.VK: case expkind.VKNUM: case expkind.VTRUE: { pc = NO_JUMP; /* always true; do nothing */ break; } case expkind.VJMP: { InvertJump(fs, e); pc = e.u.s.info; break; } default: { pc = JumpOnCond(fs, e, 0); break; } } LuaKConcat(fs, ref e.f, pc); /* insert last jump in `f' list */ LuaKPatchToHere(fs, e.t); e.t = NO_JUMP; }
private static void InvertJump (FuncState fs, expdesc e) { InstructionPtr pc = GetJumpControl(fs, e.u.s.info); LuaAssert(testTMode(GET_OPCODE(pc[0])) != 0 && GET_OPCODE(pc[0]) != OpCode.OP_TESTSET && GET_OPCODE(pc[0]) != OpCode.OP_TEST); SETARG_A(pc, (GETARG_A(pc[0]) == 0) ? 1 : 0); }
public static void LuaKStoreVar (FuncState fs, expdesc var, expdesc ex) { switch (var.k) { case expkind.VLOCAL: { FreeExp(fs, ex); Exp2Reg(fs, ex, var.u.s.info); return; } case expkind.VUPVAL: { int e = LuaKExp2AnyReg(fs, ex); LuaKCodeABC(fs, OpCode.OP_SETUPVAL, e, var.u.s.info, 0); break; } case expkind.VGLOBAL: { int e = LuaKExp2AnyReg(fs, ex); LuaKCodeABx(fs, OpCode.OP_SETGLOBAL, e, var.u.s.info); break; } case expkind.VINDEXED: { int e = LuaKExp2RK(fs, ex); LuaKCodeABC(fs, OpCode.OP_SETTABLE, var.u.s.info, var.u.s.aux, e); break; } default: { LuaAssert(0); /* invalid var kind to store */ break; } } FreeExp(fs, ex); }
public static void luaK_posfix(FuncState fs, BinOpr op, expdesc e1, expdesc e2) { switch (op) { case BinOpr.OPR_AND: { lua_assert(e1.t == NO_JUMP); /* list must be closed */ luaK_dischargevars(fs, e2); luaK_concat(fs, ref e2.f, e1.f); e1.Copy(e2); break; } case BinOpr.OPR_OR: { lua_assert(e1.f == NO_JUMP); /* list must be closed */ luaK_dischargevars(fs, e2); luaK_concat(fs, ref e2.t, e1.t); e1.Copy(e2); break; } case BinOpr.OPR_CONCAT: { luaK_exp2val(fs, e2); if (e2.k == expkind.VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OpCode.OP_CONCAT) { lua_assert(e1.u.s.info == GETARG_B(getcode(fs, e2)) - 1); freeexp(fs, e1); SETARG_B(getcode(fs, e2), e1.u.s.info); e1.k = expkind.VRELOCABLE; e1.u.s.info = e2.u.s.info; } else { luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ codearith(fs, OpCode.OP_CONCAT, e1, e2); } break; } case BinOpr.OPR_ADD: codearith(fs, OpCode.OP_ADD, e1, e2); break; case BinOpr.OPR_SUB: codearith(fs, OpCode.OP_SUB, e1, e2); break; case BinOpr.OPR_MUL: codearith(fs, OpCode.OP_MUL, e1, e2); break; case BinOpr.OPR_DIV: codearith(fs, OpCode.OP_DIV, e1, e2); break; case BinOpr.OPR_MOD: codearith(fs, OpCode.OP_MOD, e1, e2); break; case BinOpr.OPR_POW: codearith(fs, OpCode.OP_POW, e1, e2); break; case BinOpr.OPR_EQ: codecomp(fs, OpCode.OP_EQ, 1, e1, e2); break; case BinOpr.OPR_NE: codecomp(fs, OpCode.OP_EQ, 0, e1, e2); break; case BinOpr.OPR_LT: codecomp(fs, OpCode.OP_LT, 1, e1, e2); break; case BinOpr.OPR_LE: codecomp(fs, OpCode.OP_LE, 1, e1, e2); break; case BinOpr.OPR_GT: codecomp(fs, OpCode.OP_LT, 0, e1, e2); break; case BinOpr.OPR_GE: codecomp(fs, OpCode.OP_LE, 0, e1, e2); break; case BinOpr.OPR_RSHIFT: codearith(fs, OpCode.OP_RSHIFT, e1, e2); break; case BinOpr.OPR_LSHIFT: codearith(fs, OpCode.OP_LSHIFT, e1, e2); break; case BinOpr.OPR_BITAND: codearith(fs, OpCode.OP_BITAND, e1, e2); break; case BinOpr.OPR_BITOR: codearith(fs, OpCode.OP_BITOR, e1, e2); break; default: lua_assert(0); break; } }
private static void Discharge2AnyReg (FuncState fs, expdesc e) { if (e.k != expkind.VNONRELOC) { LuaKReserveRegs(fs, 1); Discharge2Reg(fs, e, fs.freereg-1); } }
public static void LuaKDischargeVars (FuncState fs, expdesc e) { switch (e.k) { case expkind.VLOCAL: { e.k = expkind.VNONRELOC; break; } case expkind.VUPVAL: { e.u.s.info = LuaKCodeABC(fs, OpCode.OP_GETUPVAL, 0, e.u.s.info, 0); e.k = expkind.VRELOCABLE; break; } case expkind.VGLOBAL: { e.u.s.info = LuaKCodeABx(fs, OpCode.OP_GETGLOBAL, 0, e.u.s.info); e.k = expkind.VRELOCABLE; break; } case expkind.VINDEXED: { FreeReg(fs, e.u.s.aux); FreeReg(fs, e.u.s.info); e.u.s.info = LuaKCodeABC(fs, OpCode.OP_GETTABLE, 0, e.u.s.info, e.u.s.aux); e.k = expkind.VRELOCABLE; break; } case expkind.VVARARG: case expkind.VCALL: { LuaKSetOneRet(fs, e); break; } default: break; /* there is one value available (somewhere) */ } }
public static void LuaKSetReturns (FuncState fs, expdesc e, int nresults) { if (e.k == expkind.VCALL) { /* expression is an open function call? */ SETARG_C(GetCode(fs, e), nresults+1); } else if (e.k == expkind.VVARARG) { SETARG_B(GetCode(fs, e), nresults+1); SETARG_A(GetCode(fs, e), fs.freereg); LuaKReserveRegs(fs, 1); } }
private static int IsNumeral(expdesc e) { return (e.k == expkind.VKNUM && e.t == NO_JUMP && e.f == NO_JUMP) ? 1 : 0; }
public static void LinyeeKSetMultRet(FuncState fs, expdesc e) { LinyeeKSetReturns(fs, e, LINYEE_MULTRET); }
public static void luaK_setmultret(FuncState fs, expdesc e) { luaK_setreturns(fs, e, LUA_MULTRET); }
public static InstructionPtr getcode(FuncState fs, expdesc e) { return(new InstructionPtr(fs.f.code, e.u.s.info)); }
public static bool HasJumps(expdesc e) { return(e.t != e.f); }
public static void LuaKSetMultRet(FuncState fs, expdesc e) { LuaKSetReturns(fs, e, LUA_MULTRET); }
public static void LuaKPosFix(FuncState fs, BinOpr op, expdesc e1, expdesc e2) { switch (op) { case BinOpr.OPR_AND: { LuaAssert(e1.t == NO_JUMP); /* list must be closed */ LuaKDischargeVars(fs, e2); LuaKConcat(fs, ref e2.f, e1.f); e1.Copy(e2); break; } case BinOpr.OPR_OR: { LuaAssert(e1.f == NO_JUMP); /* list must be closed */ LuaKDischargeVars(fs, e2); LuaKConcat(fs, ref e2.t, e1.t); e1.Copy(e2); break; } case BinOpr.OPR_CONCAT: { LuaKExp2Val(fs, e2); if (e2.k == expkind.VRELOCABLE && GET_OPCODE(GetCode(fs, e2)) == OpCode.OP_CONCAT) { LuaAssert(e1.u.s.info == GETARG_B(GetCode(fs, e2)) - 1); FreeExp(fs, e1); SETARG_B(GetCode(fs, e2), e1.u.s.info); e1.k = expkind.VRELOCABLE; e1.u.s.info = e2.u.s.info; } else { LuaKExp2NextReg(fs, e2); /* operand must be on the 'stack' */ CodeArith(fs, OpCode.OP_CONCAT, e1, e2); } break; } case BinOpr.OPR_ADD: CodeArith(fs, OpCode.OP_ADD, e1, e2); break; case BinOpr.OPR_SUB: CodeArith(fs, OpCode.OP_SUB, e1, e2); break; case BinOpr.OPR_MUL: CodeArith(fs, OpCode.OP_MUL, e1, e2); break; case BinOpr.OPR_DIV: CodeArith(fs, OpCode.OP_DIV, e1, e2); break; case BinOpr.OPR_MOD: CodeArith(fs, OpCode.OP_MOD, e1, e2); break; case BinOpr.OPR_POW: CodeArith(fs, OpCode.OP_POW, e1, e2); break; case BinOpr.OPR_EQ: CodeComp(fs, OpCode.OP_EQ, 1, e1, e2); break; case BinOpr.OPR_NE: CodeComp(fs, OpCode.OP_EQ, 0, e1, e2); break; case BinOpr.OPR_LT: CodeComp(fs, OpCode.OP_LT, 1, e1, e2); break; case BinOpr.OPR_LE: CodeComp(fs, OpCode.OP_LE, 1, e1, e2); break; case BinOpr.OPR_GT: CodeComp(fs, OpCode.OP_LT, 0, e1, e2); break; case BinOpr.OPR_GE: CodeComp(fs, OpCode.OP_LE, 0, e1, e2); break; default: LuaAssert(0); break; } }
public static void codecomp(FuncState fs, OpCode op, int cond, expdesc e1, expdesc e2) { int o1 = luaK_exp2RK(fs, e1); int o2 = luaK_exp2RK(fs, e2); freeexp(fs, e2); freeexp(fs, e1); if (cond == 0 && op != OpCode.OP_EQ) { int temp = o1; o1 = o2; o2 = temp; cond = 1; } e1.u.info = condjump(fs, op, cond, o1, o2); e1.k = expkind.VJMP; }
private static int isnumeral(expdesc e) { return((e.k == expkind.VKNUM && e.t == NO_JUMP && e.f == NO_JUMP) ? 1 : 0); }
private static void FreeExp (FuncState fs, expdesc e) { if (e.k == expkind.VNONRELOC) FreeReg(fs, e.u.s.info); }
public static void luaK_indexed(FuncState fs, expdesc t, expdesc k) { t.u.s.aux = luaK_exp2RK(fs, k); t.k = expkind.VINDEXED; }
public static void LuaKSetOneRet (FuncState fs, expdesc e) { if (e.k == expkind.VCALL) { /* expression is an open function call? */ e.k = expkind.VNONRELOC; e.u.s.info = GETARG_A(GetCode(fs, e)); } else if (e.k == expkind.VVARARG) { SETARG_B(GetCode(fs, e), 2); e.k = expkind.VRELOCABLE; /* can relocate its simple result */ } }
public static void LuaKExp2NextReg (FuncState fs, expdesc e) { LuaKDischargeVars(fs, e); FreeExp(fs, e); LuaKReserveRegs(fs, 1); Exp2Reg(fs, e, fs.freereg - 1); }
private static void Discharge2Reg (FuncState fs, expdesc e, int reg) { LuaKDischargeVars(fs, e); switch (e.k) { case expkind.VNIL: { LuaKNil(fs, reg, 1); break; } case expkind.VFALSE: case expkind.VTRUE: { LuaKCodeABC(fs, OpCode.OP_LOADBOOL, reg, (e.k == expkind.VTRUE) ? 1 : 0, 0); break; } case expkind.VK: { LuaKCodeABx(fs, OpCode.OP_LOADK, reg, e.u.s.info); break; } case expkind.VKNUM: { LuaKCodeABx(fs, OpCode.OP_LOADK, reg, LuaKNumberK(fs, e.u.nval)); break; } case expkind.VRELOCABLE: { InstructionPtr pc = GetCode(fs, e); SETARG_A(pc, reg); break; } case expkind.VNONRELOC: { if (reg != e.u.s.info) LuaKCodeABC(fs, OpCode.OP_MOVE, reg, e.u.s.info, 0); break; } default: { LuaAssert(e.k == expkind.VVOID || e.k == expkind.VJMP); return; /* nothing to do... */ } } e.u.s.info = reg; e.k = expkind.VNONRELOC; }
public static void LuaKExp2Val (FuncState fs, expdesc e) { if (HasJumps(e)) LuaKExp2AnyReg(fs, e); else LuaKDischargeVars(fs, e); }
private static void Exp2Reg (FuncState fs, expdesc e, int reg) { Discharge2Reg(fs, e, reg); if (e.k == expkind.VJMP) LuaKConcat(fs, ref e.t, e.u.s.info); /* put this jump in `t' list */ if (HasJumps(e)) { int final; /* position after whole expression */ int p_f = NO_JUMP; /* position of an eventual LOAD false */ int p_t = NO_JUMP; /* position of an eventual LOAD true */ if (NeedValue(fs, e.t)!=0 || NeedValue(fs, e.f)!=0) { int fj = (e.k == expkind.VJMP) ? NO_JUMP : LuaKJump(fs); p_f = CodeLabel(fs, reg, 0, 1); p_t = CodeLabel(fs, reg, 1, 0); LuaKPatchToHere(fs, fj); } final = LuaKGetLabel(fs); PatchListAux(fs, e.f, final, reg, p_f); PatchListAux(fs, e.t, final, reg, p_t); } e.f = e.t = NO_JUMP; e.u.s.info = reg; e.k = expkind.VNONRELOC; }
public static void LinyeeKIndexed(FuncState fs, expdesc t, expdesc k) { t.u.s.aux = LinyeeKExp2RK(fs, k); t.k = expkind.VINDEXED; }
public static int LuaKExp2AnyReg (FuncState fs, expdesc e) { LuaKDischargeVars(fs, e); if (e.k == expkind.VNONRELOC) { if (!HasJumps(e)) return e.u.s.info; /* exp is already in a register */ if (e.u.s.info >= fs.nactvar) { /* reg. is not a local? */ Exp2Reg(fs, e, e.u.s.info); /* put value on it */ return e.u.s.info; } } LuaKExp2NextReg(fs, e); /* default */ return e.u.s.info; }
public static void luaK_posfix(FuncState fs, BinOpr op, expdesc e1, expdesc e2, int line) { switch (op) { case BinOpr.OPR_AND: { lua_assert(e1.t == NO_JUMP); /* list must be closed */ luaK_dischargevars(fs, e2); luaK_concat(fs, ref e2.f, e1.f); e1.Copy(e2); break; } case BinOpr.OPR_OR: { lua_assert(e1.f == NO_JUMP); /* list must be closed */ luaK_dischargevars(fs, e2); luaK_concat(fs, ref e2.t, e1.t); e1.Copy(e2); break; } case BinOpr.OPR_CONCAT: { luaK_exp2val(fs, e2); if (e2.k == expkind.VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OpCode.OP_CONCAT) { lua_assert(e1.u.info == GETARG_B(getcode(fs, e2)) - 1); freeexp(fs, e1); SETARG_B(getcode(fs, e2), e1.u.info); e1.k = expkind.VRELOCABLE; e1.u.info = e2.u.info; } else { luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ codeexpval(fs, OpCode.OP_CONCAT, e1, e2, line); } break; } case BinOpr.OPR_ADD: case BinOpr.OPR_SUB: case BinOpr.OPR_MUL: case BinOpr.OPR_DIV: case BinOpr.OPR_IDIV: case BinOpr.OPR_MOD: case BinOpr.OPR_POW: case BinOpr.OPR_BAND: case BinOpr.OPR_BOR: case BinOpr.OPR_BXOR: case BinOpr.OPR_SHL: case BinOpr.OPR_SHR: { codeexpval(fs, (OpCode)((op - BinOpr.OPR_ADD) + OpCode.OP_ADD), e1, e2, line); break; } case BinOpr.OPR_EQ: case BinOpr.OPR_LT: case BinOpr.OPR_LE: { codecomp(fs, (OpCode)(op - BinOpr.OPR_EQ + OpCode.OP_EQ), 1, e1, e2); break; } case BinOpr.OPR_NE: case BinOpr.OPR_GT: case BinOpr.OPR_GE: { codecomp(fs, (OpCode)(op - BinOpr.OPR_NE + OpCode.OP_EQ), 0, e1, e2); break; } default: lua_assert(0); break; } }
public static int LuaKExp2RK (FuncState fs, expdesc e) { LuaKExp2Val(fs, e); switch (e.k) { case expkind.VKNUM: case expkind.VTRUE: case expkind.VFALSE: case expkind.VNIL: { if (fs.nk <= MAXINDEXRK) { /* constant fit in RK operand? */ e.u.s.info = (e.k == expkind.VNIL) ? NilK(fs) : (e.k == expkind.VKNUM) ? LuaKNumberK(fs, e.u.nval) : BoolValueK(fs, (e.k == expkind.VTRUE) ? 1 : 0); e.k = expkind.VK; return RKASK(e.u.s.info); } else break; } case expkind.VK: { if (e.u.s.info <= MAXINDEXRK) /* constant fit in argC? */ return RKASK(e.u.s.info); else break; } default: break; } /* not a constant in the right range: put it in a register */ return LuaKExp2AnyReg(fs, e); }
public static bool hasjumps(expdesc e) { return(e.t != e.f); }
public static void LuaKSelf (FuncState fs, expdesc e, expdesc key) { int func; LuaKExp2AnyReg(fs, e); FreeExp(fs, e); func = fs.freereg; LuaKReserveRegs(fs, 2); LuaKCodeABC(fs, OpCode.OP_SELF, func, e.u.s.info, LuaKExp2RK(fs, key)); FreeExp(fs, key); e.u.s.info = func; e.k = expkind.VNONRELOC; }
private static int ConstFolding (OpCode op, expdesc e1, expdesc e2) { LuaNumberType v1, v2, r; if ((IsNumeral(e1)==0) || (IsNumeral(e2)==0)) return 0; v1 = e1.u.nval; v2 = e2.u.nval; switch (op) { case OpCode.OP_ADD: r = luai_numadd(v1, v2); break; case OpCode.OP_SUB: r = luai_numsub(v1, v2); break; case OpCode.OP_MUL: r = luai_nummul(v1, v2); break; case OpCode.OP_DIV: if (v2 == 0) return 0; /* do not attempt to divide by 0 */ r = luai_numdiv(v1, v2); break; case OpCode.OP_MOD: if (v2 == 0) return 0; /* do not attempt to divide by 0 */ r = luai_nummod(v1, v2); break; case OpCode.OP_POW: r = luai_numpow(v1, v2); break; case OpCode.OP_UNM: r = luai_numunm(v1); break; case OpCode.OP_LEN: return 0; /* no constant folding for 'len' */ default: LuaAssert(0); r = 0; break; } if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ e1.u.nval = r; return 1; }
private static int JumpOnCond (FuncState fs, expdesc e, int cond) { if (e.k == expkind.VRELOCABLE) { InstructionPtr ie = GetCode(fs, e); if (GET_OPCODE(ie) == OpCode.OP_NOT) { fs.pc--; /* remove previous OpCode.OP_NOT */ return CondJump(fs, OpCode.OP_TEST, GETARG_B(ie), 0, (cond==0) ? 1 : 0); } /* else go through */ } Discharge2AnyReg(fs, e); FreeExp(fs, e); return CondJump(fs, OpCode.OP_TESTSET, NO_REG, e.u.s.info, cond); }
private static void CodeComp (FuncState fs, OpCode op, int cond, expdesc e1, expdesc e2) { int o1 = LuaKExp2RK(fs, e1); int o2 = LuaKExp2RK(fs, e2); FreeExp(fs, e2); FreeExp(fs, e1); if (cond == 0 && op != OpCode.OP_EQ) { int temp; /* exchange args to replace by `<' or `<=' */ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ cond = 1; } e1.u.s.info = CondJump(fs, op, cond, o1, o2); e1.k = expkind.VJMP; }
private static void LuaKGoIFalse (FuncState fs, expdesc e) { int pc; /* pc of last jump */ LuaKDischargeVars(fs, e); switch (e.k) { case expkind.VNIL: case expkind.VFALSE: { pc = NO_JUMP; /* always false; do nothing */ break; } case expkind.VJMP: { pc = e.u.s.info; break; } default: { pc = JumpOnCond(fs, e, 1); break; } } LuaKConcat(fs, ref e.t, pc); /* insert last jump in `t' list */ LuaKPatchToHere(fs, e.f); e.f = NO_JUMP; }
public static void LuaKInfix (FuncState fs, BinOpr op, expdesc v) { switch (op) { case BinOpr.OPR_AND: { LuaKGoIfTrue(fs, v); break; } case BinOpr.OPR_OR: { LuaKGoIFalse(fs, v); break; } case BinOpr.OPR_CONCAT: { LuaKExp2NextReg(fs, v); /* operand must be on the `stack' */ break; } case BinOpr.OPR_ADD: case BinOpr.OPR_SUB: case BinOpr.OPR_MUL: case BinOpr.OPR_DIV: case BinOpr.OPR_MOD: case BinOpr.OPR_POW: { if ((IsNumeral(v)==0)) LuaKExp2RK(fs, v); break; } default: { LuaKExp2RK(fs, v); break; } } }
public static void LuaKIndexed (FuncState fs, expdesc t, expdesc k) { t.u.s.aux = LuaKExp2RK(fs, k); t.k = expkind.VINDEXED; }
private static int constfolding(OpCode op, expdesc e1, expdesc e2) { lua_Number v1, v2, r; if ((isnumeral(e1) == 0) || (isnumeral(e2) == 0)) { return(0); } v1 = e1.u.nval; v2 = e2.u.nval; switch (op) { case OpCode.OP_ADD: r = luai_numadd(v1, v2); break; case OpCode.OP_SUB: r = luai_numsub(v1, v2); break; case OpCode.OP_MUL: r = luai_nummul(v1, v2); break; case OpCode.OP_RSHIFT: r = luai_numrshift(v1, v2); break; case OpCode.OP_LSHIFT: r = luai_numlshift(v1, v2); break; case OpCode.OP_BITAND: r = luai_numbitand(v1, v2); break; case OpCode.OP_BITOR: r = luai_numbitor(v1, v2); break; case OpCode.OP_DIV: if (v2 == 0) { return(0); /* do not attempt to divide by 0 */ } r = luai_numdiv(v1, v2); break; case OpCode.OP_MOD: if (v2 == 0) { return(0); /* do not attempt to divide by 0 */ } r = luai_nummod(v1, v2); break; case OpCode.OP_POW: r = luai_numpow(v1, v2); break; case OpCode.OP_UNM: r = luai_numunm(v1); break; case OpCode.OP_LEN: return(0); /* no constant folding for 'len' */ default: lua_assert(0); r = 0; break; } if (luai_numisnan(r)) { return(0); /* do not attempt to produce NaN */ } e1.u.nval = r; return(1); }
private static void CodeArith (FuncState fs, OpCode op, expdesc e1, expdesc e2) { if (ConstFolding(op, e1, e2) != 0) return; else { int o2 = (op != OpCode.OP_UNM && op != OpCode.OP_LEN) ? LuaKExp2RK(fs, e2) : 0; int o1 = LuaKExp2RK(fs, e1); if (o1 > o2) { FreeExp(fs, e1); FreeExp(fs, e2); } else { FreeExp(fs, e2); FreeExp(fs, e1); } e1.u.s.info = LuaKCodeABC(fs, op, 0, o1, o2); e1.k = expkind.VRELOCABLE; } }
public static InstructionPtr GetCode(FuncState fs, expdesc e) {return new InstructionPtr(fs.f.code, e.u.s.info);}
public static void LuaKPrefix (FuncState fs, UnOpr op, expdesc e) { expdesc e2 = new expdesc(); e2.t = e2.f = NO_JUMP; e2.k = expkind.VKNUM; e2.u.nval = 0; switch (op) { case UnOpr.OPR_MINUS: { if (IsNumeral(e)==0) LuaKExp2AnyReg(fs, e); /* cannot operate on non-numeric constants */ CodeArith(fs, OpCode.OP_UNM, e, e2); break; } case UnOpr.OPR_NOT: CodeNot(fs, e); break; case UnOpr.OPR_LEN: { LuaKExp2AnyReg(fs, e); /* cannot operate on constants */ CodeArith(fs, OpCode.OP_LEN, e, e2); break; } default: LuaAssert(0); break; } }
public static void LuaKSetMultRet(FuncState fs, expdesc e) {LuaKSetReturns(fs, e, LUA_MULTRET);}
public static void LuaKPosFix (FuncState fs, BinOpr op, expdesc e1, expdesc e2) { switch (op) { case BinOpr.OPR_AND: { LuaAssert(e1.t == NO_JUMP); /* list must be closed */ LuaKDischargeVars(fs, e2); LuaKConcat(fs, ref e2.f, e1.f); e1.Copy(e2); break; } case BinOpr.OPR_OR: { LuaAssert(e1.f == NO_JUMP); /* list must be closed */ LuaKDischargeVars(fs, e2); LuaKConcat(fs, ref e2.t, e1.t); e1.Copy(e2); break; } case BinOpr.OPR_CONCAT: { LuaKExp2Val(fs, e2); if (e2.k == expkind.VRELOCABLE && GET_OPCODE(GetCode(fs, e2)) == OpCode.OP_CONCAT) { LuaAssert(e1.u.s.info == GETARG_B(GetCode(fs, e2))-1); FreeExp(fs, e1); SETARG_B(GetCode(fs, e2), e1.u.s.info); e1.k = expkind.VRELOCABLE; e1.u.s.info = e2.u.s.info; } else { LuaKExp2NextReg(fs, e2); /* operand must be on the 'stack' */ CodeArith(fs, OpCode.OP_CONCAT, e1, e2); } break; } case BinOpr.OPR_ADD: CodeArith(fs, OpCode.OP_ADD, e1, e2); break; case BinOpr.OPR_SUB: CodeArith(fs, OpCode.OP_SUB, e1, e2); break; case BinOpr.OPR_MUL: CodeArith(fs, OpCode.OP_MUL, e1, e2); break; case BinOpr.OPR_DIV: CodeArith(fs, OpCode.OP_DIV, e1, e2); break; case BinOpr.OPR_MOD: CodeArith(fs, OpCode.OP_MOD, e1, e2); break; case BinOpr.OPR_POW: CodeArith(fs, OpCode.OP_POW, e1, e2); break; case BinOpr.OPR_EQ: CodeComp(fs, OpCode.OP_EQ, 1, e1, e2); break; case BinOpr.OPR_NE: CodeComp(fs, OpCode.OP_EQ, 0, e1, e2); break; case BinOpr.OPR_LT: CodeComp(fs, OpCode.OP_LT, 1, e1, e2); break; case BinOpr.OPR_LE: CodeComp(fs, OpCode.OP_LE, 1, e1, e2); break; case BinOpr.OPR_GT: CodeComp(fs, OpCode.OP_LT, 0, e1, e2); break; case BinOpr.OPR_GE: CodeComp(fs, OpCode.OP_LE, 0, e1, e2); break; default: LuaAssert(0); break; } }
public static bool HasJumps(expdesc e) {return e.t != e.f;}