print.ml 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. open Types
  2. open Util
  3. open Stringify
  4. let tab = " "
  5. let si = string_of_int
  6. let rec repeat s n = if n < 1 then "" else s ^ (repeat s (n - 1))
  7. let pad width s = s ^ (repeat " " (String.length s - width))
  8. let paddall width = List.map (pad width)
  9. let ctype2str = Stringify.type2str
  10. let type2str = function
  11. | Array (t, dims) -> ctype2str t ^ repeat "," (List.length dims - 1)
  12. | t -> ctype2str t
  13. let prefix = function
  14. | Bool _ -> "b"
  15. | Int _ -> "i"
  16. | Float _ -> "f"
  17. | Void _ -> ""
  18. | _ -> "a"
  19. let instr2str = function
  20. (* Global / directives *)
  21. | Comment comment ->
  22. "# " ^ comment
  23. | Label name ->
  24. name ^ ":"
  25. | Export (name, ret_type, arg_types, label) ->
  26. let types = List.map type2str (ret_type :: arg_types) in
  27. ".export \"" ^ name ^ "\" " ^ (String.concat " " types) ^ " " ^ label
  28. | Import (name, ret_type, arg_types) ->
  29. let types = List.map type2str (ret_type :: arg_types) in
  30. ".import \"" ^ name ^ "\" " ^ (String.concat " " types)
  31. | ConstDef node ->
  32. ".const " ^ (const2str node)
  33. | Global ctype ->
  34. ".global " ^ (type2str ctype)
  35. (* Store *)
  36. | StoreGlob (ctype, index) ->
  37. tab ^ prefix ctype ^ "storeg " ^ si index
  38. | StoreLoc (ctype, index) ->
  39. tab ^ prefix ctype ^ "store " ^ si index
  40. | StoreRel (ctype, nesting, index) ->
  41. tab ^ prefix ctype ^ "storen " ^ si nesting ^ " " ^ si index
  42. (* Load constant *)
  43. | LoadConst (ctype, index) ->
  44. tab ^ prefix ctype ^ "loadc " ^ si index
  45. | LoadImm (Const (BoolVal b, _)) ->
  46. tab ^ "bloadc_" ^ (if b then "t" else "f")
  47. | LoadImm (Const (IntVal i, _)) when i < 0 ->
  48. tab ^ "iloadc_m" ^ si (-i)
  49. | LoadImm (Const (IntVal i, _)) ->
  50. tab ^ "iloadc_" ^ si i
  51. | LoadImm (Const (FloatVal i, _)) ->
  52. tab ^ "floadc_" ^ si (int_of_float i)
  53. (* Control flow *)
  54. | RtnEnter stack_len ->
  55. tab ^ "esr " ^ si stack_len
  56. | Ret ctype ->
  57. tab ^ prefix ctype ^ "return"
  58. | EmptyLine -> ""
  59. | DummyInstr -> tab ^ "<dummy>"
  60. | _ -> tab ^ "<unknown instruction>"
  61. let rec print_assembly oc instrs =
  62. let output_line line =
  63. output_string oc line;
  64. output_char oc '\n';
  65. in
  66. let endbuf = ref [] in
  67. let rec trav = function
  68. | [] -> ()
  69. | hd :: tl ->
  70. let line = instr2str hd in
  71. (if String.length line > 0 && line.[0] = '.' then
  72. endbuf := line :: !endbuf
  73. else
  74. output_line line
  75. );
  76. trav tl
  77. in
  78. trav instrs;
  79. if List.length !endbuf > 1 then (
  80. output_line (instr2str (Comment ("globals:")));
  81. let cmp a b = compare (String.sub a 0 8) (String.sub b 0 8) in
  82. List.iter output_line (List.sort cmp (List.rev !endbuf))
  83. ); ()
  84. let phase = function
  85. | Ast node as input ->
  86. if args.verbose >= 2 then (
  87. prerr_endline "--------------------------------------------------";
  88. prerr_endline (node2str node);
  89. prerr_endline "--------------------------------------------------"
  90. );
  91. input
  92. | FileContent (display_name, content) as input ->
  93. if args.verbose >= 2 then (
  94. prerr_endline "--------------------------------------------------";
  95. prerr_endline (display_name ^ ":\n");
  96. prerr_endline content;
  97. prerr_endline "--------------------------------------------------"
  98. );
  99. input
  100. | Assembly instrs as input ->
  101. (match args.outfile with
  102. | Some filename ->
  103. let oc = open_out filename in
  104. print_assembly oc instrs;
  105. close_out oc
  106. | None ->
  107. if args.verbose >= 2 then
  108. prerr_endline "--------------------------------------------------";
  109. print_assembly stdout instrs;
  110. );
  111. input
  112. | _ -> raise (InvalidInput "print")