main.ml 4.1 KB

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