print.ml 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. open Types
  2. open Util
  3. open Stringify
  4. let tab = " "
  5. let max_instr_width = 26
  6. let si = string_of_int
  7. let op2str = function
  8. | Neg -> "neg"
  9. | Not -> "not"
  10. | Add -> "add"
  11. | Sub -> "sub"
  12. | Mul -> "mul"
  13. | Div -> "div"
  14. | Mod -> "rem"
  15. | Eq -> "eq"
  16. | Ne -> "ne"
  17. | Lt -> "lt"
  18. | Le -> "le"
  19. | Gt -> "gt"
  20. | Ge -> "ge"
  21. | _ -> raise (FatalError (Msg "unsupported operator"))
  22. let prefix = function
  23. | Void -> ""
  24. | Bool _ -> "b"
  25. | Int _ -> "i"
  26. | Float _ -> "f"
  27. | Array _ -> "a"
  28. | _ -> raise (FatalError (Msg "invalid type"))
  29. let suffix = function
  30. | Local -> "l"
  31. | Rel nesting -> "n " ^ si nesting
  32. | Glob -> "g"
  33. | Extern -> "e"
  34. | Current -> ""
  35. let rtn_suffix = function
  36. | ExternFun index -> "e " ^ si index
  37. | LocalFun (size, label) -> " " ^ si size ^ " " ^ label
  38. let rec instr2str = function
  39. (* Global / directives *)
  40. | Comment comment ->
  41. if Globals.args.verbose >= 2 then "; " ^ comment else ""
  42. | InlineComment (instr, comment) ->
  43. if Globals.args.verbose >= 2 then
  44. expand max_instr_width (instr2str instr) ^ " ; " ^ comment
  45. else
  46. instr2str instr
  47. | Label name ->
  48. name ^ ":"
  49. | ExportVar (name, index) ->
  50. ".exportvar \"" ^ name ^ "\" " ^ si index
  51. | ExportFun (name, ret_type, arg_types, label) ->
  52. let types = List.map type2str (ret_type :: arg_types) in
  53. ".exportfun \"" ^ name ^ "\" " ^ (String.concat " " types) ^ " " ^ label
  54. | ImportVar (name, ctype) ->
  55. ".importvar \"" ^ name ^ "\" " ^ type2str ctype
  56. | ImportFun (name, ret_type, arg_types) ->
  57. let types = List.map type2str (ret_type :: arg_types) in
  58. ".importfun \"" ^ name ^ "\" " ^ (String.concat " " types)
  59. | Global ctype ->
  60. ".global " ^ (type2str ctype)
  61. | ConstDef value ->
  62. ".const " ^ type2str (const_type value) ^ " " ^ const2str value
  63. (* Store *)
  64. | Store (ctype, scope, index) ->
  65. tab ^ prefix ctype ^ "store" ^ suffix scope ^ " " ^ si index
  66. (* Load *)
  67. | Load (ctype, Current, index) when index >= 0 & index <= 3 ->
  68. tab ^ prefix ctype ^ "load_" ^ si index
  69. | Load (ctype, scope, index) ->
  70. tab ^ prefix ctype ^ "load" ^ suffix scope ^ " " ^ si index
  71. | LoadConst (ctype, index) ->
  72. tab ^ prefix ctype ^ "loadc " ^ si index
  73. | LoadImm (BoolVal b) ->
  74. tab ^ "bloadc_" ^ (if b then "t" else "f")
  75. | LoadImm (IntVal i) when i < 0l ->
  76. tab ^ "iloadc_m" ^ Int32.to_string (Int32.neg i)
  77. | LoadImm (IntVal i) ->
  78. tab ^ "iloadc_" ^ Int32.to_string i
  79. | LoadImm (FloatVal i) ->
  80. tab ^ "floadc_" ^ si (int_of_float i)
  81. (* Operators *)
  82. | Op (op, ctype) ->
  83. tab ^ prefix ctype ^ op2str op
  84. | Convert (src, tgt) ->
  85. tab ^ prefix src ^ "2" ^ prefix tgt
  86. | Inc (index, const) ->
  87. tab ^ "iinc " ^ si index ^ " " ^ si const
  88. | Dec (index, const) ->
  89. tab ^ "idec " ^ si index ^ " " ^ si const
  90. | IncOne index ->
  91. tab ^ "iinc_1 " ^ si index
  92. | DecOne index ->
  93. tab ^ "idec_1 " ^ si index
  94. (* Control flow *)
  95. | RtnInit scope ->
  96. tab ^ "isr" ^ suffix scope
  97. | RtnJmp scope ->
  98. tab ^ "jsr" ^ rtn_suffix scope
  99. | RtnEnter stack_len ->
  100. tab ^ "esr " ^ si stack_len
  101. | Ret ctype ->
  102. tab ^ prefix ctype ^ "return"
  103. | Branch (true, target) ->
  104. tab ^ "branch_t " ^ target
  105. | Branch (false, target) ->
  106. tab ^ "branch_f " ^ target
  107. | Jump target ->
  108. tab ^ "jump " ^ target
  109. (* Stack management *)
  110. | Pop ctype ->
  111. tab ^ prefix ctype ^ "pop"
  112. (* Arrays *)
  113. | NewArray basetype ->
  114. tab ^ prefix basetype ^ "newa"
  115. | LoadArray basetype ->
  116. tab ^ prefix basetype ^ "loada"
  117. | StoreArray basetype ->
  118. tab ^ prefix basetype ^ "storea"
  119. | EmptyLine -> ""
  120. (* Print assembly instructions to the given file pointer. *)
  121. let rec print_assembly oc instrs =
  122. let output_line line =
  123. output_string oc line;
  124. output_char oc '\n'
  125. in
  126. (* Print instructions to outfile and collect directives in endbuf list *)
  127. let endbuf = ref [] in
  128. let rec trav = function
  129. | [] -> ()
  130. | EmptyLine :: tl -> output_line ""; trav tl
  131. | hd :: tl ->
  132. begin
  133. match instr2str hd with
  134. | "" -> ()
  135. | line when line.[0] = '.' -> endbuf := line :: !endbuf
  136. | line -> output_line line
  137. end;
  138. trav tl
  139. in
  140. trav instrs;
  141. (* Directives (lines beginning with a '.') are collected in endbuf and are
  142. * printed at the end of the file here. The directives are sorted by the first
  143. * 7 characters to group directive opcodes *)
  144. if List.length !endbuf > 0 then
  145. let cmp a b = compare (String.sub b 0 7) (String.sub a 0 7) in
  146. List.iter output_line (List.sort cmp (List.rev !endbuf))
  147. let phase = function
  148. | Ast node as input ->
  149. prerr_endline hline;
  150. prerr_endline (node2str node);
  151. prerr_endline hline;
  152. input
  153. | FileContent (display_name, content) as input ->
  154. prerr_endline hline;
  155. prerr_endline (display_name ^ ":\n");
  156. prerr_endline content;
  157. prerr_endline hline;
  158. input
  159. | Assembly instrs as input ->
  160. prerr_endline hline;
  161. print_assembly stderr instrs;
  162. prerr_endline hline;
  163. input
  164. | Empty -> Empty