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))); }
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: Utl.Assert(false); break; } }