summaryrefslogtreecommitdiff
path: root/middle_end/flambda/export_info.mli
blob: f93698be4fdf030dc160a5d5407d65f17485e25b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
(**************************************************************************)
(*                                                                        *)
(*                                 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"]

(** Exported information (that is to say, information written into a .cmx
    file) about a compilation unit. *)

module A = Simple_value_approx

type value_string_contents =
  | Contents of string
  | Unknown_or_mutable

type value_string = {
  contents : value_string_contents;
  size : int;
}

type value_float_array_contents =
  | Contents of float option array
  | Unknown_or_mutable

type value_float_array = {
  contents : value_float_array_contents;
  size : int;
}

type descr =
  | Value_block of Tag.t * approx array
  | Value_mutable_block of Tag.t * int
  | Value_int of int
  | Value_char of char
  | Value_constptr of int
  | Value_float of float
  | Value_float_array of value_float_array
  | Value_boxed_int : 'a A.boxed_int * 'a -> descr
  | Value_string of value_string
  | Value_closure of value_closure
  | Value_set_of_closures of value_set_of_closures
  | Value_unknown_descr

and value_closure = {
  closure_id : Closure_id.t;
  set_of_closures : value_set_of_closures;
}

and value_set_of_closures = {
  set_of_closures_id : Set_of_closures_id.t;
  bound_vars : approx Var_within_closure.Map.t;
  free_vars : Flambda.specialised_to Variable.Map.t;
  results : approx Closure_id.Map.t;
  aliased_symbol : Symbol.t option;
}

(* CR-soon mshinwell: Fix the export information so we can correctly
   propagate "unresolved due to..." in the manner of [Simple_value_approx].
   Unfortunately this seems to be complicated by the fact that, during
   [Import_approx], resolution can fail not only due to missing symbols but
   also due to missing export IDs.  The argument type of
   [Simple_value_approx.t] may need updating to reflect this (make the
   symbol optional?  It's only for debugging anyway.) *)
and approx =
  | Value_unknown
  | Value_id of Export_id.t
  | Value_symbol of Symbol.t

(** A structure that describes what a single compilation unit exports. *)
type t = private {
  sets_of_closures : A.function_declarations Set_of_closures_id.Map.t;
  (** Code of exported functions indexed by set of closures IDs. *)
  values : descr Export_id.Map.t Compilation_unit.Map.t;
  (** Structure of exported values. *)
  symbol_id : Export_id.t Symbol.Map.t;
  (** Associates symbols and values. *)
  offset_fun : int Closure_id.Map.t;
  (** Positions of function pointers in their closures. *)
  offset_fv : int Var_within_closure.Map.t;
  (** Positions of value pointers in their closures. *)
  constant_closures : Closure_id.Set.t;
  (* CR-soon mshinwell for pchambart: Add comment *)
  invariant_params : Variable.Set.t Variable.Map.t Set_of_closures_id.Map.t;
  (* Function parameters known to be invariant (see [Invariant_params])
     indexed by set of closures ID. *)
  recursive : Variable.Set.t Set_of_closures_id.Map.t;
}

type transient = private {
  sets_of_closures : A.function_declarations Set_of_closures_id.Map.t;
  values : descr Export_id.Map.t Compilation_unit.Map.t;
  symbol_id : Export_id.t Symbol.Map.t;
  invariant_params : Variable.Set.t Variable.Map.t Set_of_closures_id.Map.t;
  recursive : Variable.Set.t Set_of_closures_id.Map.t;
  relevant_local_closure_ids : Closure_id.Set.t;
  relevant_imported_closure_ids : Closure_id.Set.t;
  relevant_local_vars_within_closure  : Var_within_closure.Set.t;
  relevant_imported_vars_within_closure : Var_within_closure.Set.t;
}

(** Export information for a compilation unit that exports nothing. *)
val empty : t

val opaque_transient
  : compilation_unit:Compilation_unit.t
  -> root_symbol:Symbol.t
  -> transient

(** Create a new export information structure. *)
val create
   : sets_of_closures:(A.function_declarations Set_of_closures_id.Map.t)
  -> values:descr Export_id.Map.t Compilation_unit.Map.t
  -> symbol_id:Export_id.t Symbol.Map.t
  -> offset_fun:int Closure_id.Map.t
  -> offset_fv:int Var_within_closure.Map.t
  -> constant_closures:Closure_id.Set.t
  -> invariant_params:Variable.Set.t Variable.Map.t Set_of_closures_id.Map.t
  -> recursive:Variable.Set.t Set_of_closures_id.Map.t
  -> t

val create_transient
   : sets_of_closures:(A.function_declarations Set_of_closures_id.Map.t)
  -> values:descr Export_id.Map.t Compilation_unit.Map.t
  -> symbol_id:Export_id.t Symbol.Map.t
  -> invariant_params:Variable.Set.t Variable.Map.t Set_of_closures_id.Map.t
  -> recursive:Variable.Set.t Set_of_closures_id.Map.t
  -> relevant_local_closure_ids: Closure_id.Set.t
  -> relevant_imported_closure_ids : Closure_id.Set.t
  -> relevant_local_vars_within_closure : Var_within_closure.Set.t
  -> relevant_imported_vars_within_closure : Var_within_closure.Set.t
  -> transient

(* CR-someday pchambart: Should we separate [t] in 2 types: one created by the
   current [create] function, returned by [Build_export_info]. And
   another built using t and offset_informations returned by
   [flambda_to_clambda] ?
   mshinwell: I think we should, but after we've done the first release.
*)
(** Record information about the layout of closures and which sets of
    closures are constant.  These are all worked out during the
    [Flambda_to_clambda] pass. *)
val t_of_transient
   : transient
  -> program: Flambda.program
  -> local_offset_fun:int Closure_id.Map.t
  -> local_offset_fv:int Var_within_closure.Map.t
  -> imported_offset_fun:int Closure_id.Map.t
  -> imported_offset_fv:int Var_within_closure.Map.t
  -> constant_closures:Closure_id.Set.t
  -> t

(** Union of export information.  Verifies that there are no identifier
    clashes. *)
val merge : t -> t -> t

(** Look up the description of an exported value given its export ID. *)
val find_description
   : t
  -> Export_id.t
  -> descr

(** Partition a mapping from export IDs by compilation unit. *)
val nest_eid_map
   : 'a Export_id.Map.t
  -> 'a Export_id.Map.t Compilation_unit.Map.t

(**/**)
(* Debug printing functions. *)
val print_approx_components
  : Format.formatter
  -> symbol_id: Export_id.t Symbol.Map.t
  -> values: descr Export_id.Map.t Compilation_unit.Map.t
  -> Symbol.t list
  -> unit
val print_approx : Format.formatter -> t * Symbol.t list -> unit
val print_functions : Format.formatter -> t -> unit
val print_offsets : Format.formatter -> t -> unit
val print_all : Format.formatter -> t * Symbol.t list -> unit

(** Prints approx and descr as it is, without recursively looking up
    [Export_id.t] *)
val print_raw_approx : Format.formatter -> approx -> unit
val print_raw_descr  : Format.formatter -> descr -> unit