168 lines
6.4 KiB
OCaml
168 lines
6.4 KiB
OCaml
(**************************************************************************)
|
|
(* *)
|
|
(* OCaml *)
|
|
(* *)
|
|
(* Pierre Chambart, OCamlPro *)
|
|
(* Mark Shinwell and Leo White, Jane Street Europe *)
|
|
(* *)
|
|
(* Copyright 2013--2016 OCamlPro SAS *)
|
|
(* Copyright 2014--2016 Jane Street Group LLC *)
|
|
(* *)
|
|
(* All rights reserved. This file is distributed under the terms of *)
|
|
(* the GNU Lesser General Public License version 2.1, with the *)
|
|
(* special exception on linking described in the file ../LICENSE. *)
|
|
(* *)
|
|
(**************************************************************************)
|
|
|
|
[@@@ocaml.warning "+a-4-9-30-40-41-42"]
|
|
|
|
type allocation_point =
|
|
| Symbol of Symbol.t
|
|
| Variable of Variable.t
|
|
|
|
type allocated_const =
|
|
| Normal of Allocated_const.t
|
|
| Array of Lambda.array_kind * Asttypes.mutable_flag * Variable.t list
|
|
| Duplicate_array of Lambda.array_kind * Asttypes.mutable_flag * Variable.t
|
|
|
|
type constant_defining_value =
|
|
| Allocated_const of allocated_const
|
|
| Block of Tag.t * Variable.t list
|
|
| Set_of_closures of Flambda.set_of_closures
|
|
| Project_closure of Flambda.project_closure
|
|
| Move_within_set_of_closures of Flambda.move_within_set_of_closures
|
|
| Project_var of Flambda.project_var
|
|
| Field of Variable.t * int
|
|
| Symbol_field of Symbol.t * int
|
|
| Const of Flambda.const
|
|
| Symbol of Symbol.t
|
|
| Variable of Variable.t
|
|
|
|
type initialize_symbol_field = Variable.t option
|
|
|
|
type definitions = {
|
|
variable : constant_defining_value Variable.Tbl.t;
|
|
initialize_symbol : initialize_symbol_field list Symbol.Tbl.t;
|
|
symbol : Flambda.constant_defining_value Symbol.Tbl.t;
|
|
}
|
|
|
|
let print_constant_defining_value ppf = function
|
|
| Allocated_const (Normal const) -> Allocated_const.print ppf const
|
|
| Allocated_const (Array (_, _, vars)) ->
|
|
Format.fprintf ppf "[| %a |]"
|
|
(Format.pp_print_list Variable.print) vars
|
|
| Allocated_const (Duplicate_array (_, _, var)) ->
|
|
Format.fprintf ppf "dup_array(%a)" Variable.print var
|
|
| Block (tag, vars) ->
|
|
Format.fprintf ppf "[|%a: %a|]"
|
|
Tag.print tag
|
|
(Format.pp_print_list Variable.print) vars
|
|
| Set_of_closures set -> Flambda.print_set_of_closures ppf set
|
|
| Project_closure project -> Flambda.print_project_closure ppf project
|
|
| Move_within_set_of_closures move ->
|
|
Flambda.print_move_within_set_of_closures ppf move
|
|
| Project_var project -> Flambda.print_project_var ppf project
|
|
| Field (var, field) -> Format.fprintf ppf "%a.(%d)" Variable.print var field
|
|
| Symbol_field (sym, field) ->
|
|
Format.fprintf ppf "%a.(%d)" Symbol.print sym field
|
|
| Const const -> Flambda.print_const ppf const
|
|
| Symbol symbol -> Symbol.print ppf symbol
|
|
| Variable var -> Variable.print ppf var
|
|
|
|
let rec resolve_definition
|
|
(definitions: definitions)
|
|
(var: Variable.t)
|
|
(def: constant_defining_value)
|
|
~the_dead_constant : allocation_point =
|
|
match def with
|
|
| Allocated_const _
|
|
| Block _
|
|
| Set_of_closures _
|
|
| Project_closure _
|
|
| Const _
|
|
| Move_within_set_of_closures _ ->
|
|
Variable var
|
|
| Project_var {var} ->
|
|
fetch_variable definitions (Var_within_closure.unwrap var)
|
|
~the_dead_constant
|
|
| Variable v ->
|
|
fetch_variable definitions v
|
|
~the_dead_constant
|
|
| Symbol sym -> Symbol sym
|
|
| Field (v, n) ->
|
|
begin match fetch_variable definitions v ~the_dead_constant with
|
|
| Symbol s ->
|
|
fetch_symbol_field definitions s n ~the_dead_constant
|
|
| Variable v ->
|
|
fetch_variable_field definitions v n ~the_dead_constant
|
|
end
|
|
| Symbol_field (symbol, field) ->
|
|
fetch_symbol_field definitions symbol field ~the_dead_constant
|
|
|
|
and fetch_variable
|
|
(definitions: definitions)
|
|
(var: Variable.t)
|
|
~the_dead_constant : allocation_point =
|
|
match Variable.Tbl.find definitions.variable var with
|
|
| exception Not_found -> Variable var
|
|
| def -> resolve_definition definitions var def ~the_dead_constant
|
|
|
|
and fetch_variable_field
|
|
(definitions: definitions)
|
|
(var: Variable.t)
|
|
(field: int)
|
|
~the_dead_constant : allocation_point =
|
|
match Variable.Tbl.find definitions.variable var with
|
|
| Block (_, fields) ->
|
|
begin match List.nth fields field with
|
|
| exception Not_found -> Symbol the_dead_constant
|
|
| v -> fetch_variable definitions v ~the_dead_constant
|
|
end
|
|
| exception Not_found ->
|
|
Misc.fatal_errorf "No definition for field access to %a" Variable.print var
|
|
| Symbol _ | Variable _ | Project_var _ | Field _ | Symbol_field _ ->
|
|
(* Must have been resolved *)
|
|
assert false
|
|
| Const _ | Allocated_const _
|
|
| Set_of_closures _ | Project_closure _ | Move_within_set_of_closures _ ->
|
|
Symbol the_dead_constant
|
|
|
|
and fetch_symbol_field
|
|
(definitions: definitions)
|
|
(sym: Symbol.t)
|
|
(field: int)
|
|
~the_dead_constant : allocation_point =
|
|
match Symbol.Tbl.find definitions.symbol sym with
|
|
| Block (_, fields) ->
|
|
begin match List.nth fields field with
|
|
| exception Not_found -> Symbol the_dead_constant
|
|
| Symbol s -> Symbol s
|
|
| Const _ -> Symbol sym
|
|
end
|
|
| exception Not_found ->
|
|
begin match Symbol.Tbl.find definitions.initialize_symbol sym with
|
|
| fields ->
|
|
begin match List.nth fields field with
|
|
| None ->
|
|
Misc.fatal_errorf "constant field access to an inconstant %a"
|
|
Symbol.print sym
|
|
| Some v ->
|
|
fetch_variable definitions v ~the_dead_constant
|
|
end
|
|
| exception Not_found ->
|
|
Misc.fatal_errorf "No definition for field access to %a"
|
|
Symbol.print sym
|
|
end
|
|
| Allocated_const _ | Set_of_closures _ | Project_closure _ ->
|
|
Symbol the_dead_constant
|
|
|
|
let run variable initialize_symbol symbol ~the_dead_constant =
|
|
let definitions = { variable; initialize_symbol; symbol; } in
|
|
Variable.Tbl.fold (fun var definition result ->
|
|
let definition =
|
|
resolve_definition definitions var definition ~the_dead_constant
|
|
in
|
|
Variable.Map.add var definition result)
|
|
definitions.variable
|
|
Variable.Map.empty
|