main.ml 3.9 KB

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