Пример #1
0
 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);
     }
 }
Пример #2
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
     }
 }
Пример #3
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;
        }
Пример #4
0
 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)));
 }
Пример #5
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;
            }
        }