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); } }
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 } }
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 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 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 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; } }
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) ); }
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 ); } }
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)); } }