File: export_info_for_pack.ml

package info (click to toggle)
ocaml 5.3.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 43,124 kB
  • sloc: ml: 355,439; ansic: 51,636; sh: 25,098; asm: 5,413; makefile: 3,673; python: 919; javascript: 273; awk: 253; perl: 59; fortran: 21; cs: 9
file content (218 lines) | stat: -rw-r--r-- 8,717 bytes parent folder | download | duplicates (2)
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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
(**************************************************************************)
(*                                                                        *)
(*                                 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"]

module A = Simple_value_approx

let rename_id_state = Export_id.Tbl.create 100
let rename_set_of_closures_id_state = Set_of_closures_id.Tbl.create 10
let imported_function_declarations_table =
  (Set_of_closures_id.Tbl.create 10
   : A.function_declarations Set_of_closures_id.Tbl.t)

(* Rename export identifiers' compilation units to denote that they now
   live within a pack. *)
let import_eid_for_pack units pack id =
  try Export_id.Tbl.find rename_id_state id
  with Not_found ->
    let unit_id = Export_id.get_compilation_unit id in
    let id' =
      if Compilation_unit.Set.mem unit_id units
      then Export_id.create ?name:(Export_id.name id) pack
      else id
    in
    Export_id.Tbl.add rename_id_state id id';
    id'

(* Similar to [import_eid_for_pack], but for symbols. *)
let import_symbol_for_pack units pack symbol =
  let compilation_unit = Symbol.compilation_unit symbol in
  if Compilation_unit.Set.mem compilation_unit units
  then Symbol.import_for_pack ~pack symbol
  else symbol

let import_approx_for_pack units pack (approx : Export_info.approx)
      : Export_info.approx =
  match approx with
  | Value_symbol sym -> Value_symbol (import_symbol_for_pack units pack sym)
  | Value_id eid -> Value_id (import_eid_for_pack units pack eid)
  | Value_unknown -> Value_unknown

let import_set_of_closures_id_for_pack units pack
    (set_of_closures_id : Set_of_closures_id.t)
      : Set_of_closures_id.t =
  let compilation_unit =
    Set_of_closures_id.get_compilation_unit set_of_closures_id
  in
  if Compilation_unit.Set.mem compilation_unit units then
    Set_of_closures_id.Tbl.memoize
      rename_set_of_closures_id_state
      (fun _ ->
         Set_of_closures_id.create
           ?name:(Set_of_closures_id.name set_of_closures_id)
           pack)
      set_of_closures_id
  else set_of_closures_id

let import_set_of_closures_origin_for_pack units pack
    (set_of_closures_origin : Set_of_closures_origin.t)
    : Set_of_closures_origin.t =
  Set_of_closures_origin.rename
    (import_set_of_closures_id_for_pack units pack)
    set_of_closures_origin

let import_set_of_closures units pack
      (set_of_closures : Export_info.value_set_of_closures)
      : Export_info.value_set_of_closures =
  { set_of_closures_id =
      import_set_of_closures_id_for_pack units pack
        set_of_closures.set_of_closures_id;
    bound_vars =
      Var_within_closure.Map.map (import_approx_for_pack units pack)
        set_of_closures.bound_vars;
    free_vars = set_of_closures.free_vars;
    results =
      Closure_id.Map.map (import_approx_for_pack units pack)
        set_of_closures.results;
    aliased_symbol =
      Option.map
        (import_symbol_for_pack units pack)
        set_of_closures.aliased_symbol;
  }

let import_descr_for_pack units pack (descr : Export_info.descr)
      : Export_info.descr =
  match descr with
  | Value_int _
  | Value_char _
  | Value_string _
  | Value_float _
  | Value_float_array _
  | Export_info.Value_boxed_int _
  | Value_mutable_block _ as desc -> desc
  | Value_block (tag, fields) ->
    Value_block (tag, Array.map (import_approx_for_pack units pack) fields)
  | Value_closure { closure_id; set_of_closures } ->
    Value_closure {
      closure_id;
      set_of_closures = import_set_of_closures units pack set_of_closures;
    }
  | Value_set_of_closures set_of_closures ->
    Value_set_of_closures (import_set_of_closures units pack set_of_closures)
  | Value_unknown_descr -> Value_unknown_descr

let rec import_code_for_pack units pack expr =
  Flambda_iterators.map_named (function
      | Symbol sym -> Symbol (import_symbol_for_pack units pack sym)
      | Read_symbol_field (sym, field) ->
        Read_symbol_field (import_symbol_for_pack units pack sym, field)
      | Set_of_closures set_of_closures ->
        let set_of_closures =
          Flambda.create_set_of_closures
            ~free_vars:set_of_closures.free_vars
            ~specialised_args:set_of_closures.specialised_args
            ~direct_call_surrogates:set_of_closures.direct_call_surrogates
            ~function_decls:
              (import_function_declarations_for_pack_aux units pack
                 set_of_closures.function_decls)
        in
        Set_of_closures set_of_closures
      | e -> e)
    expr

and import_function_declarations_for_pack_aux units pack
      (function_decls : Flambda.function_declarations) =
  Flambda.import_function_declarations_for_pack
    function_decls
    (import_set_of_closures_id_for_pack units pack)
    (import_set_of_closures_origin_for_pack units pack)

let import_function_declarations_for_pack_aux units pack
      (function_decls : A.function_declarations) : A.function_declarations =
  let funs =
    Variable.Map.map
      (fun (function_decl : A.function_declaration) ->
         A.update_function_declaration_body function_decl
           (fun body -> import_code_for_pack units pack body))
      function_decls.funs
  in
  A.import_function_declarations_for_pack
    (A.update_function_declarations function_decls ~funs)
    (import_set_of_closures_id_for_pack units pack)
    (import_set_of_closures_origin_for_pack units pack)

let import_function_declarations_approx_for_pack units pack
      (function_decls: A.function_declarations) =
  let original_set_of_closures_id = function_decls.set_of_closures_id in
  try
    Set_of_closures_id.Tbl.find imported_function_declarations_table
      original_set_of_closures_id
  with Not_found ->
    let function_decls =
      import_function_declarations_for_pack_aux units pack function_decls
    in
    Set_of_closures_id.Tbl.add
      imported_function_declarations_table
      original_set_of_closures_id
      function_decls;
    function_decls

let import_eidmap_for_pack units pack f map =
  Export_info.nest_eid_map
    (Compilation_unit.Map.fold
      (fun _ map acc -> Export_id.Map.disjoint_union map acc)
      (Compilation_unit.Map.map (fun map ->
          Export_id.Map.map_keys (import_eid_for_pack units pack)
            (Export_id.Map.map f map))
        map)
      Export_id.Map.empty)

let import_for_pack ~pack_units ~pack (exp : Export_info.t) =
  let import_sym = import_symbol_for_pack pack_units pack in
  let import_descr = import_descr_for_pack pack_units pack in
  let import_eid = import_eid_for_pack pack_units pack in
  let import_eidmap f map = import_eidmap_for_pack pack_units pack f map in
  let import_set_of_closures_id =
    import_set_of_closures_id_for_pack pack_units pack
  in
  let import_function_declarations =
    import_function_declarations_approx_for_pack pack_units pack
  in
  let sets_of_closures =
    Set_of_closures_id.Map.map_keys import_set_of_closures_id
      (Set_of_closures_id.Map.map
         import_function_declarations
         exp.sets_of_closures)
  in
  Export_info.create ~sets_of_closures
    ~offset_fun:exp.offset_fun
    ~offset_fv:exp.offset_fv
    ~values:(import_eidmap import_descr exp.values)
    ~symbol_id:(Symbol.Map.map_keys import_sym
      (Symbol.Map.map import_eid exp.symbol_id))
    ~constant_closures:exp.constant_closures
    ~invariant_params:
      (Set_of_closures_id.Map.map_keys import_set_of_closures_id
         exp.invariant_params)
    ~recursive:
      (Set_of_closures_id.Map.map_keys import_set_of_closures_id
         exp.recursive)

let clear_import_state () =
  Set_of_closures_id.Tbl.clear imported_function_declarations_table;
  Set_of_closures_id.Tbl.clear rename_set_of_closures_id_state;
  Export_id.Tbl.clear rename_id_state