예제 #1
0
        internal Instr GenJmp(OpCode op, int pc, out int pos)
        {
            vm.CurrentScope.lastpc = vm.CurrentScope.pc;
            Instr instr = AppendInstruction(new Instr(op, pc));

            vm.CurrentScope.pc++;
            pos = vm.CurrentScope.pc;

            return(instr);
        }
예제 #2
0
        public CodeGenScope PushOP(Instr instr)
        {
            if (pc >= MAX_INSTR_SIZE)
            {
                throw new Exception("too big code block");
            }

            lastpc = pc;

            iseq.Add(instr);

            pc++;

            return(this);
        }
예제 #3
0
        public Instr Emit_Array(ArrayNode node)
        {
            int n;

            GenValues(node, out n);

            Instr instr = null;

            if (n >= 0)
            {
                Pop(n);
                AppendInstruction(GenOp_2(OpCode.Array, vm.CurrentScope.sp, n));
                Push();
            }

            return(instr);
        }
예제 #4
0
 private void GenReturn(CodeGenScope s, OpCode op, int src)
 {
     if (no_peephole(s))
     {
         GenOp_1(s, op, src);
     }
     else
     {
         Instr data = s.Last;
         if (data.insn == OpCode.Move && src == data.a)
         {
             s.pc = s.lastpc;
             GenOp_1(s, op, data.b);
         }
         else if (data.insn != OpCode.Return)
         {
             GenOp_1(s, op, src);
         }
     }
 }
예제 #5
0
        private int GenJmp2(CodeGenScope scope, OpCode op, int a, int pc, int val)
        {
            int pos;

            if (val != NOVAL)
            {
                Instr instr = scope.Last;
                if (instr.insn == OpCode.Move && instr.a == a)
                {
                    scope.pc = scope.lastpc;
                    a        = instr.b;
                }
            }

            scope.lastpc = scope.pc;
            scope.PushOP(new Instr(op, a, pc));
            pos = scope.pc;

            return(pos);
        }
예제 #6
0
        public Instr Emit_Hash(HashNode node)
        {
            int len = 0;

            for (var i = 0; i < node.keys.Count; ++i)
            {
                node.keys[i].Compile(this);
                node.values[i].Compile(this);
                len++;
            }

            Instr instr = null;

            if (len >= 0)
            {
                Pop(len * 2);
                AppendInstruction(GenOp_2(OpCode.Hash, vm.CurrentScope.sp, len));
                Push();
            }

            return(instr);
        }
예제 #7
0
        internal Instr GenMove(int dst, int src, bool nopeep)
        {
            if (true)
            {
                goto normal;
            }
            else
            {
                Scope s    = vm.CurrentScope;
                Instr data = s.Last;
                switch (data.insn)
                {
                case OpCode.Move:
                    if (dst == src)
                    {
                        return(null);                                                 /* remove useless MOVE */
                    }
                    if (data.b == dst && data.a == src)                               /* skip swapping MOVE */
                    {
                        return(null);
                    }
                    goto normal;

                case OpCode.LoadNIL:
                case OpCode.LoadSelf:
                    if (nopeep || data.a != src /*|| data.a < s->nlocals*/)
                    {
                        goto normal;
                    }
                    s.pc = s.lastpc;
                    GenOp_1(data.insn, dst);
                    break;

                case OpCode.LoadI:
                case OpCode.GetGV:
                case OpCode.GetIV:
                case OpCode.GetCV:
                case OpCode.GetConst:
                case OpCode.String:
                case OpCode.Lambda:
                case OpCode.Block:
                case OpCode.Method:
                    if (nopeep || data.a != src /*|| data.a < s.nlocals*/)
                    {
                        goto normal;
                    }
                    s.pc = s.lastpc;
                    GenOp_2(data.insn, dst, data.b);
                    break;

                default:
                    goto normal;
                }
            }
            return(null);

normal:
            return(AppendInstruction(new Instr(OpCode.Move, dst, src)));

            // TODO: on_eval
            //return;
        }
예제 #8
0
 internal Instr AppendInstruction(Instr c)
 {
     Code.Add(c);
     return(c);
 }
예제 #9
0
        private void GenMove(CodeGenScope s, int dst, int src, bool nopeep)
        {
            if (no_peephole(s))
            {
                goto normal;
            }
            else
            {
                Instr data = s.Last;
                switch (data.insn)
                {
                case OpCode.Move:
                    if (dst == src)
                    {
                        return;                                                       /* remove useless MOVE */
                    }
                    if (data.b == dst && data.a == src)                               /* skip swapping MOVE */
                    {
                        return;
                    }
                    goto normal;

                case OpCode.LoadNIL:
                case OpCode.LoadSelf:
                    if (nopeep || data.a != src /*|| data.a < s->nlocals*/)
                    {
                        goto normal;
                    }
                    s.pc = s.lastpc;
                    GenOp_1(s, data.insn, dst);
                    break;

                case OpCode.LoadI:
                case OpCode.GetGV:
                case OpCode.GetIV:
                case OpCode.GetCV:
                case OpCode.GetConst:
                case OpCode.String:
                case OpCode.Lambda:
                case OpCode.Block:
                case OpCode.Method:
                    if (nopeep || data.a != src /*|| data.a < s.nlocals*/)
                    {
                        goto normal;
                    }
                    s.pc = s.lastpc;
                    GenOp_2(s, data.insn, dst, data.b);
                    break;

                default:
                    goto normal;
                }
            }
            return;

normal:
            s.PushOP(new Instr(OpCode.Move, dst, src));

            // TODO: on_eval
            return;
        }