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(); }
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(); }