static void Main(string[] args) { foreach (var fn in args) { if (!File.Exists(fn)) { Console.WriteLine("cannot find file: {0}", fn); } string src = File.ReadAllText(fn); /// Stage 1: lexer. ReadOnlyCollection <T> tokens; try { tokens = new ReadOnlyCollection <T>(Lexer.Instance.Scan(src)); } catch (LexerException e) { Console.WriteLine(e.Message); return; } /// Stage 2: parser. Parser.Env.Clear(); var stream = new TokenStream <T>(tokens); var results = P.TranslationUnit().End()(stream); if (results.Count() == 0) { Console.WriteLine("Parser Error: parsing failed"); return; } if (results.Count() > 1) { Console.WriteLine("Parser Error: ambiguity"); return; } /// Stage 3: type check and build ast. AST.Node ast = null; try { ast = results.First().Value.ToAST(new SyntaxTree.Env()); } catch (Error e) { Console.WriteLine(e.Message); return; } /// Stage 4: code generation and write to file. var gen = new X86Gen(); ast.ToX86(gen); if (fn.Length > 2 && fn.Substring(fn.Length - 2) == ".c") { File.WriteAllText(fn.Substring(0, fn.Length - 2) + ".s", gen.ToString()); } else { File.WriteAllText(fn + ".s", gen.ToString()); } } }
public override void ToX86(X86Gen gen) { gen.Comment(X86Gen.Seg.TEXT, "if"); gen.Branch(expr, other != null ? elseLabel : endIfLabel, false); /// Generate code for then branch. /// Remember to jump to endif label since /// "If the first substatement is reached via a label, the second substatement is not executed. gen.Comment(X86Gen.Seg.TEXT, "then"); then.ToX86(gen); gen.Inst(X86Gen.jmp, endIfLabel); if (other != null) { gen.Comment(X86Gen.Seg.TEXT, "else"); gen.Tag(X86Gen.Seg.TEXT, elseLabel); other.ToX86(gen); } gen.Tag(X86Gen.Seg.TEXT, endIfLabel); }
public override void ToX86(X86Gen gen) { var ret = expr.ToX86Expr(gen); switch (expr.Type.Kind) { case TKind.INT: case TKind.LONG: /// Move the result to ecx. if (ret == X86Gen.Ret.PTR) { gen.Inst(X86Gen.mov, X86Gen.ecx, X86Gen.eax.Addr()); } else { gen.Inst(X86Gen.mov, X86Gen.ecx, X86Gen.eax); } /// For each case. foreach (var c in cases) { var cRet = c.Item2.ToX86Expr(gen); Debug.Assert(cRet == X86Gen.Ret.REG); gen.Inst(X86Gen.cmp, X86Gen.eax, X86Gen.ecx); gen.Inst(X86Gen.je, c.Item1); } /// Jump to default label. gen.Inst(X86Gen.jmp, defaultLabel); break; default: throw new NotImplementedException(); } /// Lay the code for the body. stmt.ToX86(gen); /// Lay down the break label. gen.Tag(X86Gen.Seg.TEXT, breakLabel); }
/// <summary> /// The basic structure is like: /// /// # init /// jmp first_label /// second_plus_label: /// # iter /// first_label: /// # pred /// je break_label /// # body /// jmp second_plus_label /// break_label: /// /// </summary> /// <param name="gen"></param> public override void ToX86(X86Gen gen) { /// Generate the initialize code. /// Jump to first_label if iter is not omitted. gen.Comment(X86Gen.Seg.TEXT, "for init"); if (init != null) { init.ToX86(gen); if (iter != null) { gen.Inst(X86Gen.jmp, firstLabel); } } /// Generate the iterate code. gen.Comment(X86Gen.Seg.TEXT, "for iter"); if (iter != null) { gen.Tag(X86Gen.Seg.TEXT, secondPlusLabel); iter.ToX86(gen); } /// Generate the controlling (predicating) code. gen.Comment(X86Gen.Seg.TEXT, "for pred"); gen.Tag(X86Gen.Seg.TEXT, firstLabel); gen.Branch(pred, breakLabel, false); /// Generate body code. gen.Comment(X86Gen.Seg.TEXT, "for body"); body.ToX86WithLabel(gen, continueLabel); gen.Inst(X86Gen.jmp, iter != null ? secondPlusLabel : firstLabel); /// Generate break labe. gen.Comment(X86Gen.Seg.TEXT, "for end"); gen.Tag(X86Gen.Seg.TEXT, breakLabel); }
public override void ToX86(X86Gen gen) { gen.Tag(X86Gen.Seg.TEXT, label); stmt.ToX86(gen); }