]> Joshua Wise's Git repositories - snipe.git/blob - top/top.sml
c350c094c898d4002af110839f7415a77bd94251
[snipe.git] / top / top.sml
1 (* L3 Compiler
2  * Top Level Environment
3  * Author: Kaustuv Chaudhuri <kaustuv+@cs.cmu.edu>
4  * Modified: Alex Vaynberg <alv@andrew.cmu.edu>
5  * Modified: Frank Pfenning <fp@cs.cmu.edu>
6  *)
7
8 signature TOP =
9 sig
10   (* main function for standalone executable
11    * use with SMLofNJ.exportFn("heapfilename", Top.main)
12    *)
13   val main : string * string list -> OS.Process.status
14   
15   (* test "arguments"; is the same as executing a saved
16    * heap with arguments on the command line
17    *)
18   val test : string -> OS.Process.status
19 end
20
21 structure Top :> TOP =
22 struct
23   structure G = GetOpt  (* from $/smlnj-lib/Util/getopt-sig.sml *)
24
25   fun say s = TextIO.output (TextIO.stdErr, s ^ "\n")
26
27   fun newline () = TextIO.output (TextIO.stdErr, "\n")
28
29   exception EXIT
30
31   (* see flag explanations below *)
32   val flag_verbose = Flag.flag "verbose"
33   val flag_liveness = Flag.flag "liveness"
34   val flag_ast = Flag.flag "ast"
35   val flag_ir = Flag.flag "ir"
36   val flag_assem = Flag.flag "assem"
37   val flag_color = Flag.flag "color"
38
39   fun reset_flags () =
40       List.app Flag.unset [flag_verbose, flag_ast,
41                            flag_ir, flag_assem, flag_liveness];
42
43   val options = [{short = "v", long=["verbose"], 
44                   desc=G.NoArg (fn () => Flag.set flag_verbose),
45                   help="verbose messages"},
46                  {short = "a", long=["dump-ast"],
47                   desc=G.NoArg (fn () => Flag.set flag_ast),
48                   help="pretty print the AST"},
49                  {short = "i", long=["dump-ir"],
50                   desc=G.NoArg (fn () => Flag.set flag_ir),
51                   help="pretty print the IR"},
52                  {short = "l", long=["dump-liveness"],
53                   desc=G.NoArg (fn () => Flag.set flag_liveness),
54                   help="pretty print the liveness results"},
55                  {short = "s", long=["dump-assem"],
56                   desc=G.NoArg (fn () => Flag.set flag_assem),
57                   help="pretty print the assembly before register allocaction"},
58                  {short = "c", long=["dump-color"],
59                   desc=G.NoArg (fn () => Flag.set flag_color),
60                   help="pretty print the allocated regs"}
61                 ]
62
63
64   fun stem s =
65       let
66           val (prefix, suffix) =
67               Substring.splitr (fn c => c <> #".") (Substring.full s)
68       in
69           if Substring.isEmpty prefix (* no "." in string s *)
70              then s (* return whole string *)
71           else Substring.string (Substring.trimr 1 prefix)
72       end
73   
74   fun processir externs (Tree.FUNCTION (id, ir)) =
75       let
76         val name = "_l4_" ^ (Symbol.name id)
77         
78         fun realname s = if (List.exists (fn n => s = n) externs)
79                          then s
80                          else "_l4_" ^ s
81       
82         val _ = Flag.guard flag_verbose say ("Processing function: " ^ name)
83
84         val _ = Flag.guard flag_verbose say "  Generating proto-x86_64 code..."
85         val assem = Codegen.codegen ir
86         val _ = Flag.guard flag_assem
87                   (fn () => List.app (TextIO.print o (x86.prettyprint)) assem) ()
88
89         val _ = Flag.guard flag_verbose say "  Analyzing liveness..."
90         val (preds, liveness) = Liveness.liveness assem;
91         val _ = Flag.guard flag_liveness
92                   (fn () => List.app
93                     (fn (asm, liv) =>
94                       TextIO.print (
95                         let
96                           val xpp = x86.prettyprint asm
97                           val xpp = String.extract (xpp, 0, SOME (size xpp - 1))
98                           val spaces = implode (List.tabulate (40 - size xpp, fn _ => #" ")) handle size => ""
99                           val lpp = Liveness.prettyprint liv
100                           val lpp = String.extract (lpp, 0, SOME (size lpp - 1))
101                           val spaces2 = implode (List.tabulate (40 - size lpp, fn _ => #" ")) handle size => ""
102                         in
103                           xpp ^ spaces ^ lpp ^ spaces2 ^ "\n"
104                         end))
105                     (ListPair.zip (assem, Liveness.listify liveness))) ()
106
107         val _ = Flag.guard flag_verbose say "  Graphing..."
108         val (igraph,temps) = Igraph.gengraph (preds, liveness)
109
110         val _ = Flag.guard flag_verbose say "  Ordering..."
111         val order = ColorOrder.colororder (igraph,temps)
112         
113         val _ = Flag.guard flag_verbose say "  Coloring..."
114         val colors = Colorizer.colorize order igraph;
115         val _ = Flag.guard flag_color
116                   (fn () => List.app (TextIO.print o
117                     (fn (t, i) =>
118                       (Temp.name t) ^ " => " ^ (
119                         if (i <= x86.regtonum x86.R13D)
120                           then (x86.prettyprint_oper x86.Long (x86.REG (x86.numtoreg i)))
121                         else
122                           "spill[" ^ Int.toString (i - x86.regtonum x86.R13D) ^ "]")
123                         ^ "--"^ Int.toString i ^ "\n"))
124                     colors) ()
125
126         val _ = Flag.guard flag_verbose say "  Solidifying x86_64 code..."
127         val x86 = Solidify.solidify colors assem;
128
129         val _ = Flag.guard flag_verbose say "  Peepholing..."
130         val x86p = Peephole.peephole x86;
131
132         val _ = Flag.guard flag_verbose say "  Stringifying..."
133         val x86d = [x86.DIRECTIVE(".globl " ^ name),
134                     x86.DIRECTIVE(name ^ ":")]
135                     @ x86p
136         val code = Stringify.stringify realname x86d
137       in
138         code
139       end
140
141   fun main (name, args) =
142       let
143         val header = "Usage: compile [OPTION...] SOURCEFILE\nwhere OPTION is"
144         val usageinfo = G.usageInfo {header = header, options = options}
145         fun errfn msg = (say (msg ^ "\n" ^ usageinfo) ; raise EXIT)
146
147         val _ = Temp.reset (); (* reset temp variable counter *)
148         val _ = reset_flags (); (* return all flags to default value *)
149
150         val _ = if List.length args = 0 then
151                     (say usageinfo; raise EXIT)
152                 else ()
153
154         val (opts, files) =
155             G.getOpt {argOrder = G.Permute,
156                       options = options,
157                       errFn = errfn}
158                      args
159
160         val source =
161             case files
162               of [] => errfn "Error: no input file"
163                | [filename] => filename
164                | _ => errfn "Error: more than one input file"
165
166         val _ = Flag.guard flag_verbose say ("Parsing... " ^ source)
167         val ast = Parse.parse source
168         val (_, funcs) = ast
169         val _ = Flag.guard flag_ast
170                   (fn () => say (Ast.Print.pp_program ast)) ()
171
172         val externs = Symbol.mapPartiali
173                         (fn (a, b) => case (AstUtils.Function.data b)
174                                       of Ast.Extern _ => SOME(Symbol.name a)
175                                        | _ => NONE
176                         ) funcs
177
178         val _ = Flag.guard flag_verbose say "Checking..."
179         val ast = TypeChecker.typecheck ast
180
181         val _ = Flag.guard flag_verbose say "Translating..."
182         val ir = Trans.translate ast
183         val _ = Flag.guard flag_ir (fn () => say (Tree.Print.pp_program ir)) ()
184         
185         val output = foldr (fn (func, code) => (processir ("calloc" (* lololololol *) :: (Symbol.elems externs)) func) ^ code) 
186           (".file\t\"" ^ source ^ "\"\n.ident\t\"15-411 L4 compiler by czl@ and jwise@\"\n") ir
187
188         val afname = stem source ^ ".s"
189         val _ = Flag.guard flag_verbose say ("Writing assembly to " ^ afname ^ " ...")
190         val _ = SafeIO.withOpenOut afname (fn afstream =>
191                    TextIO.output (afstream, output))
192       in
193           OS.Process.success
194       end
195       handle ErrorMsg.Error => ( say "Compilation failed" ; OS.Process.failure )
196            | EXIT => OS.Process.failure
197            | ErrorMsg.InternalError s => ( say ("Internal compiler error: "^s^"\n"); OS.Process.failure)
198            | e => (say ("Unrecognized exception " ^ exnMessage e); OS.Process.failure)
199
200   fun test s = main ("", String.tokens Char.isSpace s)
201 end
This page took 0.029243 seconds and 2 git commands to generate.