|
|
@@ -6,108 +6,132 @@ open Util
|
|
|
(* For some reason OCaml wants me to redefine this type's implementation -.- *)
|
|
|
type phase_func = Types.intermediate -> Types.intermediate
|
|
|
|
|
|
-let always _ = true
|
|
|
-let when_optimize _ = Globals.args.optimize
|
|
|
-
|
|
|
-(* List of all phases, which will be executed in the order defined here. *)
|
|
|
-let phases = [
|
|
|
- ("load", Load.phase, always,
|
|
|
- "Load input file");
|
|
|
- ("parse", Parse.phase, always,
|
|
|
- "Parse input");
|
|
|
- ("desug", Desug.phase, always,
|
|
|
- "Desugaring");
|
|
|
- ("context", Context.phase, always,
|
|
|
- "Context analysis");
|
|
|
- ("typecheck", Typecheck.phase, always,
|
|
|
- "Type checking");
|
|
|
- ("dimreduce", Dimreduce.phase, always,
|
|
|
- "Array dimension reduction");
|
|
|
- ("boolop", Boolop.phase, always,
|
|
|
- "Convert bool operations");
|
|
|
- ("constprop", Constprop.phase, when_optimize,
|
|
|
- "Constant propagation");
|
|
|
- ("unroll", Unroll.phase, when_optimize,
|
|
|
- "Loop unrolling");
|
|
|
- ("index", Index.phase, always,
|
|
|
- "Index analysis");
|
|
|
- ("assemble", Assemble.phase, always,
|
|
|
- "Assembly");
|
|
|
- ("peephole", Peephole.phase, when_optimize,
|
|
|
- "Peephole optimization");
|
|
|
- ("output", Output.phase, always,
|
|
|
- "Output assembly");
|
|
|
-]
|
|
|
-
|
|
|
(* Parse command-line arguments *)
|
|
|
let parse_args () =
|
|
|
- let rec upto_usage = function
|
|
|
- | [] -> ""
|
|
|
- | (id, _, _, msg) :: tl ->
|
|
|
- "\n" ^ repeat " " 12 ^ expand 10 id ^ ": " ^ msg ^ (upto_usage tl)
|
|
|
+ let usage =
|
|
|
+"Usage: " ^ Sys.argv.(0) ^ " \
|
|
|
+[-h] [-o <file>] [-v <verbosity>] [-nocpp] [-noopt] [-upto <phase>] [<file>]
|
|
|
+-h Display this help message
|
|
|
+-o <file> Optional output file (defaults to stdout)
|
|
|
+-v <num> Set verbosity: 0: nothing, 1: errors (default), 2: intermediate, 3: debug
|
|
|
+-nocpp Disable C preprocessor
|
|
|
+-noopt Disable optimization phases (constprop, unroll, peephole)
|
|
|
+-upto <phase> Stop after the specified phase, and print the intermediate
|
|
|
+ representation to stderr.
|
|
|
+ Possible options are (in order of execution):
|
|
|
+ load : Load input file and run C preprocessor
|
|
|
+ parse : Parse input
|
|
|
+ desug : Desugaring
|
|
|
+ context : Context analysis
|
|
|
+ typecheck : Type checking
|
|
|
+ dimreduce : Array dimension reduction
|
|
|
+ boolop : Convert boolean operations
|
|
|
+ constprop : Constant propagation and folding
|
|
|
+ unroll : Loop unrolling
|
|
|
+ assemble : Assembly code generation
|
|
|
+ peephole : Peephole optimization
|
|
|
+<file> Optional input file (default is to read from stdin)
|
|
|
+"
|
|
|
in
|
|
|
- let args_spec = [
|
|
|
- ("<file>", Arg.Rest (fun s -> ()),
|
|
|
- " Optional input file (default is to read from stdin)");
|
|
|
|
|
|
- ("-o", Arg.String (fun s -> Globals.args.outfile <- Some s),
|
|
|
- "<file> Output file (defaults to stdout)");
|
|
|
+ let rec handle = function
|
|
|
+ | [("-v" | "-o" | "-upto") as arg] ->
|
|
|
+ raise (Failure ("missing argument value for \"" ^ arg ^ "\""))
|
|
|
+ | ("-v" | "-o" | "-upto") as arg :: next :: _ when next.[0] = '-' ->
|
|
|
+ raise (Failure ("missing argument value for \"" ^ arg ^ "\""))
|
|
|
|
|
|
- ("-v", Arg.Int (fun i -> Globals.args.verbose <- i),
|
|
|
- "<num> Set verbosity (0: nothing, 1: errors, 2: intermediate, 3: debug)");
|
|
|
+ | "-h" :: _ ->
|
|
|
+ prerr_string usage;
|
|
|
+ exit 0
|
|
|
|
|
|
- ("-nocpp", Arg.Unit (fun _ -> Globals.args.cpp <- false),
|
|
|
- " Disable C preprocessor");
|
|
|
- ("-cpp", Arg.Unit (fun _ -> Globals.args.cpp <- true),
|
|
|
- " Enable C preprocessor (overwrite earlier -nocpp)");
|
|
|
+ | "-v" :: num :: tl ->
|
|
|
+ begin
|
|
|
+ try
|
|
|
+ Globals.args.verbose <- int_of_string num;
|
|
|
+ handle tl
|
|
|
+ with Failure "int_of_string" ->
|
|
|
+ raise (Failure ("invalid verbosity level"))
|
|
|
+ end
|
|
|
+ | "-o" :: filename :: tl ->
|
|
|
+ Globals.args.outfile <- Some filename;
|
|
|
+ handle tl
|
|
|
+ | "-nocpp" :: tl ->
|
|
|
+ Globals.args.cpp <- false;
|
|
|
+ handle tl
|
|
|
+ | "-noopt" :: tl ->
|
|
|
+ Globals.args.optimize <- false;
|
|
|
+ handle tl
|
|
|
+ | "-upto" :: id :: tl ->
|
|
|
+ Globals.args.endphase <- id;
|
|
|
+ handle tl
|
|
|
+ | arg :: tl when arg.[0] = '-' ->
|
|
|
+ raise (Failure ("unknown option \"" ^ arg ^ "\""))
|
|
|
+ | filename :: tl ->
|
|
|
+ Globals.args.infile <- Some filename;
|
|
|
+ handle tl
|
|
|
+ | [] -> ()
|
|
|
+ in
|
|
|
|
|
|
- ("-noopt", Arg.Unit (fun _ -> Globals.args.optimize <- false),
|
|
|
- " Disable optimization");
|
|
|
- ("-opt", Arg.Unit (fun _ -> Globals.args.optimize <- true),
|
|
|
- " Enable optimization (overwrite earlier -noopt)");
|
|
|
+ try
|
|
|
+ handle (List.tl (Array.to_list Sys.argv))
|
|
|
+ with Failure msg ->
|
|
|
+ prerr_endline msg;
|
|
|
+ prerr_string usage;
|
|
|
+ exit 1
|
|
|
|
|
|
- ("-upto", Arg.String (fun s -> Globals.args.endphase <- s),
|
|
|
- "<phase> Stop after the specified phase, and print the intermediate \
|
|
|
- representation to stderr.\n \
|
|
|
- Possible options are (in order of execution):" ^ upto_usage phases);
|
|
|
- ] in
|
|
|
+(* Main function, returns exit status
|
|
|
+ * Command-line arguments are stored in Globals.args *)
|
|
|
+let () =
|
|
|
+ parse_args ();
|
|
|
|
|
|
- let usage =
|
|
|
- "Usage: " ^ Sys.argv.(0) ^ " [-o <file>] [-nocpp] [-noopt] \
|
|
|
- [-v <verbosity>] [-upto <phase>] [<file>]"
|
|
|
+ let run_phase condition phase msg = function
|
|
|
+ | Some input when condition ->
|
|
|
+ if String.length msg > 0 then log_plain_line 2 ("- " ^ msg);
|
|
|
+ Some (phase input)
|
|
|
+ | value -> value
|
|
|
in
|
|
|
|
|
|
- Arg.parse args_spec (fun s -> Globals.args.infile <- Some s) usage
|
|
|
+ let always = true in
|
|
|
+ let when_opt = Globals.args.optimize in
|
|
|
|
|
|
-(* Compile CVC file to assembly code *)
|
|
|
-let compile () =
|
|
|
- let rec run_phases input = function
|
|
|
- | [] -> ()
|
|
|
- | (id, phase, cond, msg) :: tl ->
|
|
|
- let output =
|
|
|
- if cond () then begin
|
|
|
- log_plain_line 2 (expand 13 ("- " ^ id ^ ":") ^ msg);
|
|
|
- let output = phase input in
|
|
|
- if id = Globals.args.endphase || Globals.args.verbose >= 2 then begin
|
|
|
- ignore (Print.phase output)
|
|
|
- end;
|
|
|
- output
|
|
|
- end else
|
|
|
- input
|
|
|
- in
|
|
|
- if id = Globals.args.endphase then () else run_phases output tl
|
|
|
+ let print_ir condition only_if_endphase id = function
|
|
|
+ | Some input when id = Globals.args.endphase ->
|
|
|
+ ignore (Print.phase input);
|
|
|
+ None
|
|
|
+ | Some input when condition && not only_if_endphase && Globals.args.verbose >= 2 ->
|
|
|
+ ignore (Print.phase input);
|
|
|
+ Some input
|
|
|
+ | value -> value
|
|
|
in
|
|
|
- run_phases Empty phases
|
|
|
|
|
|
-(* Main function, returns exit status
|
|
|
- * Command-line arguments are stored in lobals.args *)
|
|
|
-let main () =
|
|
|
try
|
|
|
- parse_args ();
|
|
|
- compile ();
|
|
|
- 0
|
|
|
+ Some Empty
|
|
|
+ |> run_phase always Load.phase "Load input file and run C preprocessor"
|
|
|
+ |> print_ir always false "load"
|
|
|
+ |> run_phase always Parse.phase "Parse input"
|
|
|
+ |> print_ir always false "parse"
|
|
|
+ |> run_phase always Desug.phase "Desugaring"
|
|
|
+ |> print_ir always false "desug"
|
|
|
+ |> run_phase always Context.phase "Context analysis"
|
|
|
+ |> print_ir always true "context"
|
|
|
+ |> run_phase always Typecheck.phase "Type checking"
|
|
|
+ |> print_ir always true "typecheck"
|
|
|
+ |> run_phase always Dimreduce.phase "Array dimension reduction"
|
|
|
+ |> print_ir always false "dimreduce"
|
|
|
+ |> run_phase always Boolop.phase "Convert boolean operations"
|
|
|
+ |> print_ir always false "boolop"
|
|
|
+ |> run_phase when_opt Constprop.phase "Constant propagation and folding"
|
|
|
+ |> print_ir when_opt false "constprop"
|
|
|
+ |> run_phase when_opt Unroll.phase "Loop unrolling"
|
|
|
+ |> run_phase when_opt Constprop.phase ""
|
|
|
+ |> print_ir when_opt false "unroll"
|
|
|
+ |> run_phase always Index.phase ""
|
|
|
+ |> run_phase always Assemble.phase "Assembly code generation"
|
|
|
+ |> print_ir always false "assemble"
|
|
|
+ |> run_phase when_opt Peephole.phase "Peephole optimization"
|
|
|
+ |> print_ir when_opt false "peephole"
|
|
|
+ |> run_phase always Output.phase ""
|
|
|
+ |> ignore
|
|
|
with FatalError err ->
|
|
|
print_error err;
|
|
|
- 1
|
|
|
-
|
|
|
-let _ = exit (main ())
|
|
|
+ exit 1
|