assemble.ml 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. open Printf
  2. open Types
  3. open Util
  4. open Stringify
  5. let comline comment = InlineComment (EmptyLine, comment)
  6. let assemble program =
  7. let labcounter = ref 0 in
  8. let genlabel suffix =
  9. labcounter := !labcounter + 1;
  10. string_of_int !labcounter ^ "_" ^ suffix
  11. in
  12. let consts = Hashtbl.create 20 in
  13. let rec trav_args callstack node =
  14. let trav = trav_args callstack in
  15. let rec trav_all = function
  16. | [] -> []
  17. | hd :: tl -> trav hd @ (trav_all tl)
  18. in
  19. let rec traverse_localfuns callstack = function
  20. | LocalFuns body -> List.concat (List.map (trav_args callstack) body)
  21. | Block body -> List.concat (List.map (traverse_localfuns callstack) body)
  22. | _ -> []
  23. in
  24. match node with
  25. (* Global *)
  26. | Program (decls, _) ->
  27. trav_all decls
  28. | GlobalDef (_, ctype, _, _, _) ->
  29. [Global ctype]
  30. | FunDec (ret_type, name, params, _) ->
  31. [Import (name, ret_type, List.map typeof params)]
  32. | FunDef (export, ret_type, name, params, body, _) ->
  33. let callstack = name :: callstack in
  34. let label = String.concat "$" (List.rev callstack) in
  35. (if export then
  36. let param_types = List.map typeof params in
  37. [Export (name, ret_type, param_types, label)]
  38. else []) @
  39. [
  40. Comment ("function \"" ^ label ^ "\":");
  41. Label label;
  42. RtnEnter (indexof node);
  43. ] @
  44. (trav_args callstack body) @
  45. (match ret_type with Void -> [Ret Void] | _ -> []) @
  46. [EmptyLine] @
  47. (traverse_localfuns callstack body)
  48. | VarDec (ctype, name, _, _) ->
  49. [comline (sprintf "index %d: %s %s" (indexof node) (type2str ctype) name)]
  50. | LocalFuns _ -> []
  51. | Block body | VarDecs body -> trav_all body
  52. (* Statements *)
  53. | VarLet (dec, None, value, _) ->
  54. let store = match (depthof dec, depthof node) with
  55. | (0, _) -> StoreGlob (typeof dec, indexof dec)
  56. | (a, b) when a = b -> StoreLoc (typeof dec, indexof dec)
  57. | (a, b) -> StoreRel (typeof dec, b - a, indexof dec)
  58. in
  59. trav value @ [InlineComment (store, node2str node)]
  60. | Return (value, _) ->
  61. trav value @ [InlineComment (Ret (typeof value), node2str node)]
  62. (* Expressions *)
  63. | Const (BoolVal _, _) ->
  64. [LoadImm node]
  65. | Const (value, _) ->
  66. let def = if Hashtbl.mem consts value then [] else (
  67. Hashtbl.add consts value true;
  68. [ConstDef value]
  69. ) in
  70. def @ [LoadConst (typeof node, indexof node)]
  71. | VarUse (dec, None, _) ->
  72. let load = match (depthof dec, depthof node) with
  73. | (0, _) -> LoadGlob (typeof dec, indexof dec)
  74. | (a, b) when a = b -> LoadLoc (typeof dec, indexof dec)
  75. | (a, b) -> LoadRel (typeof dec, b - a, indexof dec)
  76. in
  77. [InlineComment (load, node2str node)]
  78. | Monop (op, value, _) ->
  79. trav value @ [Op (op, typeof node)]
  80. | Binop (op, left, right, _) ->
  81. trav left @ (trav right) @ [Op (op, typeof node)]
  82. | TypeCast (ctype, value, _) ->
  83. let vtype = typeof value in
  84. (match (ctype, vtype) with
  85. | (Float, Int) | (Int, Float) -> ()
  86. | _ -> raise (NodeError (node, "invalid typecast"))
  87. );
  88. trav value @ [Convert (vtype, ctype)]
  89. | _ -> [Comment ("FIXME: " ^ Stringify.node2str node)]
  90. (*| _ -> raise InvalidNode*)
  91. in
  92. trav_args [] program
  93. let rec phase input =
  94. log_line 1 "- Assembly";
  95. match input with
  96. | Ast node -> Assembly (assemble node)
  97. | _ -> raise (InvalidInput "assembly")