Example #1
0
        public void Compile(TextReader assemblySourceReader,
            Action<int, string, Tuple<long, byte[]>> listingHandler = null)
        {
            gen = new CodeGenerator(new MemoryStream());

            errorsAndWarnings.Clear();
            CompileResult = null;

            int lineIndex = 0;
            long lastPositionInStream = 0;

            List<long> lineOffsets = null;
            List<string> lines = null;

            if (listingHandler != null)
            {
                lineOffsets = new List<long>();
                lines = new List<string>();
            }

            string line = assemblySourceReader.ReadLine();
            while (line != null)
            {
                try
                {
                    CompileLine(lineIndex, line);
                }
                catch (ParseException ex)
                {
                    errorsAndWarnings.Add(
                        new CodeIssue(lineIndex, IssueKind.Error, ex.Message));
                }

                if (listingHandler != null)
                {
                    lineOffsets.Add(lastPositionInStream);
                    lines.Add(line);
                }

                lineIndex++;
                lastPositionInStream = gen.OutputStream.Position;
                line = assemblySourceReader.ReadLine();
            }

            CheckLabels();

            try
            {
                gen.Finish();
            }
            catch (CodeGenerationException)
            { // eat 'incorrect label' exceptions
            }

            if (listingHandler != null)
            {
                var stream = (MemoryStream)gen.OutputStream;
                stream.Position = 0;

                for (int i = 0; i < lines.Count; i++)
                {
                    long next = (i != lines.Count - 1)
                        ? lineOffsets[i + 1] : stream.Length;

                    byte[] bytes = new byte[next - lineOffsets[i]];

                    // read generated bytes for line i
                    for (int j = 0; j < bytes.Length; j++)
                    {
                        bytes[j] = (byte)stream.ReadByte();
                    }

                    listingHandler(i, lines[i], Tuple.Create(lineOffsets[i], bytes));
                }
            }

            if (errorsAndWarnings.Count(iss => iss.Kind == IssueKind.Error) == 0)
            {
                CompileResult = (MemoryStream)gen.OutputStream;
            }

            labels.Clear();
            labelLines.Clear();
        }
Example #2
0
        static void CodeGeneratorTest()
        {
            CodeGenerator gen = new CodeGenerator(new MemoryStream());

            Label loop    = gen.DefineLabel();
            Label testsub = gen.DefineLabel();
            Label crash   = gen.DefineLabel();

            gen.Emit(OpCodes.Set, Argument.A, Argument.Literal(0x30));
            gen.Emit(OpCodes.Set, Argument.Indirect(0x1000), Argument.Literal(0x20));
            gen.Emit(OpCodes.Sub, Argument.A, Argument.Indirect(0x1000));
            gen.Emit(OpCodes.Ifn, Argument.A, Argument.Literal(0x10));
            gen.Emit(OpCodes.Set, Argument.PC, crash);

            gen.Emit(OpCodes.Set, Argument.I, Argument.Literal(10));
            gen.Emit(OpCodes.Set, Argument.A, Argument.Literal(0x2000));
            gen.MarkLabel(loop);
            gen.Emit(OpCodes.Set, Argument.Indirect(0x2000, Register.I), Argument.IndirectA);
            gen.Emit(OpCodes.Sub, Argument.I, Argument.Literal(1));
            gen.Emit(OpCodes.Ifn, Argument.I, Argument.Literal(0));
            gen.Emit(OpCodes.Set, Argument.PC, loop);

            gen.Emit(OpCodes.Set, Argument.X, Argument.Literal(0x4));
            gen.Emit(OpCodes.Jsr, testsub);
            gen.Emit(OpCodes.Set, Argument.PC, crash);

            gen.MarkLabel(testsub);
            gen.Emit(OpCodes.Shl, Argument.X, Argument.Literal(4));
            gen.Emit(OpCodes.Set, Argument.PC, Argument.Pop);

            gen.MarkLabel(crash);
            gen.Emit(OpCodes.Set, Argument.PC, crash);

            gen.Finish();

            PrintDump(((MemoryStream)gen.OutputStream).ToArray(), 8);
            Console.ReadLine();
        }