main.ml 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. open Printf
  2. open Lexing
  3. open Types
  4. open Util
  5. (* For some reason OCaml wants me to redefine this type's implementation -.- *)
  6. type phase_func = Types.intermediate -> Types.intermediate
  7. let always _ = true
  8. let when_optimize _ = Globals.args.optimize
  9. (* List of all phases, which will be executed in the order defined here. *)
  10. let phases = [
  11. ("load", Load.phase, always,
  12. "Load input file");
  13. ("parse", Parse.phase, always,
  14. "Parse input");
  15. ("desug", Desug.phase, always,
  16. "Desugaring");
  17. ("context", Context.phase, always,
  18. "Context analysis");
  19. ("typecheck", Typecheck.phase, always,
  20. "Type checking");
  21. ("extern", Extern.phase, always,
  22. "Create getters and setters for extern variables");
  23. ("dimreduce", Dimreduce.phase, always,
  24. "Array dimension reduction");
  25. ("boolop", Boolop.phase, always,
  26. "Convert bool operations");
  27. ("constprop", Constprop.phase, when_optimize,
  28. "Constant propagation");
  29. ("unroll", Unroll.phase, when_optimize,
  30. "Loop unrolling");
  31. ("index", Index.phase, always,
  32. "Index analysis");
  33. ("assemble", Assemble.phase, always,
  34. "Assembly");
  35. ("peephole", Peephole.phase, when_optimize,
  36. "Peephole optimization");
  37. ("output", Output.phase, always,
  38. "Output assembly");
  39. ]
  40. (* Parse command-line arguments *)
  41. let parse_args () =
  42. let rec upto_usage = function
  43. | [] -> ""
  44. | (id, _, _, msg) :: tl ->
  45. "\n" ^ repeat " " 12 ^ expand 10 id ^ ": " ^ msg ^ (upto_usage tl)
  46. in
  47. let args_spec = [
  48. ("<file>", Arg.Rest (fun s -> ()),
  49. " Optional input file (default is to read from stdin)");
  50. ("-o", Arg.String (fun s -> Globals.args.outfile <- Some s),
  51. "<file> Output file (defaults to stdout)");
  52. ("-v", Arg.Int (fun i -> Globals.args.verbose <- i),
  53. "<num> Set verbosity (0: nothing, 1: errors, 2: intermediate, 3: debug)");
  54. ("-nocpp", Arg.Unit (fun _ -> Globals.args.cpp <- false),
  55. " Disable C preprocessor");
  56. ("-cpp", Arg.Unit (fun _ -> Globals.args.cpp <- true),
  57. " Enable C preprocessor (overwrite earlier -nocpp)");
  58. ("-noopt", Arg.Unit (fun _ -> Globals.args.optimize <- false),
  59. " Disable optimization");
  60. ("-opt", Arg.Unit (fun _ -> Globals.args.optimize <- true),
  61. " Enable optimization (overwrite earlier -nocpp)");
  62. ("-upto", Arg.String (fun s -> Globals.args.endphase <- s),
  63. "<phase> Stop after the specified phase, and print the intermediate \
  64. representation to stderr.\n \
  65. Possible options are (in order of execution):" ^ upto_usage phases);
  66. ] in
  67. let usage =
  68. "Usage: " ^ Sys.argv.(0) ^ " [-o <file>] [-nocpp] [-noopt] \
  69. [-v <verbosity>] [-upto <phase>] [<file>]"
  70. in
  71. Arg.parse args_spec (fun s -> Globals.args.infile <- Some s) usage
  72. (* Compile CVC file to assembly code *)
  73. let compile () =
  74. let rec run_phases input = function
  75. | [] -> ()
  76. | (id, phase, cond, msg) :: tl ->
  77. let output =
  78. if cond () then begin
  79. log_plain_line 2 (expand 13 ("- " ^ id ^ ":") ^ msg);
  80. let output = phase input in
  81. if id = Globals.args.endphase || Globals.args.verbose >= 2 then begin
  82. ignore (Print.phase output)
  83. end;
  84. output
  85. end else
  86. input
  87. in
  88. if id = Globals.args.endphase then () else run_phases output tl
  89. in
  90. run_phases Empty phases
  91. (* Main function, returns exit status
  92. * Command-line arguments are stored in lobals.args *)
  93. let main () =
  94. try
  95. try
  96. parse_args ();
  97. compile ();
  98. 0
  99. with
  100. (*| InvalidNode ->
  101. raise (CompileError "invalid node")*)
  102. | InvalidInput name ->
  103. raise (CompileError ("invalid input for phase \"" ^ name ^ "\""))
  104. | NodeError (node, msg) ->
  105. (* If no location is given, just stringify the node to at least give
  106. * some information *)
  107. let msg = if locof node = noloc then
  108. msg ^ "\nnode: " ^ Stringify.node2str node
  109. else msg in
  110. raise (LocError (locof node, msg))
  111. with
  112. | CompileError msg ->
  113. eprintf "Error: %s\n" msg;
  114. 1
  115. | LocError (loc, msg) ->
  116. prerr_loc_msg loc ("Error: " ^ msg);
  117. 1
  118. | EmptyError ->
  119. 1
  120. let _ = exit (main ())