1 (***********************************************************************)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 1996 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
11 (***********************************************************************)
15 (* Compilation environments for compilation units *)
22 Not_a_unit_info
of string
23 | Corrupted_unit_info
of string
24 | Illegal_renaming
of string * string
26 exception Error
of error
28 (* Each .o file has a matching .cmx file that provides the following infos
29 on the compilation unit:
30 - list of other units imported, with CRCs of their .cmx files
31 - approximation of the structure implemented
32 (includes descriptions of known functions: arity and direct entry
34 - list of currying functions and application functions needed
35 The .cmx file contains these infos (as an externed record) plus a CRC
39 { mutable ui_name
: string; (* Name of unit implemented *)
40 mutable ui_symbol
: string; (* Prefix for symbols *)
41 mutable ui_defines
: string list
; (* Unit and sub-units implemented *)
42 mutable ui_imports_cmi
: (string * Digest.t
) list
; (* Interfaces imported *)
43 mutable ui_imports_cmx
: (string * Digest.t
) list
; (* Infos imported *)
44 mutable ui_approx
: value_approximation
; (* Approx of the structure *)
45 mutable ui_curry_fun
: int list
; (* Currying functions needed *)
46 mutable ui_apply_fun
: int list
; (* Apply functions needed *)
47 mutable ui_send_fun
: int list
; (* Send functions needed *)
48 mutable ui_force_link
: bool } (* Always linked *)
50 (* Each .a library has a matching .cmxa file that provides the following
51 infos on the library: *)
54 { lib_units
: (unit_infos
* Digest.t
) list
; (* List of unit infos w/ CRCs *)
55 lib_ccobjs
: string list
; (* C object files needed *)
56 lib_ccopts
: string list
} (* Extra opts to C compiler *)
58 let global_infos_table =
59 (Hashtbl.create
17 : (string, unit_infos
option) Hashtbl.t
)
67 ui_approx
= Value_unknown
;
71 ui_force_link
= false }
73 let symbolname_for_pack pack name
=
77 let b = Buffer.create
64 in
78 for i
= 0 to String.length p
- 1 do
80 | '
.'
-> Buffer.add_string
b "__"
81 | c
-> Buffer.add_char
b c
83 Buffer.add_string
b "__";
84 Buffer.add_string
b name
;
87 let reset ?packname name
=
88 Hashtbl.clear
global_infos_table;
89 let symbol = symbolname_for_pack packname name
in
90 current_unit.ui_name
<- name
;
91 current_unit.ui_symbol
<- symbol;
92 current_unit.ui_defines
<- [symbol];
93 current_unit.ui_imports_cmi
<- [];
94 current_unit.ui_imports_cmx
<- [];
95 current_unit.ui_curry_fun
<- [];
96 current_unit.ui_apply_fun
<- [];
97 current_unit.ui_send_fun
<- [];
98 current_unit.ui_force_link
<- false
100 let current_unit_infos () =
103 let current_unit_name () =
106 let make_symbol ?
(unitname
= current_unit.ui_symbol
) idopt
=
107 let prefix = "caml" ^ unitname
in
110 | Some id
-> prefix ^
"__" ^ id
112 let read_unit_info filename
=
113 let ic = open_in_bin filename
in
115 let buffer = String.create
(String.length cmx_magic_number
) in
116 really_input
ic buffer 0 (String.length cmx_magic_number
);
117 if buffer <> cmx_magic_number
then begin
119 raise
(Error
(Not_a_unit_info filename
))
121 let ui = (input_value
ic : unit_infos
) in
122 let crc = Digest.input
ic in
125 with End_of_file
| Failure _
->
127 raise
(Error
(Corrupted_unit_info
(filename
)))
129 (* Read and cache info on global identifiers *)
131 let cmx_not_found_crc =
132 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
134 let get_global_info global_ident
=
135 let modname = Ident.name global_ident
in
136 if modname = current_unit.ui_name
then
140 Hashtbl.find
global_infos_table modname
145 find_in_path_uncap
!load_path
(modname ^
".cmx") in
146 let (ui, crc) = read_unit_info filename in
147 if ui.ui_name
<> modname then
148 raise
(Error
(Illegal_renaming
(ui.ui_name
, filename)));
151 (None
, cmx_not_found_crc) in
152 current_unit.ui_imports_cmx
<-
153 (modname, crc) :: current_unit.ui_imports_cmx
;
154 Hashtbl.add
global_infos_table modname infos
;
158 let cache_unit_info ui =
159 Hashtbl.add
global_infos_table ui.ui_name
(Some
ui)
161 (* Return the approximation of a global identifier *)
163 let global_approx id
=
164 match get_global_info id
with
165 | None
-> Value_unknown
166 | Some
ui -> ui.ui_approx
168 (* Return the symbol used to refer to a global identifier *)
170 let symbol_for_global id
=
171 if Ident.is_predef_exn id
then
172 "caml_exn_" ^
Ident.name id
174 match get_global_info id
with
175 | None
-> make_symbol ~unitname
:(Ident.name id
) None
176 | Some
ui -> make_symbol ~unitname
:ui.ui_symbol None
179 (* Register the approximation of the module being compiled *)
181 let set_global_approx approx
=
182 current_unit.ui_approx
<- approx
184 (* Record that a currying function or application function is needed *)
186 let need_curry_fun n
=
187 if not
(List.mem n
current_unit.ui_curry_fun
) then
188 current_unit.ui_curry_fun
<- n
:: current_unit.ui_curry_fun
190 let need_apply_fun n
=
191 if not
(List.mem n
current_unit.ui_apply_fun
) then
192 current_unit.ui_apply_fun
<- n
:: current_unit.ui_apply_fun
194 let need_send_fun n
=
195 if not
(List.mem n
current_unit.ui_send_fun
) then
196 current_unit.ui_send_fun
<- n
:: current_unit.ui_send_fun
198 (* Write the description of the current unit *)
200 let write_unit_info info
filename =
201 let oc = open_out_bin
filename in
202 output_string
oc cmx_magic_number
;
203 output_value
oc info
;
205 let crc = Digest.file
filename in
206 Digest.output
oc crc;
209 let save_unit_info filename =
210 current_unit.ui_imports_cmi
<- Env.imported_units
();
211 write_unit_info current_unit filename
217 let report_error ppf
= function
218 | Not_a_unit_info
filename ->
219 fprintf ppf
"%s@ is not a compilation unit description." filename
220 | Corrupted_unit_info
filename ->
221 fprintf ppf
"Corrupted compilation unit description@ %s" filename
222 | Illegal_renaming
(modname, filename) ->
223 fprintf ppf
"%s@ contains the description for unit@ %s" filename modname