コード例 #1
0
ファイル: AssemblerTests.cs プロジェクト: redcoreit/vmr
        public void Method_call_load_two_numbers_then_add()
        {
            // Arrange
            var builder = GetBuilder();
            var pointer = 0;

            // Act
            _ = builder.GetIlProgram(); // Test reproducable property of CodeBuilder
            var program = builder.GetBinaryProgram();

            // Assert

            // Entry Point
            Assert.Equal(0, pointer);
            Assert.Equal(11, BinaryConvert.GetInt32(ref pointer, program));

            // two
            var method_two = pointer;

            Assert.Equal(5, ++pointer);
            Assert.Equal(InstructionCode.Ldc_i4, BinaryConvert.GetInstructionCode(ref pointer, program));
            Assert.Equal(2, BinaryConvert.GetInt32(ref pointer, program));
            Assert.Equal(InstructionCode.Ret, BinaryConvert.GetInstructionCode(ref pointer, program));

            // main
            Assert.Equal(12, ++pointer);
            Assert.Equal(InstructionCode.Ldc_i4, BinaryConvert.GetInstructionCode(ref pointer, program));
            Assert.Equal(1, BinaryConvert.GetInt32(ref pointer, program));
            Assert.Equal(InstructionCode.Call, BinaryConvert.GetInstructionCode(ref pointer, program));
            Assert.Equal(method_two, BinaryConvert.GetInt32(ref pointer, program));
            Assert.Equal(InstructionCode.Add, BinaryConvert.GetInstructionCode(ref pointer, program));
            Assert.Equal(InstructionCode.Ret, BinaryConvert.GetInstructionCode(ref pointer, program));
コード例 #2
0
ファイル: VirtualMachine.cs プロジェクト: redcoreit/vmr
        private void GetOpCodeArg(ReadOnlySpan <byte> program, out int value)
        {
            if (_pointer >= program.Length)
            {
                Throw.MissingInstructionArgument(_pointer);
            }

            value = BinaryConvert.GetInt32(ref _pointer, program);
        }
コード例 #3
0
ファイル: VirtualMachine.cs プロジェクト: redcoreit/vmr
        public void Execute(byte[] program)
        {
            _stackFrame.Clear();
            var span = program.AsSpan();

            var entryPointAddress = BinaryConvert.GetInt32(ref _pointer, program);

            _pointer = entryPointAddress + InstructionFacts.SizeOfMethodHeader;

            while (_pointer < span.Length)
            {
                var instruction = GetInstruction(span);
                DispatchInstruction(instruction, span);
            }
        }
コード例 #4
0
        private IlObject?ReadArguments(InstructionCode instruction, ReadOnlySpan <byte> program, ref int pointer)
        {
            var address = new IlAddress(pointer);

            switch (instruction)
            {
            case InstructionCode.Ldstr:
            {
                var arg = BinaryConvert.GetString(ref pointer, program);
                return(new IlObject(address, 0, arg));
            }

            case InstructionCode.Ldloc:
            case InstructionCode.Stloc:
            case InstructionCode.Ldc_i4:
            case InstructionCode.Ldarg:
            case InstructionCode.Call:
            {
                var arg = BinaryConvert.GetInt32(ref pointer, program);
                return(new IlObject(address, 0, arg));
            }

            case InstructionCode.Br:
            case InstructionCode.Brfalse:
            case InstructionCode.Brtrue:
            {
                var arg = BinaryConvert.GetInt32(ref pointer, program);
                _labelTargets.Add(new IlAddress(arg));
                return(new IlObject(address, 0, arg));
            }

            case InstructionCode.Ret:
            case InstructionCode.Add:
            case InstructionCode.Ceq:
            case InstructionCode.Pop:
            case InstructionCode.Nop:
            {
                return(null);
            }

            default:
            {
                Throw.NotSupportedInstruction(pointer, program[pointer - 1]);
                return(null);
            }
            }
        }
コード例 #5
0
        private IlProgram GetProgram(ReadOnlySpan <byte> program)
        {
            var pointer     = 0;
            var ilMethods   = new List <IlMethod>();
            var methodNames = new Dictionary <IlAddress, string>();

            var entryPointValue = BinaryConvert.GetInt32(ref pointer, program);

            var callTargets = new Stack <int>();

            callTargets.Push(entryPointValue);
            var visitedTargets = new HashSet <int> {
                entryPointValue
            };

            while (callTargets.Count > 0)
            {
                var ilObjects = new List <IlObject>();

                pointer = callTargets.Pop();
                var argCount = program[pointer];

                var method = new IlMethod(pointer, argCount, ilObjects);
                ilMethods.Add(method);
                methodNames.Add(method.Address, $"m{ilMethods.Count}");

                pointer += InstructionFacts.SizeOfMethodHeader;

                while (pointer < program.Length)
                {
                    var instructionAddress = pointer;
                    var instruction        = GetInstruction(program, ref pointer);
                    ilObjects.Add(new IlObject(instructionAddress, 0, instruction));

                    var arg = ReadArguments(instruction, program, ref pointer);

                    if (instruction == InstructionCode.Ret)
                    {
                        break;
                    }

                    if (arg is null)
                    {
                        continue;
                    }

                    ilObjects.Add(arg);

                    if (instruction != InstructionCode.Call)
                    {
                        continue;
                    }

                    var callTarget = (int)arg.Obj;

                    if (!visitedTargets.Add(callTarget))
                    {
                        continue;
                    }

                    callTargets.Push(callTarget);
                }
            }

            return(new IlProgram(entryPointValue, ilMethods.OrderBy(m => m.Address).ToArray(), methodNames, _labelTargets));
        }