示例#1
0
 private static void FreeExp(FuncState fs, ExpDesc e)
 {
     if (e.Kind == ExpKind.VNONRELOC)
     {
         FreeReg(fs, e.Info);
     }
 }
示例#2
0
        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);
        }
示例#3
0
        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;
        }
示例#4
0
        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;
        }
示例#5
0
 public static void Exp2AnyRegUp(FuncState fs, ExpDesc e)
 {
     if (e.Kind != ExpKind.VUPVAL || HasJumps(e))
     {
         Exp2AnyReg(fs, e);
     }
 }
示例#6
0
        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;
            }
        }
示例#7
0
 public static void Exp2NextReg(FuncState fs, ExpDesc e)
 {
     DischargeVars(fs, e);
     FreeExp(fs, e);
     ReserveRegs(fs, 1);
     Exp2Reg(fs, e, fs.FreeReg - 1);
 }
示例#8
0
        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;
            }
        }
示例#9
0
        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;
        }
示例#10
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);

            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);
        }
示例#11
0
 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;
 }
示例#12
0
 private static void Discharge2AnyReg(FuncState fs, ExpDesc e)
 {
     if (e.Kind != ExpKind.VNONRELOC)
     {
         ReserveRegs(fs, 1);
         Discharge2Reg(fs, e, fs.FreeReg - 1);
     }
 }
示例#13
0
        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);
        }
示例#14
0
 public static void Exp2Val(FuncState fs, ExpDesc e)
 {
     if (HasJumps(e))
     {
         Exp2AnyReg(fs, e);
     }
     else
     {
         DischargeVars(fs, e);
     }
 }
示例#15
0
        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);
        }
示例#16
0
 public void CopyFrom(ExpDesc e)
 {
     this.Kind = e.Kind;
     this.Info = e.Info;
     // this.Ind.T       = e.Ind.T;
     // this.Ind.Idx     = e.Ind.Idx;
     // this.Ind.Vt      = e.Ind.Vt;
     this.Ind         = e.Ind;
     this.NumberValue = e.NumberValue;
     this.ExitTrue    = e.ExitTrue;
     this.ExitFalse   = e.ExitFalse;
 }
示例#17
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);
     }
 }
示例#18
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;
        }
示例#19
0
        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);
        }
示例#20
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
     }
 }
示例#21
0
        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));
        }
示例#22
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)));
 }
示例#23
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;
        }
示例#24
0
        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);
        }
示例#25
0
        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);
        }
示例#26
0
        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);
            }
        }
示例#27
0
 public ConstructorControl()
 {
     ExpLastItem = new ExpDesc();
 }
示例#28
0
 public LHSAssign()
 {
     Prev = null;
     Exp  = new ExpDesc();
 }
示例#29
0
 private static bool HasJumps(ExpDesc e)
 {
     return(e.ExitTrue != e.ExitFalse);
 }
示例#30
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;
            }
        }