public static void StoreVar(FuncState fs, ExpDesc v, ExpDesc e) { switch (v.Kind) { case ExpKind.VLOCAL: { FreeExp(fs, e); Exp2Reg(fs, e, v.Info); break; } case ExpKind.VUPVAL: { int c = Exp2AnyReg(fs, e); CodeABC(fs, OpCode.OP_SETUPVAL, c, v.Info, 0); break; } case ExpKind.VINDEXED: { OpCode op = (v.Ind.Vt == ExpKind.VLOCAL) ? OpCode.OP_SETTABLE : OpCode.OP_SETTABUP; int c = Exp2RK(fs, e); CodeABC(fs, op, v.Ind.T, v.Ind.Idx, c); break; } default: { throw new NotImplementedException("invalid var kind to store"); } } FreeExp(fs, e); }
public static void Exp2AnyRegUp(FuncState fs, ExpDesc e) { if (e.Kind != ExpKind.VUPVAL || HasJumps(e)) { Exp2AnyReg(fs, e); } }
public static void Exp2NextReg(FuncState fs, ExpDesc e) { DischargeVars(fs, e); FreeExp(fs, e); ReserveRegs(fs, 1); Exp2Reg(fs, e, fs.FreeReg - 1); }
private static void FreeExp(FuncState fs, ExpDesc e) { if (e.Kind == ExpKind.VNONRELOC) { FreeReg(fs, e.Info); } }
private static void CodeArith(FuncState fs, OpCode op, ExpDesc e1, ExpDesc e2, int line) { if (ConstFolding(op, e1, e2)) { return; } int o2 = (op != OpCode.OP_UNM && op != OpCode.OP_LEN) ? Exp2RK(fs, e2) : 0; int o1 = Exp2RK(fs, e1); if (o1 > o2) { FreeExp(fs, e1); FreeExp(fs, e2); } else { FreeExp(fs, e2); FreeExp(fs, e1); } e1.Info = CodeABC(fs, op, 0, o1, o2); e1.Kind = ExpKind.VRELOCABLE; FixLine(fs, line); }
private static void Exp2Reg(FuncState fs, ExpDesc e, int reg) { Discharge2Reg(fs, e, reg); if (e.Kind == ExpKind.VJMP) { e.ExitTrue = Concat(fs, e.ExitTrue, e.Info); } if (HasJumps(e)) { int p_f = NO_JUMP; int p_t = NO_JUMP; if (NeedValue(fs, e.ExitTrue) || NeedValue(fs, e.ExitFalse)) { int fj = (e.Kind == ExpKind.VJMP) ? NO_JUMP : Jump(fs); p_f = CodeLabel(fs, reg, 0, 1); p_t = CodeLabel(fs, reg, 1, 0); PatchToHere(fs, fj); } // position after whole expression int final = GetLabel(fs); PatchListAux(fs, e.ExitFalse, final, reg, p_f); PatchListAux(fs, e.ExitTrue, final, reg, p_t); } e.ExitFalse = NO_JUMP; e.ExitTrue = NO_JUMP; e.Info = reg; e.Kind = ExpKind.VNONRELOC; }
public static void GoIfTrue(FuncState fs, ExpDesc e) { int pc; // pc of last jump DischargeVars(fs, e); switch (e.Kind) { case ExpKind.VJMP: InvertJump(fs, e); pc = e.Info; break; case ExpKind.VK: case ExpKind.VKNUM: case ExpKind.VTRUE: pc = NO_JUMP; break; default: pc = JumpOnCond(fs, e, false); break; } // insert last jump in `f' list e.ExitFalse = Concat(fs, e.ExitFalse, pc); PatchToHere(fs, e.ExitTrue); e.ExitTrue = NO_JUMP; }
public static void GoIfFalse(FuncState fs, ExpDesc e) { int pc; // pc of last jump DischargeVars(fs, e); switch (e.Kind) { case ExpKind.VJMP: pc = e.Info; break; case ExpKind.VNIL: case ExpKind.VFALSE: pc = NO_JUMP; break; default: pc = JumpOnCond(fs, e, true); break; } // insert last jump in `t' list e.ExitTrue = Concat(fs, e.ExitTrue, pc); PatchToHere(fs, e.ExitFalse); e.ExitFalse = NO_JUMP; }
public static void DischargeVars(FuncState fs, ExpDesc e) { switch (e.Kind) { case ExpKind.VLOCAL: e.Kind = ExpKind.VNONRELOC; break; case ExpKind.VUPVAL: e.Info = CodeABC(fs, OpCode.OP_GETUPVAL, 0, e.Info, 0); e.Kind = ExpKind.VRELOCABLE; break; case ExpKind.VINDEXED: OpCode op = OpCode.OP_GETTABUP; FreeReg(fs, e.Ind.Idx); if (e.Ind.Vt == ExpKind.VLOCAL) { FreeReg(fs, e.Ind.T); op = OpCode.OP_GETTABLE; } e.Info = CodeABC(fs, op, 0, e.Ind.T, e.Ind.Idx); e.Kind = ExpKind.VRELOCABLE; break; case ExpKind.VVARARG: case ExpKind.VCALL: SetOneRet(fs, e); break; default: break; } }
public static void Infix(FuncState fs, BinOpr op, ExpDesc e) { switch (op) { case BinOpr.AND: { GoIfTrue(fs, e); } break; case BinOpr.OR: { GoIfFalse(fs, e); } break; case BinOpr.CONCAT: { Exp2NextReg(fs, e); // operand must be on the `stack' } break; case BinOpr.ADD: case BinOpr.SUB: case BinOpr.MUL: case BinOpr.DIV: case BinOpr.MOD: case BinOpr.POW: { if (!IsNumeral(e)) { Exp2RK(fs, e); } } break; default: { Exp2RK(fs, e); } break; } }
private static void Discharge2AnyReg(FuncState fs, ExpDesc e) { if (e.Kind != ExpKind.VNONRELOC) { ReserveRegs(fs, 1); Discharge2Reg(fs, e, fs.FreeReg - 1); } }
public static void Indexed(FuncState fs, ExpDesc t, ExpDesc k) { t.Ind.T = t.Info; t.Ind.Idx = Exp2RK(fs, k); t.Ind.Vt = (t.Kind == ExpKind.VUPVAL) ? ExpKind.VUPVAL : ExpKind.VLOCAL; // FIXME t.Kind = ExpKind.VINDEXED; }
private static void InvertJump(FuncState fs, ExpDesc e) { InstructionPtr pc = GetJumpControl(fs, e.Info); Utl.Assert(TestTMode(pc.Value.GET_OPCODE()) && pc.Value.GET_OPCODE() != OpCode.OP_TESTSET && pc.Value.GET_OPCODE() != OpCode.OP_TEST); pc.Value = pc.Value.SETARG_A(pc.Value.GETARG_A() == 0 ? 1 : 0); }
private static void Discharge2Reg(FuncState fs, ExpDesc e, int reg) { DischargeVars(fs, e); switch (e.Kind) { case ExpKind.VNIL: { CodeNil(fs, reg, 1); break; } case ExpKind.VFALSE: case ExpKind.VTRUE: { CodeABC(fs, OpCode.OP_LOADBOOL, reg, (e.Kind == ExpKind.VTRUE ? 1 : 0), 0); break; } case ExpKind.VK: { CodeK(fs, reg, e.Info); break; } case ExpKind.VKNUM: { CodeK(fs, reg, NumberK(fs, e.NumberValue)); break; } case ExpKind.VRELOCABLE: { InstructionPtr pi = fs.GetCode(e); pi.Value = pi.Value.SETARG_A(reg); break; } case ExpKind.VNONRELOC: { if (reg != e.Info) { CodeABC(fs, OpCode.OP_MOVE, reg, e.Info, 0); } break; } default: { Utl.Assert(e.Kind == ExpKind.VVOID || e.Kind == ExpKind.VJMP); return; // nothing to do... } } e.Info = reg; e.Kind = ExpKind.VNONRELOC; }
public static void Exp2Val(FuncState fs, ExpDesc e) { if (HasJumps(e)) { Exp2AnyReg(fs, e); } else { DischargeVars(fs, e); } }
public static void Self(FuncState fs, ExpDesc e, ExpDesc key) { Exp2AnyReg(fs, e); int ereg = e.Info; // register where `e' is placed FreeExp(fs, e); e.Info = fs.FreeReg; // base register for op_self e.Kind = ExpKind.VNONRELOC; ReserveRegs(fs, 2); CodeABC(fs, OpCode.OP_SELF, e.Info, ereg, Coder.Exp2RK(fs, key)); FreeExp(fs, key); }
public static void SetReturns(FuncState fs, ExpDesc e, int nResults) { if (e.Kind == ExpKind.VCALL) // expression is an open function call? { var pi = fs.GetCode(e); pi.Value = pi.Value.SETARG_C(nResults + 1); } else if (e.Kind == ExpKind.VVARARG) { var pi = fs.GetCode(e); pi.Value = pi.Value.SETARG_B(nResults + 1).SETARG_A(fs.FreeReg); ReserveRegs(fs, 1); } }
private static bool ConstFolding(OpCode op, ExpDesc e1, ExpDesc e2) { if (!IsNumeral(e1) || !IsNumeral(e2)) { return(false); } if ((op == OpCode.OP_DIV || op == OpCode.OP_MOD) && e2.NumberValue == 0.0) { return(false); // do not attempt to divide by 0 } switch (op) { case OpCode.OP_ADD: e1.NumberValue = e1.NumberValue + e2.NumberValue; break; case OpCode.OP_SUB: e1.NumberValue = e1.NumberValue - e2.NumberValue; break; case OpCode.OP_MUL: e1.NumberValue = e1.NumberValue * e2.NumberValue; break; case OpCode.OP_DIV: e1.NumberValue = e1.NumberValue / e2.NumberValue; break; case OpCode.OP_MOD: e1.NumberValue = Utl.LuaMod(e1.NumberValue, e2.NumberValue); break; case OpCode.OP_POW: e1.NumberValue = Math.Pow(e1.NumberValue, e2.NumberValue); break; case OpCode.OP_UNM: e1.NumberValue = -e1.NumberValue; break; default: throw new Exception("ConstFolding unknown op" + op); } return(true); }
public static void SetOneRet(FuncState fs, ExpDesc e) { // expression is an open function call? if (e.Kind == ExpKind.VCALL) { e.Kind = ExpKind.VNONRELOC; e.Info = (fs.GetCode(e)).Value.GETARG_A(); } else if (e.Kind == ExpKind.VVARARG) { var pi = fs.GetCode(e); pi.Value = pi.Value.SETARG_B(2); e.Kind = ExpKind.VRELOCABLE; // can relocate its simple result } }
public static int Exp2RK(FuncState fs, ExpDesc e) { Exp2Val(fs, e); switch (e.Kind) { case ExpKind.VTRUE: case ExpKind.VFALSE: case ExpKind.VNIL: { // constant fits in RK operand? if (fs.Proto.K.Count <= Instruction.MAXINDEXRK) { e.Info = (e.Kind == ExpKind.VNIL) ? NilK(fs) : BoolK(fs, (e.Kind == ExpKind.VTRUE)); e.Kind = ExpKind.VK; return(Instruction.RKASK(e.Info)); } else { break; } } case ExpKind.VKNUM: case ExpKind.VK: { if (e.Kind == ExpKind.VKNUM) { e.Info = NumberK(fs, e.NumberValue); e.Kind = ExpKind.VK; } if (e.Info <= Instruction.MAXINDEXRK) { return(Instruction.RKASK(e.Info)); } else { break; } } default: break; } return(Exp2AnyReg(fs, e)); }
private static int JumpOnCond(FuncState fs, ExpDesc e, bool cond) { if (e.Kind == ExpKind.VRELOCABLE) { Instruction ie = fs.GetCode(e).Value; if (ie.GET_OPCODE() == OpCode.OP_NOT) { fs.Pc--; // remove previous OP_NOT return(CondJump(fs, OpCode.OP_TEST, ie.GETARG_B(), 0, (cond ? 0 : 1))); } // else go through } Discharge2AnyReg(fs, e); FreeExp(fs, e); return(CondJump(fs, OpCode.OP_TESTSET, NO_REG, e.Info, (cond ? 1 : 0))); }
private static void CodeComp(FuncState fs, OpCode op, int cond, ExpDesc e1, ExpDesc e2) { int o1 = Exp2RK(fs, e1); int o2 = Exp2RK(fs, e2); FreeExp(fs, e2); FreeExp(fs, e1); // exchange args to replace by `<' or `<=' if (cond == 0 && op != OpCode.OP_EQ) { int temp; temp = o1; o1 = o2; o2 = temp; // o1 <==> o2 cond = 1; } e1.Info = CondJump(fs, op, cond, o1, o2); e1.Kind = ExpKind.VJMP; }
public static void Prefix(FuncState fs, UnOpr op, ExpDesc e, int line) { ExpDesc e2 = new ExpDesc(); e2.ExitTrue = NO_JUMP; e2.ExitFalse = NO_JUMP; e2.Kind = ExpKind.VKNUM; e2.NumberValue = 0.0; switch (op) { case UnOpr.MINUS: { if (IsNumeral(e)) // minus constant? { e.NumberValue = -e.NumberValue; } else { Exp2AnyReg(fs, e); CodeArith(fs, OpCode.OP_UNM, e, e2, line); } } break; case UnOpr.NOT: { CodeNot(fs, e); } break; case UnOpr.LEN: { Exp2AnyReg(fs, e); // cannot operate on constants CodeArith(fs, OpCode.OP_LEN, e, e2, line); } break; default: throw new Exception("[Coder]Prefix Unknown UnOpr:" + op); } }
public static int Exp2AnyReg(FuncState fs, ExpDesc e) { DischargeVars(fs, e); if (e.Kind == ExpKind.VNONRELOC) { // exp is already in a register if (!HasJumps(e)) { return(e.Info); } // reg. is not a local? if (e.Info >= fs.NumActVar) { Exp2Reg(fs, e, e.Info); return(e.Info); } } Exp2NextReg(fs, e); // default return(e.Info); }
private static void CodeNot(FuncState fs, ExpDesc e) { DischargeVars(fs, e); switch (e.Kind) { case ExpKind.VNIL: case ExpKind.VFALSE: e.Kind = ExpKind.VTRUE; break; case ExpKind.VK: case ExpKind.VKNUM: case ExpKind.VTRUE: e.Kind = ExpKind.VFALSE; break; case ExpKind.VJMP: InvertJump(fs, e); break; case ExpKind.VRELOCABLE: case ExpKind.VNONRELOC: Discharge2AnyReg(fs, e); FreeExp(fs, e); e.Info = CodeABC(fs, OpCode.OP_NOT, 0, e.Info, 0); e.Kind = ExpKind.VRELOCABLE; break; default: throw new Exception("CodeNot unknown e.Kind:" + e.Kind); } // interchange true and false lists { int temp = e.ExitFalse; e.ExitFalse = e.ExitTrue; e.ExitTrue = temp; } RemoveValues(fs, e.ExitFalse); RemoveValues(fs, e.ExitTrue); }
public static void DischargeVars( FuncState fs, ExpDesc e ) { switch( e.Kind ) { case ExpKind.VLOCAL: e.Kind = ExpKind.VNONRELOC; break; case ExpKind.VUPVAL: e.Info = CodeABC( fs, OpCode.OP_GETUPVAL, 0, e.Info, 0 ); e.Kind = ExpKind.VRELOCABLE; break; case ExpKind.VINDEXED: OpCode op = OpCode.OP_GETTABUP; FreeReg( fs, e.Ind.Idx ); if( e.Ind.Vt == ExpKind.VLOCAL ) { FreeReg( fs, e.Ind.T ); op = OpCode.OP_GETTABLE; } e.Info = CodeABC( fs, op, 0, e.Ind.T, e.Ind.Idx ); e.Kind = ExpKind.VRELOCABLE; break; case ExpKind.VVARARG: case ExpKind.VCALL: SetOneRet( fs, e ); break; default: break; } }
public static void Exp2AnyRegUp( FuncState fs, ExpDesc e ) { if( e.Kind != ExpKind.VUPVAL || HasJumps( e ) ) { Exp2AnyReg( fs, e ); } }
public static void SetMultiRet(FuncState fs, ExpDesc e) { SetReturns(fs, e, LuaDef.LUA_MULTRET); }
private static bool IsNumeral(ExpDesc e) { return(e.Kind == ExpKind.VKNUM && e.ExitTrue == NO_JUMP && e.ExitFalse == NO_JUMP); }
private static int JumpOnCond( FuncState fs, ExpDesc e, bool cond ) { // Debug.Log("--------------- 2 ----------JumpOnCond k:" + e.Kind ); if( e.Kind == ExpKind.VRELOCABLE ) { Instruction ie = fs.GetCode( e ).Value; if( ie.GET_OPCODE() == OpCode.OP_NOT ) { fs.Pc--; // remove previous OP_NOT return CondJump( fs, OpCode.OP_TEST, ie.GETARG_B(), 0, (cond ? 0 : 1) ); } // else go through } Discharge2AnyReg( fs, e ); FreeExp( fs, e ); return CondJump( fs, OpCode.OP_TESTSET, NO_REG, e.Info, (cond ? 1 : 0) ); }
private static void CodeArith( FuncState fs, OpCode op, ExpDesc e1, ExpDesc e2, int line ) { if( ConstFolding( op, e1, e2 ) ) return; int o2 = ( op != OpCode.OP_UNM && op != OpCode.OP_LEN ) ? Exp2RK( fs, e2 ) : 0; int o1 = Exp2RK( fs, e1 ); // Debug.Log("CODE ARITH o1:" + o1 + " o2:" + o2 + // " fs.FreeReg:" + fs.FreeReg + // "\ne1.k:" + e1.Kind + // "\ne2.k:" + e2.Kind); if( o1 > o2 ) { FreeExp( fs, e1 ); FreeExp( fs, e2 ); } else { FreeExp( fs, e2 ); FreeExp( fs, e1 ); } e1.Info = CodeABC( fs, op, 0, o1, o2 ); e1.Kind = ExpKind.VRELOCABLE; FixLine( fs, line ); }
private static bool IsNumeral( ExpDesc e ) { return e.Kind == ExpKind.VKNUM && e.ExitTrue == NO_JUMP && e.ExitFalse == NO_JUMP; }
public static void Self( FuncState fs, ExpDesc e, ExpDesc key ) { Exp2AnyReg( fs, e ); int ereg = e.Info; // register where `e' is placed FreeExp( fs, e ); e.Info = fs.FreeReg; // base register for op_self e.Kind = ExpKind.VNONRELOC; ReserveRegs( fs, 2 ); CodeABC( fs, OpCode.OP_SELF, e.Info, ereg, Coder.Exp2RK(fs, key) ); FreeExp( fs, key ); }
public static void SetOneRet( FuncState fs, ExpDesc e ) { // expression is an open function call? if( e.Kind == ExpKind.VCALL ) { e.Kind = ExpKind.VNONRELOC; e.Info = ( fs.GetCode( e ) ).Value.GETARG_A(); } else if( e.Kind == ExpKind.VVARARG ) { var pi = fs.GetCode( e ); pi.Value = pi.Value.SETARG_B( 2 ); e.Kind = ExpKind.VRELOCABLE; // can relocate its simple result } }
public static void SetReturns( FuncState fs, ExpDesc e, int nResults ) { if( e.Kind == ExpKind.VCALL ) { // expression is an open function call? var pi = fs.GetCode(e); pi.Value = pi.Value.SETARG_C( nResults+1 ); } else if( e.Kind == ExpKind.VVARARG ) { var pi = fs.GetCode(e); pi.Value = pi.Value.SETARG_B( nResults+1 ).SETARG_A( fs.FreeReg ); ReserveRegs( fs, 1 ); } }
// stat -> LOCAL NAME {`,' NAME} [`=' explist] private void LocalStat() { int nvars = 0; int nexps; var e = new ExpDesc(); do { var v = NewLocalVar( CheckName() ); ActVars.Add(v); ++nvars; } while( TestNext( (int)',' ) ); if( TestNext( (int)'=' ) ) nexps = ExpList( e ); else { e.Kind = ExpKind.VVOID; nexps = 0; } AdjustAssign( nvars, nexps, e ); AdjustLocalVars( nvars ); }
public static void SetMultiRet( FuncState fs, ExpDesc e ) { SetReturns( fs, e, LuaDef.LUA_MULTRET ); }
public static void Indexed( FuncState fs, ExpDesc t, ExpDesc k ) { t.Ind.T = t.Info; t.Ind.Idx = Exp2RK( fs, k ); t.Ind.Vt = (t.Kind == ExpKind.VUPVAL) ? ExpKind.VUPVAL : ExpKind.VLOCAL; // FIXME t.Kind = ExpKind.VINDEXED; }
public static void StoreVar( FuncState fs, ExpDesc v, ExpDesc e ) { switch( v.Kind ) { case ExpKind.VLOCAL: { FreeExp( fs, e ); Exp2Reg( fs, e, v.Info ); break; } case ExpKind.VUPVAL: { int c = Exp2AnyReg( fs, e ); // Debug.Log("SETUPVAL " + c + " " + v.Info); CodeABC( fs, OpCode.OP_SETUPVAL, c, v.Info, 0 ); break; } case ExpKind.VINDEXED: { OpCode op = (v.Ind.Vt == ExpKind.VLOCAL) ? OpCode.OP_SETTABLE : OpCode.OP_SETTABUP; int c = Exp2RK( fs, e ); CodeABC( fs, op, v.Ind.T, v.Ind.Idx, c ); break; } default: { throw new NotImplementedException("invalid var kind to store"); } } FreeExp( fs, e ); }
private static void Discharge2Reg( FuncState fs, ExpDesc e, int reg ) { DischargeVars( fs, e ); switch( e.Kind ) { case ExpKind.VNIL: { CodeNil( fs, reg, 1 ); break; } case ExpKind.VFALSE: case ExpKind.VTRUE: { CodeABC( fs, OpCode.OP_LOADBOOL, reg, (e.Kind == ExpKind.VTRUE ? 1 : 0), 0 ); break; } case ExpKind.VK: { CodeK( fs, reg, e.Info ); break; } case ExpKind.VKNUM: { CodeK( fs, reg, NumberK( fs, e.NumberValue ) ); break; } case ExpKind.VRELOCABLE: { InstructionPtr pi = fs.GetCode(e); pi.Value = pi.Value.SETARG_A(reg); break; } case ExpKind.VNONRELOC: { if( reg != e.Info ) CodeABC( fs, OpCode.OP_MOVE, reg, e.Info, 0 ); break; } default: { Utl.Assert( e.Kind == ExpKind.VVOID || e.Kind == ExpKind.VJMP ); return; // nothing to do... } } e.Info = reg; e.Kind = ExpKind.VNONRELOC; }
private static void FreeExp( FuncState fs, ExpDesc e ) { // Debug.Log("--------------- 3 ----------FreeExp k:" + e.Kind ); if( e.Kind == ExpKind.VNONRELOC ) { FreeReg( fs, e.Info ); } }
private static void Exp2Reg( FuncState fs, ExpDesc e, int reg ) { Discharge2Reg( fs, e, reg ); if( e.Kind == ExpKind.VJMP ) { e.ExitTrue = Concat( fs, e.ExitTrue, e.Info ); } if( HasJumps(e) ) { int p_f = NO_JUMP; int p_t = NO_JUMP; if( NeedValue( fs, e.ExitTrue ) || NeedValue( fs, e.ExitFalse ) ) { int fj = (e.Kind == ExpKind.VJMP) ? NO_JUMP : Jump( fs ); p_f = CodeLabel( fs, reg, 0, 1 ); p_t = CodeLabel( fs, reg, 1, 0 ); PatchToHere( fs, fj ); } // position after whole expression int final = GetLabel( fs ); PatchListAux( fs, e.ExitFalse, final, reg, p_f ); PatchListAux( fs, e.ExitTrue, final, reg, p_t ); } e.ExitFalse = NO_JUMP; e.ExitTrue = NO_JUMP; e.Info = reg; e.Kind = ExpKind.VNONRELOC; }
private static bool ConstFolding( OpCode op, ExpDesc e1, ExpDesc e2 ) { if( !IsNumeral(e1) || !IsNumeral(e2) ) return false; if( (op == OpCode.OP_DIV || op == OpCode.OP_MOD) && e2.NumberValue == 0.0 ) { return false; // do not attempt to divide by 0 } switch( op ) { case OpCode.OP_ADD: e1.NumberValue = e1.NumberValue + e2.NumberValue; break; case OpCode.OP_SUB: e1.NumberValue = e1.NumberValue - e2.NumberValue; break; case OpCode.OP_MUL: e1.NumberValue = e1.NumberValue * e2.NumberValue; break; case OpCode.OP_DIV: e1.NumberValue = e1.NumberValue / e2.NumberValue; break; case OpCode.OP_MOD: e1.NumberValue = e1.NumberValue % e2.NumberValue; break; case OpCode.OP_POW: e1.NumberValue = Math.Pow( e1.NumberValue, e2.NumberValue ); break; case OpCode.OP_UNM: e1.NumberValue = -e1.NumberValue; break; default: throw new Exception("ConstFolding unknown op" + op); } return true; }
public static void GoIfFalse( FuncState fs, ExpDesc e ) { // Debug.Log("GoIfFalse k:" + e.Kind ); int pc; // pc of last jump DischargeVars( fs, e ); switch( e.Kind ) { case ExpKind.VJMP: pc = e.Info; break; case ExpKind.VNIL: case ExpKind.VFALSE: pc = NO_JUMP; break; default: pc = JumpOnCond( fs, e, true ); break; } // insert last jump in `t' list e.ExitTrue = Concat( fs, e.ExitTrue, pc ); PatchToHere( fs, e.ExitFalse ); e.ExitFalse = NO_JUMP; }
private static void InvertJump( FuncState fs, ExpDesc e ) { InstructionPtr pc = GetJumpControl( fs, e.Info ); Utl.Assert( TestTMode( pc.Value.GET_OPCODE() ) && pc.Value.GET_OPCODE() != OpCode.OP_TESTSET && pc.Value.GET_OPCODE() != OpCode.OP_TEST ); pc.Value = pc.Value.SETARG_A( pc.Value.GETARG_A() == 0 ? 1 : 0 ); }
private static void CodeComp( FuncState fs, OpCode op, int cond, ExpDesc e1, ExpDesc e2 ) { int o1 = Exp2RK( fs, e1 ); int o2 = Exp2RK( fs, e2 ); FreeExp( fs, e2 ); FreeExp( fs, e1 ); // exchange args to replace by `<' or `<=' if( cond == 0 && op != OpCode.OP_EQ ) { int temp; temp = o1; o1 = o2; o2 = temp; // o1 <==> o2 cond = 1; } e1.Info = CondJump( fs, op, cond, o1, o2 ); e1.Kind = ExpKind.VJMP; }
public static void GoIfTrue( FuncState fs, ExpDesc e ) { // Debug.Log("--------------- 1 ----------GoIfTrue k:" + e.Kind ); int pc; // pc of last jump DischargeVars( fs, e ); switch( e.Kind ) { case ExpKind.VJMP: InvertJump( fs, e ); pc = e.Info; break; case ExpKind.VK: case ExpKind.VKNUM: case ExpKind.VTRUE: pc = NO_JUMP; break; default: pc = JumpOnCond( fs, e, false ); break; } // insert last jump in `f' list e.ExitFalse = Concat( fs, e.ExitFalse, pc ); PatchToHere( fs, e.ExitTrue ); e.ExitTrue = NO_JUMP; }
public static void Infix( FuncState fs, BinOpr op, ExpDesc e ) { // Debug.Log(">> INFIX op:" + op); switch( op ) { case BinOpr.AND: { GoIfTrue( fs, e ); } break; case BinOpr.OR: { GoIfFalse( fs, e ); } break; case BinOpr.CONCAT: { Exp2NextReg( fs, e ); // operand must be on the `stack' } break; case BinOpr.ADD: case BinOpr.SUB: case BinOpr.MUL: case BinOpr.DIV: case BinOpr.MOD: case BinOpr.POW: { if( !IsNumeral(e) ) Exp2RK( fs, e ); } break; default: { Exp2RK( fs, e ); } break; } }
private static void CodeNot( FuncState fs, ExpDesc e ) { DischargeVars( fs, e ); switch( e.Kind ) { case ExpKind.VNIL: case ExpKind.VFALSE: e.Kind = ExpKind.VTRUE; break; case ExpKind.VK: case ExpKind.VKNUM: case ExpKind.VTRUE: e.Kind = ExpKind.VFALSE; break; case ExpKind.VJMP: InvertJump( fs, e ); break; case ExpKind.VRELOCABLE: case ExpKind.VNONRELOC: Discharge2AnyReg( fs, e ); FreeExp( fs, e ); e.Info = CodeABC( fs, OpCode.OP_NOT, 0, e.Info, 0 ); e.Kind = ExpKind.VRELOCABLE; break; default: throw new Exception("CodeNot unknown e.Kind:" + e.Kind); } // interchange true and false lists { int temp = e.ExitFalse; e.ExitFalse = e.ExitTrue; e.ExitTrue = temp; } RemoveValues( fs, e.ExitFalse ); RemoveValues( fs, e.ExitTrue ); }
public static void Exp2Val( FuncState fs, ExpDesc e ) { if( HasJumps(e) ) Exp2AnyReg( fs, e ); else DischargeVars( fs, e ); }
public static void Prefix( FuncState fs, UnOpr op, ExpDesc e, int line ) { ExpDesc e2 = new ExpDesc(); e2.ExitTrue = NO_JUMP; e2.ExitFalse = NO_JUMP; e2.Kind = ExpKind.VKNUM; e2.NumberValue = 0.0; switch( op ) { case UnOpr.MINUS: { if( IsNumeral( e ) ) // minus constant? { e.NumberValue = -e.NumberValue; } else { Exp2AnyReg( fs, e ); CodeArith( fs, OpCode.OP_UNM, e, e2, line ); } } break; case UnOpr.NOT: { CodeNot( fs, e ); } break; case UnOpr.LEN: { Exp2AnyReg( fs, e ); // cannot operate on constants CodeArith( fs, OpCode.OP_LEN, e, e2, line ); } break; default: throw new Exception("[Coder]Prefix Unknown UnOpr:" + op); } }
public static int Exp2RK( FuncState fs, ExpDesc e ) { Exp2Val( fs, e ); switch( e.Kind ) { case ExpKind.VTRUE: case ExpKind.VFALSE: case ExpKind.VNIL: { // constant fits in RK operand? if( fs.Proto.K.Count <= Instruction.MAXINDEXRK ) { e.Info = (e.Kind == ExpKind.VNIL) ? NilK(fs) : BoolK( fs, (e.Kind == ExpKind.VTRUE ) ); e.Kind = ExpKind.VK; return Instruction.RKASK( e.Info ); } else break; } case ExpKind.VKNUM: case ExpKind.VK: { if( e.Kind == ExpKind.VKNUM ) { e.Info = NumberK( fs, e.NumberValue ); e.Kind = ExpKind.VK; } if( e.Info <= Instruction.MAXINDEXRK ) return Instruction.RKASK( e.Info ); else break; } default: break; } return Exp2AnyReg( fs, e ); }
public static void Posfix( FuncState fs, BinOpr op, ExpDesc e1, ExpDesc e2, int line ) { // Debug.Log(">> POSFIX op:" + op); switch( op ) { case BinOpr.AND: { Utl.Assert( e1.ExitTrue == NO_JUMP ); DischargeVars( fs, e2 ); e2.ExitFalse = Concat( fs, e2.ExitFalse, e1.ExitFalse ); e1.CopyFrom( e2 ); break; } case BinOpr.OR: { Utl.Assert( e1.ExitFalse == NO_JUMP ); DischargeVars( fs, e2 ); e2.ExitTrue = Concat( fs, e2.ExitTrue, e1.ExitTrue ); e1.CopyFrom( e2 ); break; } case BinOpr.CONCAT: { Exp2Val( fs, e2 ); var pe2 = fs.GetCode( e2 ); if( e2.Kind == ExpKind.VRELOCABLE && pe2.Value.GET_OPCODE() == OpCode.OP_CONCAT ) { Utl.Assert( e1.Info == pe2.Value.GETARG_B()-1 ); FreeExp( fs, e1 ); pe2.Value = pe2.Value.SETARG_B( e1.Info ); e1.Kind = ExpKind.VRELOCABLE; e1.Info = e2.Info; } else { // operand must be on the `stack' Exp2NextReg( fs, e2 ); CodeArith( fs, OpCode.OP_CONCAT, e1, e2, line ); } break; } case BinOpr.ADD: { CodeArith( fs, OpCode.OP_ADD, e1, e2, line); break; } case BinOpr.SUB: { CodeArith( fs, OpCode.OP_SUB, e1, e2, line); break; } case BinOpr.MUL: { CodeArith( fs, OpCode.OP_MUL, e1, e2, line); break; } case BinOpr.DIV: { CodeArith( fs, OpCode.OP_DIV, e1, e2, line); break; } case BinOpr.MOD: { CodeArith( fs, OpCode.OP_MOD, e1, e2, line); break; } case BinOpr.POW: { CodeArith( fs, OpCode.OP_POW, e1, e2, line); break; } case BinOpr.EQ: { CodeComp( fs, OpCode.OP_EQ, 1, e1, e2 ); break; } case BinOpr.LT: { CodeComp( fs, OpCode.OP_LT, 1, e1, e2 ); break; } case BinOpr.LE: { CodeComp( fs, OpCode.OP_LE, 1, e1, e2 ); break; } case BinOpr.NE: { CodeComp( fs, OpCode.OP_EQ, 0, e1, e2 ); break; } case BinOpr.GT: { CodeComp( fs, OpCode.OP_LT, 0, e1, e2 ); break; } case BinOpr.GE: { CodeComp( fs, OpCode.OP_LE, 0, e1, e2 ); break; } default: Utl.Assert(false); break; } }
public static int Exp2AnyReg( FuncState fs, ExpDesc e ) { // Debug.Log("Exp2AnyReg k:" + e.Kind + // " hasjump:" + HasJumps(e) + // " info:" + e.Info + // " nactvar:" + fs.NumActVar); DischargeVars( fs, e ); if( e.Kind == ExpKind.VNONRELOC ) { // exp is already in a register if( ! HasJumps( e ) ) return e.Info; // reg. is not a local? if( e.Info >= fs.NumActVar ) { Exp2Reg( fs, e, e.Info ); return e.Info; } } Exp2NextReg( fs, e ); // default return e.Info; }
private static bool HasJumps( ExpDesc e ) { return e.ExitTrue != e.ExitFalse; }
public static void Posfix(FuncState fs, BinOpr op, ExpDesc e1, ExpDesc e2, int line) { switch (op) { case BinOpr.AND: { Utl.Assert(e1.ExitTrue == NO_JUMP); DischargeVars(fs, e2); e2.ExitFalse = Concat(fs, e2.ExitFalse, e1.ExitFalse); e1.CopyFrom(e2); break; } case BinOpr.OR: { Utl.Assert(e1.ExitFalse == NO_JUMP); DischargeVars(fs, e2); e2.ExitTrue = Concat(fs, e2.ExitTrue, e1.ExitTrue); e1.CopyFrom(e2); break; } case BinOpr.CONCAT: { Exp2Val(fs, e2); var pe2 = fs.GetCode(e2); if (e2.Kind == ExpKind.VRELOCABLE && pe2.Value.GET_OPCODE() == OpCode.OP_CONCAT) { Utl.Assert(e1.Info == pe2.Value.GETARG_B() - 1); FreeExp(fs, e1); pe2.Value = pe2.Value.SETARG_B(e1.Info); e1.Kind = ExpKind.VRELOCABLE; e1.Info = e2.Info; } else { // operand must be on the `stack' Exp2NextReg(fs, e2); CodeArith(fs, OpCode.OP_CONCAT, e1, e2, line); } break; } case BinOpr.ADD: { CodeArith(fs, OpCode.OP_ADD, e1, e2, line); break; } case BinOpr.SUB: { CodeArith(fs, OpCode.OP_SUB, e1, e2, line); break; } case BinOpr.MUL: { CodeArith(fs, OpCode.OP_MUL, e1, e2, line); break; } case BinOpr.DIV: { CodeArith(fs, OpCode.OP_DIV, e1, e2, line); break; } case BinOpr.MOD: { CodeArith(fs, OpCode.OP_MOD, e1, e2, line); break; } case BinOpr.POW: { CodeArith(fs, OpCode.OP_POW, e1, e2, line); break; } case BinOpr.EQ: { CodeComp(fs, OpCode.OP_EQ, 1, e1, e2); break; } case BinOpr.LT: { CodeComp(fs, OpCode.OP_LT, 1, e1, e2); break; } case BinOpr.LE: { CodeComp(fs, OpCode.OP_LE, 1, e1, e2); break; } case BinOpr.NE: { CodeComp(fs, OpCode.OP_EQ, 0, e1, e2); break; } case BinOpr.GT: { CodeComp(fs, OpCode.OP_LT, 0, e1, e2); break; } case BinOpr.GE: { CodeComp(fs, OpCode.OP_LE, 0, e1, e2); break; } default: throw new NotImplementedException(string.Format("opcode {0}({1}, {2}) @line:{3}", op, e1, e2, line)); } }
private static void Discharge2AnyReg( FuncState fs, ExpDesc e ) { if( e.Kind != ExpKind.VNONRELOC ) { ReserveRegs( fs, 1 ); Discharge2Reg( fs, e, fs.FreeReg-1 ); } }
private static bool HasJumps(ExpDesc e) { return(e.ExitTrue != e.ExitFalse); }
public static void Exp2NextReg( FuncState fs, ExpDesc e ) { DischargeVars( fs, e ); FreeExp( fs, e ); ReserveRegs( fs, 1 ); Exp2Reg( fs, e, fs.FreeReg-1 ); }
public Pointer <Instruction> GetCode(ExpDesc e) { return(new Pointer <Instruction>(Proto.Code, e.Info)); }