예제 #1
0
        public void TestEmitJump()
        {
            var offset_i8  = sbyte.MaxValue;
            var offset_i32 = int.MaxValue;

            foreach (OpCode op in Enum.GetValues(typeof(OpCode)))
            {
                using (var script = new ScriptBuilder())
                {
                    if (op < OpCode.JMP || op > OpCode.JMPLE_L)
                    {
                        Assert.ThrowsException <ArgumentOutOfRangeException>(() => script.EmitJump(op, offset_i8));
                        Assert.ThrowsException <ArgumentOutOfRangeException>(() => script.EmitJump(op, offset_i32));
                    }
                    else
                    {
                        script.EmitJump(op, offset_i8);
                        script.EmitJump(op, offset_i32);
                        if ((int)op % 2 == 0)
                        {
                            CollectionAssert.AreEqual(new[] { (byte)op, (byte)offset_i8, (byte)(op + 1) }.Concat(BitConverter.GetBytes(offset_i32)).ToArray(), script.ToArray());
                        }
                        else
                        {
                            CollectionAssert.AreEqual(new[] { (byte)op }.Concat(BitConverter.GetBytes((int)offset_i8)).Concat(new[] { (byte)op }).Concat(BitConverter.GetBytes(offset_i32)).ToArray(), script.ToArray());
                        }
                    }
                }
            }

            offset_i8  = sbyte.MinValue;
            offset_i32 = int.MinValue;

            foreach (OpCode op in Enum.GetValues(typeof(OpCode)))
            {
                using (var script = new ScriptBuilder())
                {
                    if (op < OpCode.JMP || op > OpCode.JMPLE_L)
                    {
                        Assert.ThrowsException <ArgumentOutOfRangeException>(() => script.EmitJump(op, offset_i8));
                        Assert.ThrowsException <ArgumentOutOfRangeException>(() => script.EmitJump(op, offset_i32));
                    }
                    else
                    {
                        script.EmitJump(op, offset_i8);
                        script.EmitJump(op, offset_i32);
                        if ((int)op % 2 == 0)
                        {
                            CollectionAssert.AreEqual(new[] { (byte)op, (byte)offset_i8, (byte)(op + 1) }.Concat(BitConverter.GetBytes(offset_i32)).ToArray(), script.ToArray());
                        }
                        else
                        {
                            CollectionAssert.AreEqual(new[] { (byte)op }.Concat(BitConverter.GetBytes((int)offset_i8)).Concat(new[] { (byte)op }).Concat(BitConverter.GetBytes(offset_i32)).ToArray(), script.ToArray());
                        }
                    }
                }
            }
        }
예제 #2
0
        public void TestBreakPointStepOver()
        {
            using (var engine = new ExecutionEngine(null, Crypto.Default, null, null))
                using (var script = new ScriptBuilder())
                {
                    /* ┌     */ script.EmitJump(OpCode.CALL, 5);
                    /* │  ┌> */ script.Emit(OpCode.NOT);
                    /* │  │  */ script.Emit(OpCode.RET);
                    /* └>X│  */ script.Emit(OpCode.PUSH0);
                    /*   └┘  */ script.Emit(OpCode.RET);

                    engine.LoadScript(script.ToArray());

                    var debugger = new Debugger(engine);

                    debugger.AddBreakPoint(engine.CurrentContext.ScriptHash, 5);
                    debugger.StepOver();

                    Assert.AreEqual(5, engine.CurrentContext.InstructionPointer);
                    Assert.AreEqual(VMState.BREAK, engine.State);

                    debugger.Execute();

                    Assert.AreEqual(true, engine.ResultStack.Pop().GetBoolean());
                    Assert.AreEqual(VMState.HALT, engine.State);
                }
        }
예제 #3
0
        public void TestEmitJump()
        {
            var offset = RandomHelper.RandInt16();

            foreach (OpCode op in Enum.GetValues(typeof(OpCode)))
            {
                using (var script = new ScriptBuilder())
                {
                    if (op != OpCode.JMP && op != OpCode.JMPIF && op != OpCode.JMPIFNOT && op != OpCode.CALL)
                    {
                        Assert.ThrowsException <ArgumentException>(() => script.EmitJump(op, offset));
                    }
                    else
                    {
                        script.EmitJump(op, offset);
                        CollectionAssert.AreEqual(new byte[] { (byte)op }.Concat(BitConverter.GetBytes(offset)).ToArray(), script.ToArray());
                    }
                }
            }
        }
예제 #4
0
        public void TestStepInto()
        {
            using (var engine = new ExecutionEngine())
                using (var script = new ScriptBuilder())
                {
                    /* ┌     CALL
                     * │  ┌> NOT
                     * │  │  RET
                     * └> │  PUSH0
                     *  └─┘  RET */
                    script.EmitJump(OpCode.CALL, 5);
                    script.Emit(OpCode.NOT);
                    script.Emit(OpCode.RET);
                    script.Emit(OpCode.PUSH0);
                    script.Emit(OpCode.RET);

                    engine.LoadScript(script.ToArray());

                    var debugger = new Debugger(engine);

                    var context = engine.CurrentContext;

                    Assert.AreEqual(context, engine.CurrentContext);
                    Assert.AreEqual(context, engine.EntryContext);
                    Assert.IsNull(engine.CurrentContext.CallingScript);
                    Assert.AreEqual(OpCode.NOT, engine.CurrentContext.NextInstruction.OpCode);

                    Assert.AreEqual(VMState.BREAK, debugger.StepInto());

                    Assert.AreNotEqual(context, engine.CurrentContext);
                    Assert.AreEqual(context, engine.EntryContext);
                    Assert.AreEqual(engine.EntryContext.Script, engine.CurrentContext.CallingScript);
                    Assert.AreEqual(OpCode.RET, engine.CurrentContext.NextInstruction.OpCode);

                    Assert.AreEqual(VMState.BREAK, debugger.StepInto());
                    Assert.AreEqual(VMState.BREAK, debugger.StepInto());

                    Assert.AreEqual(context, engine.CurrentContext);
                    Assert.AreEqual(context, engine.EntryContext);
                    Assert.IsNull(engine.CurrentContext.CallingScript);
                    Assert.AreEqual(OpCode.RET, engine.CurrentContext.NextInstruction.OpCode);

                    Assert.AreEqual(VMState.BREAK, debugger.StepInto());
                    Assert.AreEqual(VMState.HALT, debugger.StepInto());

                    Assert.AreEqual(true, engine.ResultStack.Pop().GetBoolean());
                    Assert.AreEqual(VMState.HALT, engine.State);

                    // Test step into again

                    Assert.AreEqual(VMState.HALT, debugger.StepInto());
                    Assert.AreEqual(VMState.HALT, engine.State);
                }
        }
        public void Test_Optimize_ConstExecution_ROT()
        {
            using (var scriptBefore = new ScriptBuilder())
            {
                scriptBefore.Emit(VM.OpCode.PUSH1);
                scriptBefore.Emit(VM.OpCode.PUSH2);
                scriptBefore.Emit(VM.OpCode.PUSH3);
                scriptBefore.Emit(VM.OpCode.ROT);

                using (var scriptAfter = new ScriptBuilder())
                {
                    scriptAfter.Emit(VM.OpCode.PUSH2);
                    scriptAfter.Emit(VM.OpCode.PUSH3);
                    scriptAfter.Emit(VM.OpCode.PUSH1);

                    var optimized = NefOptimizeTool.Optimize(scriptBefore.ToArray(), Array.Empty <int>(), OptimizeParserType.DELETE_CONST_EXECUTION);
                    CollectionAssert.AreEqual(scriptAfter.ToArray(), optimized);
                }
            }

            using (var scriptBefore = new ScriptBuilder())
            {
                scriptBefore.Emit(VM.OpCode.PUSH1);
                scriptBefore.Emit(VM.OpCode.PUSH2);
                scriptBefore.Emit(VM.OpCode.PUSHNULL);
                scriptBefore.Emit(VM.OpCode.ROT);

                using (var scriptAfter = new ScriptBuilder())
                {
                    scriptAfter.Emit(VM.OpCode.PUSH2);
                    scriptAfter.Emit(VM.OpCode.PUSHNULL);
                    scriptAfter.Emit(VM.OpCode.PUSH1);

                    var optimized = NefOptimizeTool.Optimize(scriptBefore.ToArray(), Array.Empty <int>(), OptimizeParserType.DELETE_CONST_EXECUTION);
                    CollectionAssert.AreEqual(scriptAfter.ToArray(), optimized);
                }
            }

            using (var scriptBefore = new ScriptBuilder())
            {
                scriptBefore.Emit(VM.OpCode.PUSH5);
                scriptBefore.Emit(VM.OpCode.PUSH4);
                scriptBefore.EmitJump(VM.OpCode.JMP, 3);
                scriptBefore.Emit(VM.OpCode.PUSH1);
                scriptBefore.Emit(VM.OpCode.PUSH2);
                scriptBefore.Emit(VM.OpCode.PUSH3);
                scriptBefore.Emit(VM.OpCode.ROT);

                var optimized = NefOptimizeTool.Optimize(scriptBefore.ToArray(), Array.Empty <int>(), OptimizeParserType.DELETE_CONST_EXECUTION);
                CollectionAssert.AreEqual(scriptBefore.ToArray(), optimized);
            }
        }
예제 #6
0
        private void ProcessJump(ScriptBuilder sb)
        {
            if (Arguments.Length != 1)
            {
                throw new CompilerException(LineNumber, ERR_INCORRECT_NUMBER);
            }

            if (!Arguments[0].IsLabel())
            {
                throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT);
            }
            else
            {
                sb.EmitJump(Opcode.JMP, Arguments[0].AsLabel());
            }
        }
예제 #7
0
        private void InsertJump(Instruction i, VM.Opcode opcode)
        {
            byte reg;

            // for conditional jumps, fetch the appropriate register for the conditional value
            if (opcode != VM.Opcode.JMP)
            {
                reg = FetchRegister(i.a.target);
            }
            else
            {
                reg = 0;
            }

            _output.EmitJump(opcode, i.b.target, reg);
        }
예제 #8
0
        public void TestStepInto()
        {
            using (var engine = new ExecutionEngine())
                using (var script = new ScriptBuilder())
                {
                    /* ┌     */ script.EmitJump(OpCode.CALL, 5);
                    /* │  ┌> */ script.Emit(OpCode.NOT);
                    /* │  │  */ script.Emit(OpCode.RET);
                    /* └> │  */ script.Emit(OpCode.PUSH0);
                    /*  └─┘  */ script.Emit(OpCode.RET);

                    engine.LoadScript(script.ToArray());

                    var debugger = new Debugger(engine);

                    var context = engine.CurrentContext;

                    Assert.AreEqual(context, engine.CurrentContext);
                    Assert.AreEqual(context, engine.EntryContext);

                    debugger.StepInto();

                    Assert.AreNotEqual(context, engine.CurrentContext);
                    Assert.AreEqual(context, engine.EntryContext);

                    debugger.StepInto();
                    debugger.StepInto();

                    Assert.AreEqual(context, engine.CurrentContext);
                    Assert.AreEqual(context, engine.EntryContext);

                    debugger.StepInto();
                    debugger.StepInto();

                    Assert.AreEqual(true, engine.ResultStack.Pop().GetBoolean());
                    Assert.AreEqual(VMState.HALT, engine.State);
                }
        }
예제 #9
0
        public void TestBreakPointStepOver()
        {
            using (var engine = new ExecutionEngine())
                using (var script = new ScriptBuilder())
                {
                    /* ┌     CALL
                     * │  ┌> NOT
                     * │  │  RET
                     * └>X│  PUSH0
                     *   └┘  RET */
                    script.EmitJump(OpCode.CALL, 5);
                    script.Emit(OpCode.NOT);
                    script.Emit(OpCode.RET);
                    script.Emit(OpCode.PUSH0);
                    script.Emit(OpCode.RET);

                    engine.LoadScript(script.ToArray());

                    var debugger = new Debugger(engine);

                    Assert.IsNull(engine.CurrentContext.CallingScript);
                    Assert.AreEqual(OpCode.NOT, engine.CurrentContext.NextInstruction.OpCode);

                    debugger.AddBreakPoint(engine.CurrentContext.Script, 5);
                    Assert.AreEqual(VMState.BREAK, debugger.StepOver());

                    Assert.AreEqual(engine.EntryContext.Script, engine.CurrentContext.CallingScript);
                    Assert.AreEqual(OpCode.RET, engine.CurrentContext.NextInstruction.OpCode);
                    Assert.AreEqual(5, engine.CurrentContext.InstructionPointer);
                    Assert.AreEqual(VMState.BREAK, engine.State);

                    debugger.Execute();

                    Assert.AreEqual(true, engine.ResultStack.Pop().GetBoolean());
                    Assert.AreEqual(VMState.HALT, engine.State);
                }
        }
예제 #10
0
        public void TestStepOver()
        {
            using (var engine = new ExecutionEngine())
                using (var script = new ScriptBuilder())
                {
                    /* ┌     */ script.EmitJump(OpCode.CALL, 5);
                    /* │  ┌> */ script.Emit(OpCode.NOT);
                    /* │  │  */ script.Emit(OpCode.RET);
                    /* └> │  */ script.Emit(OpCode.PUSH0);
                    /*  └─┘  */ script.Emit(OpCode.RET);

                    engine.LoadScript(script.ToArray());

                    var debugger = new Debugger(engine);

                    Assert.IsNull(engine.CurrentContext.CallingScript);
                    Assert.AreEqual(OpCode.NOT, engine.CurrentContext.NextInstruction.OpCode);

                    Assert.AreEqual(VMState.BREAK, debugger.StepOver());

                    Assert.IsNull(engine.CurrentContext.CallingScript);
                    Assert.AreEqual(3, engine.CurrentContext.InstructionPointer);
                    Assert.AreEqual(VMState.BREAK, engine.State);
                    Assert.AreEqual(OpCode.RET, engine.CurrentContext.NextInstruction.OpCode);

                    debugger.Execute();

                    Assert.AreEqual(true, engine.ResultStack.Pop().GetBoolean());
                    Assert.AreEqual(VMState.HALT, engine.State);

                    // Test step over again

                    Assert.AreEqual(VMState.HALT, debugger.StepOver());
                    Assert.AreEqual(VMState.HALT, engine.State);
                }
        }