print.ml 4.8 KB

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