| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- open Printf
- open Types
- open Util
- open Stringify
- let comline comment = InlineComment (EmptyLine, comment)
- let assemble program =
- let labcounter = ref 0 in
- let genlabel suffix =
- labcounter := !labcounter + 1;
- string_of_int !labcounter ^ "_" ^ suffix
- in
- let consts = Hashtbl.create 20 in
- let rec trav_args callstack node =
- let trav = trav_args callstack in
- let rec trav_all = function
- | [] -> []
- | hd :: tl -> trav hd @ (trav_all tl)
- in
- let rec traverse_localfuns callstack = function
- | LocalFuns body -> List.concat (List.map (trav_args callstack) body)
- | Block body -> List.concat (List.map (traverse_localfuns callstack) body)
- | _ -> []
- in
- match node with
- (* Global *)
- | Program (decls, _) ->
- trav_all decls
- | GlobalDef (_, ctype, _, _, _) ->
- [Global ctype]
- | FunDec (ret_type, name, params, _) ->
- [Import (name, ret_type, List.map typeof params)]
- | FunDef (export, ret_type, name, params, body, _) ->
- let callstack = name :: callstack in
- let label = String.concat "$" (List.rev callstack) in
- (if export then
- let param_types = List.map typeof params in
- [Export (name, ret_type, param_types, label)]
- else []) @
- [
- Comment ("function \"" ^ label ^ "\":");
- Label label;
- RtnEnter (indexof node);
- ] @
- (trav_args callstack body) @
- (match ret_type with Void -> [Ret Void] | _ -> []) @
- [EmptyLine] @
- (traverse_localfuns callstack body)
- | VarDec (ctype, name, _, _) ->
- [comline (sprintf "index %d: %s %s" (indexof node) (type2str ctype) name)]
- | LocalFuns _ -> []
- | Block body | VarDecs body -> trav_all body
- (* Statements *)
- | VarLet (dec, None, value, _) ->
- let store = match (depthof dec, depthof node) with
- | (0, _) -> StoreGlob (typeof dec, indexof dec)
- | (a, b) when a = b -> StoreLoc (typeof dec, indexof dec)
- | (a, b) -> StoreRel (typeof dec, b - a, indexof dec)
- in
- trav value @ [InlineComment (store, node2str node)]
- | Return (value, _) ->
- trav value @ [InlineComment (Ret (typeof value), node2str node)]
- (* Expressions *)
- | Const (BoolVal _, _) ->
- [LoadImm node]
- | Const (value, _) ->
- let def = if Hashtbl.mem consts value then [] else (
- Hashtbl.add consts value true;
- [ConstDef value]
- ) in
- def @ [LoadConst (typeof node, indexof node)]
- | VarUse (dec, None, _) ->
- let load = match (depthof dec, depthof node) with
- | (0, _) -> LoadGlob (typeof dec, indexof dec)
- | (a, b) when a = b -> LoadLoc (typeof dec, indexof dec)
- | (a, b) -> LoadRel (typeof dec, b - a, indexof dec)
- in
- [InlineComment (load, node2str node)]
- | Monop (op, value, _) ->
- trav value @ [Op (op, typeof node)]
- | Binop (op, left, right, _) ->
- trav left @ (trav right) @ [Op (op, typeof node)]
- | TypeCast (ctype, value, _) ->
- let vtype = typeof value in
- (match (ctype, vtype) with
- | (Float, Int) | (Int, Float) -> ()
- | _ -> raise (NodeError (node, "invalid typecast"))
- );
- trav value @ [Convert (vtype, ctype)]
- | _ -> [Comment ("FIXME: " ^ Stringify.node2str node)]
- (*| _ -> raise InvalidNode*)
- in
- trav_args [] program
- let rec phase input =
- log_line 1 "- Assembly";
- match input with
- | Ast node -> Assembly (assemble node)
- | _ -> raise (InvalidInput "assembly")
|