print.ml 3.5 KB

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