summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaweł Dybiec <pdybiec@stud.cs.uni.wroc.pl>2018-12-09 17:49:20 +0100
committerPaweł Dybiec <pdybiec@stud.cs.uni.wroc.pl>2018-12-09 17:49:20 +0100
commitd8e44d7e8e043eb5559ff7228f2bd6c4ecbce3f0 (patch)
treec674515acd43f2d81290fad9443d08fc75c20ff4
parentFix topdown strategy for add (diff)
Initial code for translator
-rw-r--r--source/mod_student/plugin.ml14
-rw-r--r--source/mod_student/translator.ml209
-rw-r--r--source/xi/.merlin15
-rw-r--r--source/xi/pipeline.ml2
-rw-r--r--source/xi/xi.ml2
-rw-r--r--source/xi_lib/.merlin5
-rw-r--r--source/xi_lib/analysis_domain.ml4
-rw-r--r--source/xi_lib/ir.ml65
-rw-r--r--source/xi_lib/ir_utils.ml15
-rw-r--r--source/xi_lib/logger.ml6
-rw-r--r--xisdk/mod_uwr.cmabin1205101 -> 1208788 bytes
11 files changed, 304 insertions, 33 deletions
diff --git a/source/mod_student/plugin.ml b/source/mod_student/plugin.ml
index 41487d3..33e2f27 100644
--- a/source/mod_student/plugin.ml
+++ b/source/mod_student/plugin.ml
@@ -28,21 +28,17 @@ module Plugin : PLUGIN = struct
   let make_spill_costs_analysis = None
 
   let lexer_and_parser = None
+
   (*
-   * Przenieś pliki parser.mly oraz lexer.mll z poprzedniego rozwiązania 
-   * i odkomentuj poniższą linijkę.
-   *
-   * Przenoszenie rozwiązania nie jest wymagane. Pamiętaj, że możesz napotkać
-   * trudności gdy rozwiązanie z poprzedniej pracowni okaże się nie do końca
-   * kompatybilne z kształtem danych oczekiwanym przez resztę modułów
-   * kompilatora.
-   *
   let lexer_and_parser = Some (module LexerAndParser : LEXER_AND_PARSER)
    *)
 
+  let make_typechecker = None
+  (*
   let make_typechecker = Some (module Typechecker.Make : MAKE_TYPECHECKER)
+   *)
 
-  let make_translator = None
+  let make_translator = Some (module Translator.Make : MAKE_TRANSLATOR)
 
   let make_jump_threading = None
 
diff --git a/source/mod_student/translator.ml b/source/mod_student/translator.ml
new file mode 100644
index 0000000..1514319
--- /dev/null
+++ b/source/mod_student/translator.ml
@@ -0,0 +1,209 @@
+open Xi_lib
+open Ir
+
+let i32_0 = Int32.of_int 0
+let i32_1 = Int32.of_int 1
+
+(* --------------------------------------------------- *)
+
+module Make() = struct
+
+  module Environment = struct
+
+    type env = Env of
+      { procmap: procid Ast.IdMap.t
+      ; varmap: reg Ast.IdMap.t
+      }
+
+    let empty =
+      let procmap = Ast.IdMap.empty in
+      let varmap = Ast.IdMap.empty in
+      Env {procmap; varmap}
+
+
+    let add_proc id procid (Env {procmap; varmap}) =
+      let procmap = Ast.IdMap.add id procid procmap in
+      Env {procmap; varmap}
+
+    let add_var id reg (Env {procmap; varmap}) =
+      let varmap = Ast.IdMap.add id reg varmap in
+      Env {procmap; varmap}
+
+    let lookup_proc id (Env {procmap; _}) =
+      try
+        Ast.IdMap.find id procmap
+      with Not_found ->
+        failwith @@ Format.sprintf "Unknown procedure identifier: %s" (Ast.string_of_identifier id)
+
+    let lookup_var id (Env {varmap; _}) =
+      try
+        Ast.IdMap.find id varmap
+      with Not_found ->
+        failwith @@ Format.sprintf "Unknown variable identifier: %s" (Ast.string_of_identifier id)
+
+  end
+
+
+(* --------------------------------------------------- *)
+  module Scanner = struct
+
+    let mangle_id id =
+      Format.sprintf "_I_%s" (Ast.string_of_identifier id)
+
+    let rec mangle_texpr = function
+      | Ast.TEXPR_Int _ -> "i"
+      | Ast.TEXPR_Bool _ -> "b"
+      | Ast.TEXPR_Array {sub;_} -> "a" ^ mangle_texpr sub
+
+
+    let mangle_var_declaration v = mangle_texpr @@ Ast.type_expression_of_var_declaration v
+
+    let mangle_formal_parameters xs = String.concat "" (List.map mangle_var_declaration xs)
+
+    let mangle_return_types xs = String.concat "" (List.map mangle_texpr xs)
+
+    let scan_global_declaration (env, symbols) = function
+      | Ast.GDECL_Function {id; formal_parameters; return_types; _} ->
+        let name = Format.sprintf "%s_%s_%s" 
+          (mangle_id id) (mangle_formal_parameters formal_parameters) (mangle_return_types return_types)
+          in
+        
+        Environment.add_proc id (Procid name) env, Procid name :: symbols
+
+    let scan_module env (Ast.ModuleDefinition {global_declarations; _}) = 
+      List.fold_left scan_global_declaration (env, []) global_declarations
+
+  end
+(* --------------------------------------------------- *)
+
+  module type SContext = sig
+
+    val cfg : ControlFlowGraph.t
+
+    val node2type: (Ast.node_tag, Types.normal_type) Hashtbl.t
+
+    val allocate_register: unit -> reg
+  end
+
+(* --------------------------------------------------- *)
+  module Translator(M:SContext) = struct
+    open M
+
+    (* dodaj instrukcje do bloku *)
+    let append_instruction l i =
+      let block = ControlFlowGraph.block cfg l in
+      ControlFlowGraph.set_block cfg l (block @ [i])
+
+    (* ustaw terminator na skok bezwarunkowy *)
+    let set_jump l_from l_to =
+      ControlFlowGraph.set_terminator cfg l_from @@ T_Jump l_to;
+      ControlFlowGraph.connect cfg l_from l_to
+
+    (* ustaw terminator na powrót-z-procedury *)
+    let set_return l_from xs =
+      ControlFlowGraph.set_terminator cfg l_from @@ T_Return xs;
+      ControlFlowGraph.connect cfg l_from (ControlFlowGraph.exit_label cfg)
+
+    (* ustaw terminator na skok warunkowy *)
+    let set_branch cond a b l_from l_to1 l_to2 =
+      ControlFlowGraph.set_terminator cfg l_from @@ T_Branch (cond, a, b, l_to1, l_to2);
+      ControlFlowGraph.connect cfg l_from l_to1;
+      ControlFlowGraph.connect cfg l_from l_to2
+
+    let allocate_block () = ControlFlowGraph.allocate_block cfg
+
+    let i32_0 = Int32.of_int 0
+    let i32_1 = Int32.of_int 1
+
+    (* --------------------------------------------------- *)
+    let rec translate_expression env current_bb = function
+      | Ast.EXPR_Char {value; _} ->
+        current_bb, E_Int (Int32.of_int @@ Char.code value)
+
+      | Ast.EXPR_Id {id; _} ->
+        current_bb, E_Reg (Environment.lookup_var id env)
+
+      | _ ->
+        failwith "not yet implemented"
+
+    (* --------------------------------------------------- *)
+    and translate_condition env current_bb else_bb = function 
+      | Ast.EXPR_Bool {value=true; _} ->
+        current_bb
+
+      | Ast.EXPR_Bool {value=false; _} ->
+        set_jump current_bb else_bb;
+        allocate_block ()
+
+      (* Zaimplementuj dodatkowe przypadki *)
+
+      | e ->
+        let current_bb, res = translate_expression env current_bb e in
+        let next_bb = allocate_block () in 
+        set_branch COND_Ne res (E_Int i32_0) current_bb next_bb else_bb;
+        next_bb
+
+
+    (* --------------------------------------------------- *)
+
+    let rec translate_statement env current_bb = function
+      | _ ->
+        failwith "not yet implemented"
+
+
+    and translate_block env current_bb (Ast.STMTBlock {body; _}) =
+      failwith "not yet implemented"
+
+    let bind_var_declaration env vardecl =
+      let r = allocate_register () in
+      let env = Environment.add_var (Ast.identifier_of_var_declaration vardecl) r env in
+      env, r
+
+    let bind_formal_parameters env xs =
+      let f env x = fst (bind_var_declaration env x) in 
+      List.fold_left f env xs
+
+  let translate_global_definition env = function
+    | Ast.GDECL_Function {id; body=Some body; formal_parameters;_} ->
+      let procid = Environment.lookup_proc id env in 
+      let frame_size = 0 in
+      let env = bind_formal_parameters env formal_parameters in
+      let formal_parameters = List.length formal_parameters in
+      let proc = Procedure {procid; cfg; frame_size; allocate_register; formal_parameters} in
+      let first_bb = allocate_block () in
+      let _, last_bb = translate_block env first_bb body in 
+      ControlFlowGraph.connect cfg  last_bb (ControlFlowGraph.exit_label cfg);
+      ControlFlowGraph.connect cfg  (ControlFlowGraph.entry_label cfg) first_bb;
+      [proc]
+    
+    | _ ->
+      []
+
+  end
+
+  let make_allocate_register () = 
+    let counter = ref 0 in
+    fun () ->
+      let i = !counter in
+      incr counter;
+      REG_Tmp i
+
+
+    let translate_global_definition node2type env gdef = 
+      let cfg = ControlFlowGraph.create () in
+      let module T = Translator(struct
+        let cfg = cfg
+        let node2type = node2type
+        let allocate_register = make_allocate_register ()
+      end) in
+      T.translate_global_definition env gdef
+
+    let translate_module node2type env (Ast.ModuleDefinition {global_declarations; _}) =
+      List.flatten @@ List.map (translate_global_definition node2type env) global_declarations
+
+    let translate_module mdef node2type =
+      let env = Environment.empty in
+      let env, symbols = Scanner.scan_module env mdef in
+      let procedures = translate_module node2type env mdef in
+      Program {procedures; symbols}
+  end
diff --git a/source/xi/.merlin b/source/xi/.merlin
new file mode 100644
index 0000000..dc01a8e
--- /dev/null
+++ b/source/xi/.merlin
@@ -0,0 +1,15 @@
+B /home/wieczyk/.opam/4.07.0/lib/bytes
+B /home/wieczyk/.opam/4.07.0/lib/cmdliner
+B /home/wieczyk/.opam/4.07.0/lib/ocaml
+B /home/wieczyk/.opam/4.07.0/lib/ocamlgraph
+B /home/wieczyk/.opam/4.07.0/lib/result
+B ../../_build/default/source/xi/.xi.eobjs
+B ../../_build/default/source/xi_lib/.xi_lib.objs
+S /home/wieczyk/.opam/4.07.0/lib/bytes
+S /home/wieczyk/.opam/4.07.0/lib/cmdliner
+S /home/wieczyk/.opam/4.07.0/lib/ocaml
+S /home/wieczyk/.opam/4.07.0/lib/ocamlgraph
+S /home/wieczyk/.opam/4.07.0/lib/result
+S .
+S ../xi_lib
+FLG -w @a-4-29-40-41-42-44-45-48-58-59-60-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -w -39-33-26-27
diff --git a/source/xi/pipeline.ml b/source/xi/pipeline.ml
index ae9a4c9..190a3f3 100644
--- a/source/xi/pipeline.ml
+++ b/source/xi/pipeline.ml
@@ -22,7 +22,7 @@ module Make(Steps:COMPILER_STEPS)(Params:PARAMS) = struct
 
   let describe_register_mapping mapping =
     let describe_map k v xs =
-      let entry = Format.sprintf "%s -> %s" (Ir.string_of_reg k) (Ir.string_of_reg v) in
+      let entry = Format.sprintf "%s -> %s" (Ir_utils.string_of_reg k) (Ir_utils.string_of_reg v) in
       entry :: xs
     in
     String.concat "\n" @@ Hashtbl.fold describe_map mapping []
diff --git a/source/xi/xi.ml b/source/xi/xi.ml
index d59dbf6..c54a499 100644
--- a/source/xi/xi.ml
+++ b/source/xi/xi.ml
@@ -72,7 +72,7 @@ module CommandLine = struct
 
   let cmd =
     let doc = "Compile Xi Program" in
-    let version = "pracownia2.3-0-g63fd12e" in
+    let version = "pracownia3.1-0-g147dd61" in
     Term.(const compile $ xi_log $ extra_debug $ mod_uwr $ plugin $ reg_descr $ stop_after $ output $ source_file),
     Term.info "xi" ~doc ~version
 
diff --git a/source/xi_lib/.merlin b/source/xi_lib/.merlin
new file mode 100644
index 0000000..e44069f
--- /dev/null
+++ b/source/xi_lib/.merlin
@@ -0,0 +1,5 @@
+B /home/wieczyk/.opam/4.07.0/lib/ocamlgraph
+B ../../_build/default/source/xi_lib/.xi_lib.objs
+S /home/wieczyk/.opam/4.07.0/lib/ocamlgraph
+S .
+FLG -open Xi_lib -w @a-4-29-40-41-42-44-45-48-58-59-60-40 -strict-sequence -strict-formats -short-paths -keep-locs
diff --git a/source/xi_lib/analysis_domain.ml b/source/xi_lib/analysis_domain.ml
index 9f49a3e..db124e0 100644
--- a/source/xi_lib/analysis_domain.ml
+++ b/source/xi_lib/analysis_domain.ml
@@ -103,7 +103,7 @@ module ConstantFolding = struct
     | Some a -> Ir_utils.string_of_expr a
 
   let string_of_domain dom =
-    let f (k,v) = Format.sprintf "%s=%s" (Ir.string_of_reg k) (string_of_el v) in
+    let f (k,v) = Format.sprintf "%s=%s" (Ir_utils.string_of_reg k) (string_of_el v) in
     let seq = Ir.RegMap.to_seq dom in
     let seq = Seq.map f seq in
     String.concat " " @@ List.of_seq seq
@@ -132,4 +132,4 @@ module ReachabilityAnalysis = struct
 
   type table = Ir.LabelSet.t Analysis.BlockKnowledge.table
 
-end
\ No newline at end of file
+end
diff --git a/source/xi_lib/ir.ml b/source/xi_lib/ir.ml
index b611916..f7d2c96 100644
--- a/source/xi_lib/ir.ml
+++ b/source/xi_lib/ir.ml
@@ -1,12 +1,11 @@
 type reg
+    (* rejestr tymczasowy *)
   = REG_Tmp of int
+    (* rejestr sprzętowy *)
   | REG_Hard of int
+    (* rejestr sprzętowy specjalnego przeznaczenia *)
   | REG_Spec of int
 
-let string_of_reg = function
-  | REG_Tmp i -> Format.sprintf "%%tmp%u" i
-  | REG_Hard i -> Format.sprintf "%%hard%u" i
-  | REG_Spec i -> Format.sprintf "%%spec%u" i
 
 let is_spec_reg = function
   | REG_Spec _ -> true
@@ -69,49 +68,74 @@ type cond
   | COND_Le
   | COND_Ge
 
-let string_of_cond = function
-  | COND_Eq -> "eq"
-  | COND_Ne -> "ne"
-  | COND_Lt -> "lt"
-  | COND_Gt -> "gt"
-  | COND_Le -> "le"
-  | COND_Ge -> "ge"
-
 
 type instr
+    (* dodaj *)
   = I_Add of reg * expr * expr
+    (* odejmij *)
   | I_Sub of reg * expr * expr
+    (* podziel *)
   | I_Div of reg * expr * expr
+    (* reszta z dzielenia *)
   | I_Rem of reg * expr * expr
+    (* pomnóż *)
   | I_Mul of reg * expr * expr
+    (* bitowy and *)
   | I_And of reg * expr * expr
+    (* bitowy or *)
   | I_Or of reg * expr * expr
+    (* bitowy xor *)
   | I_Xor of reg * expr * expr
+    (* LoadArray(r, xs, i) oznacza załaduj i-ty element tablicy xs do rejestru r *)
   | I_LoadArray of reg * expr * expr
+    (* StoreArray(xs, i, e) oznacza zapisz do i-tego elementu tablicy xs atom e *)
   | I_StoreArray of expr * expr * expr
+    (* LoadMem(r, xs, i) oznacza załaduj komórkę pamięci o adresie (xs+i) do rejestru r*)
   | I_LoadMem of reg * expr * expr
+    (* StoreMem(xs, i, e) oznacza zapisz do komórki pamięci o adresie (xs+i) atom e *)
   | I_StoreMem of expr * expr * expr
+    (* wysokopoziomowa instrukcja: konkatenacja tablic *)
   | I_Concat of reg * expr * expr
+    (* zaneguj liczbę *)
   | I_Neg of reg * expr
+    (* bitowy not *)
   | I_Not of reg * expr
+    (* zapisz atom do rejestru *)
   | I_Move of reg * expr
+    (* wysokopoziomowa instrukcja: zapisuje do rejestru długość tablicy *)
   | I_Length of reg * expr
+    (* wysokopoziomowa instrukcja: zaalokuj tablicę o określonym rozmiarze *)
   | I_NewArray of reg * expr
+    (* I_Call(rs, p, xs, ms) oznacza wywołaj p z argumentami xs, wyniki
+     * funkcji znajdą się w rejestrach rs, dodatkowo zostaną zmodyfikowane rejestry ms *)
   | I_Call of reg list * procid * expr list * reg list
-  | I_Set of reg * cond * expr * expr  
+    (* I_Set(r, cond, a, b) zapisz do rejestru r wartość boolowską warunku cond(a,b) *)
+  | I_Set of reg * cond * expr * expr
+    (* załaduj do rejestru zmienną lokalną *)
   | I_LoadVar of reg * int
+    (* zapisz atom do zmiennej lokalnej *)
   | I_StoreVar of int * expr
+    (* załaduj do rejestru komórkę ze stosu *)
   | I_LoadStack of reg * int
+    (* zapisz do komórki na stosie atom *)
   | I_StoreStack of int * expr
+    (* przydziel stos *)
   | I_StackAlloc of Int32.t
+    (* zwolnij stos *)
   | I_StackFree of Int32.t
+    (* meta-instrukcja, podane rejestry będą uznawane za użyte *)
   | I_Use of reg list
+    (* meta-instrukcja, podane rejestry będą uznane za zmodyfikowane *)
   | I_Def of reg list
 
 
 type terminator =
+    (* return *)
   | T_Return of expr list
+    (* T_Branch(cond, a, b, then_bb, else_bb) oznacza skok warunkowy
+     * if cond(a,b) then goto then_bb else goto else_bb *)
   | T_Branch of cond * expr * expr * label * label
+    (* skok bezwarunkowy *)
   | T_Jump of label 
 
 let labels_of_terminator = function
@@ -122,13 +146,13 @@ let labels_of_terminator = function
 type block = instr list
 
 module LabelGraph = Graph.Imperative.Digraph.ConcreteBidirectional(struct 
-(*module LabelGraph = Mygraph.MakeBidirectional(struct *)
   type t = label
   let compare = compare
   let hash = Hashtbl.hash
   let equal a b = a = b
   end)
 
+(* Reprezentacja ciała funkcji *)
 module ControlFlowGraph = struct
 
   type graph = LabelGraph.t 
@@ -253,11 +277,17 @@ module ControlFlowGraph = struct
 
 end
 
+(* Reprezentacja całej procedury *)
 type procedure = Procedure of
+    (* identyfikator *)
   { procid: procid
+    (* graf sterowania *)
   ; cfg: ControlFlowGraph.t
+    (* rozmiar rekordu aktywacji *)
   ; mutable frame_size: int
+    (* ilość parametrów formalnych *)
   ; formal_parameters: int
+    (* funkcja do przydzielania świeżych rejestrów wewnątrz danej proceduy *)
   ; allocate_register: unit -> reg
   }
 
@@ -278,11 +308,14 @@ let procid_of_procedure (Procedure {procid; _}) = procid
 let frame_size_of_procedure (Procedure {frame_size; _}) = frame_size
 
 
+(* Reprezentacja programu *)
 type program = Program of
+    (* lista procedur *)
   { procedures: procedure list
-  ; externals: procid list
+    (* lista wszystkich symboli *)
+  ; symbols: procid list
   }
 
 let procedures_of_program (Program{procedures; _}) = procedures
 
-let externals_of_program (Program{externals; _}) = externals
+let symbols_of_program (Program{symbols; _}) = symbols
diff --git a/source/xi_lib/ir_utils.ml b/source/xi_lib/ir_utils.ml
index 48b59a1..b43655d 100644
--- a/source/xi_lib/ir_utils.ml
+++ b/source/xi_lib/ir_utils.ml
@@ -1,5 +1,18 @@
 open Ir
 
+let string_of_reg = function
+  | REG_Tmp i -> Format.sprintf "%%tmp%u" i
+  | REG_Hard i -> Format.sprintf "%%hard%u" i
+  | REG_Spec i -> Format.sprintf "%%spec%u" i
+
+let string_of_cond = function
+  | COND_Eq -> "eq"
+  | COND_Ne -> "ne"
+  | COND_Lt -> "lt"
+  | COND_Gt -> "gt"
+  | COND_Le -> "le"
+  | COND_Ge -> "ge"
+
 let remap_register_reg sb r = 
   try
     Hashtbl.find sb r
@@ -665,4 +678,4 @@ let string_of_module_definition xs =
   String.concat "\n" @@ List.map string_of_procedure xs
 
 let string_of_program (Program {procedures; _}) =
-  String.concat "\n" @@ List.map string_of_procedure procedures
\ No newline at end of file
+  String.concat "\n" @@ List.map string_of_procedure procedures
diff --git a/source/xi_lib/logger.ml b/source/xi_lib/logger.ml
index 746bbb8..26ce286 100644
--- a/source/xi_lib/logger.ml
+++ b/source/xi_lib/logger.ml
@@ -134,7 +134,7 @@ let dump_ir_proc title irproc =
   dump_string title buffer
 
 let dump_spill_costs spill_costs =
-  let f (k,v) = Format.sprintf "%s -> %u" (Ir.string_of_reg k) v in 
+  let f (k,v) = Format.sprintf "%s -> %u" (Ir_utils.string_of_reg k) v in 
   let seq = Hashtbl.to_seq spill_costs in
   let seq = Seq.map f seq in
   let seq = List.of_seq seq in
@@ -142,7 +142,7 @@ let dump_spill_costs spill_costs =
   dump_string "spill_costs" buf
 
 let dump_spill_costs_f spill_costs =
-  let f (k,v) = Format.sprintf "%s -> %f" (Ir.string_of_reg k) v in 
+  let f (k,v) = Format.sprintf "%s -> %f" (Ir_utils.string_of_reg k) v in 
   let seq = Hashtbl.to_seq spill_costs in
   let seq = Seq.map f seq in
   let seq = List.of_seq seq in
@@ -167,4 +167,4 @@ let dump_constant_folding title cfg table =
   dump_string (title ^ ".cfa.xdot") buffer
 
 let init xilog =
-  FS.init xilog
\ No newline at end of file
+  FS.init xilog
diff --git a/xisdk/mod_uwr.cma b/xisdk/mod_uwr.cma
index 1bb9965..827e6e2 100644
--- a/xisdk/mod_uwr.cma
+++ b/xisdk/mod_uwr.cma
Binary files differ