| Attached Files | patch_pack [^] (19,359 bytes) 2006-08-09 15:41 [Show Content] [Hide Content]diff -ur ocaml/asmcomp/asmpackager.ml ocaml_bug2/asmcomp/asmpackager.ml
--- ocaml/asmcomp/asmpackager.ml 2006-01-04 17:55:49.000000000 +0100
+++ ocaml_bug2/asmcomp/asmpackager.ml 2006-08-09 14:02:55.000000000 +0200
@@ -78,7 +78,7 @@
(* Make the .o file for the package *)
-let make_package_object ppf members targetobj targetname coercion =
+let make_package_object ppf members targetobj coercion =
let objtemp = Filename.temp_file "camlpackage" Config.ext_obj in
let components =
List.map
@@ -87,10 +87,13 @@
| PM_intf -> None
| PM_impl _ -> Some(Ident.create_persistent m.pm_name))
members in
+ let (_,lam) as unit = Translmod.transl_store_package
+ components (Compilenv.current_unit_glob ()) coercion in
+ if !Clflags.dump_lambda then
+ Format.fprintf ppf "%a@." Printlambda.lambda lam;
Asmgen.compile_implementation
(chop_extension_if_any objtemp) ppf
- (Translmod.transl_store_package
- components (Ident.create_persistent targetname) coercion);
+ unit;
let objfiles =
List.map
(fun m -> chop_extension_if_any m.pm_file ^ Config.ext_obj)
@@ -156,7 +159,7 @@
| Some p -> p ^ "." ^ targetname in
let members = map_left_right (read_member_info pack_path) files in
check_units members;
- make_package_object ppf members targetobj targetname coercion;
+ make_package_object ppf members targetobj coercion;
build_package_cmx members targetcmx
(* The entry point *)
diff -ur ocaml/asmcomp/closure.ml ocaml_bug2/asmcomp/closure.ml
--- ocaml/asmcomp/closure.ml 2006-01-04 17:55:49.000000000 +0100
+++ ocaml_bug2/asmcomp/closure.ml 2006-08-09 13:23:53.000000000 +0200
@@ -36,14 +36,7 @@
Tbl.add id (Uprim(Pfield pos, [Uvar env_param]))
(build_closure_env env_param (pos+1) rem)
-(* Auxiliary for accessing globals. We change the name of the global
- to the name of the corresponding asm symbol. This is done here
- and no longer in Cmmgen so that approximations stored in .cmx files
- contain the right names if the -for-pack option is active. *)
-
-let getglobal id =
- Uprim(Pgetglobal (Ident.create_persistent (Compilenv.symbol_for_global id)),
- [])
+let getglobal id = Uprim(Pgetglobal id, [])
(* Check if a variable occurs in a [clambda] term. *)
diff -ur ocaml/asmcomp/compilenv.ml ocaml_bug2/asmcomp/compilenv.ml
--- ocaml/asmcomp/compilenv.ml 2005-08-01 17:51:09.000000000 +0200
+++ ocaml_bug2/asmcomp/compilenv.ml 2006-08-09 15:21:47.000000000 +0200
@@ -58,6 +58,9 @@
let global_infos_table =
(Hashtbl.create 17 : (string, unit_infos option) Hashtbl.t)
+let global_infos_table_of_sym =
+ (Hashtbl.create 17 : (string, unit_infos option) Hashtbl.t)
+
let current_unit =
{ ui_name = "";
ui_symbol = "";
@@ -86,6 +89,7 @@
let reset ?packname name =
Hashtbl.clear global_infos_table;
+ Hashtbl.clear global_infos_table_of_sym;
let symbol = symbolname_for_pack packname name in
current_unit.ui_name <- name;
current_unit.ui_symbol <- symbol;
@@ -109,6 +113,9 @@
| None -> prefix
| Some id -> prefix ^ "__" ^ id
+let current_unit_glob () =
+ Lambda.getglobal_sym (Ident.create_persistent (make_symbol None))
+
let read_unit_info filename =
let ic = open_in_bin filename in
try
@@ -121,6 +128,20 @@
let ui = (input_value ic : unit_infos) in
let crc = Digest.input ic in
close_in ic;
+
+ Hashtbl.add global_infos_table ui.ui_name (Some ui);
+ (* This function is called by -pack on all the given .cmx files.
+ Recording the information here ensures
+ that the resolution (global ident -> symbol) will work for this
+ unit (this is needed to compile the lambda code generated
+ by -pack). *)
+
+ Hashtbl.add global_infos_table_of_sym
+ (make_symbol ~unitname:ui.ui_symbol None) (Some ui);
+ (* Recording the information in global_infos_table_of_sym makes
+ it possible to retrieve the approximation for this unit from its global
+ symbol. *)
+
(ui, crc)
with End_of_file | Failure _ ->
close_in ic;
@@ -133,9 +154,7 @@
let get_global_info global_ident =
let modname = Ident.name global_ident in
- if modname = current_unit.ui_name then
- Some current_unit
- else begin
+ begin
try
Hashtbl.find global_infos_table modname
with Not_found ->
@@ -148,17 +167,40 @@
raise(Error(Illegal_renaming(ui.ui_name, filename)));
(Some ui, crc)
with Not_found ->
+ Hashtbl.add global_infos_table modname None;
+ Format.eprintf "Warning %a@."
+ (fun ppf w -> ignore (Warnings.print ppf w))
+ (Warnings.Cmx_not_found modname);
(None, cmx_not_found_crc) in
current_unit.ui_imports_cmx <-
(modname, crc) :: current_unit.ui_imports_cmx;
- Hashtbl.add global_infos_table modname infos;
infos
end
+(* Get the unit info corresponding to a global symbol.
+ We assume that the corresponding .cmx file has been loaded
+ previously by a call to read_unit_info, either
+ explicitly (during -pack) or through get_global_info
+ (during the resolution global name -> global symbol).
+ Special treatment for the current unit (whose .cmx does not exist
+ yet) and for exception idents. *)
+
+let get_global_info_sym id =
+ let sym = Ident.name id in
+ if sym = make_symbol None
+ then Some current_unit
+ else
+ if (String.length sym > 9 && String.sub sym 0 9 = "caml_exn_") then None
+ else
+ try Hashtbl.find global_infos_table_of_sym sym
+ with Not_found ->
+ Hashtbl.add global_infos_table_of_sym sym None;
+ None
+
(* Return the approximation of a global identifier *)
let global_approx id =
- match get_global_info id with
+ match get_global_info_sym id with
| None -> Value_unknown
| Some ui -> ui.ui_approx
@@ -219,3 +261,7 @@
| Illegal_renaming(modname, filename) ->
fprintf ppf "%s@ contains the description for unit@ %s" filename modname
+
+let () =
+ Lambda.transl_global :=
+ (fun id -> Ident.create_persistent (symbol_for_global id))
diff -ur ocaml/asmcomp/compilenv.mli ocaml_bug2/asmcomp/compilenv.mli
--- ocaml/asmcomp/compilenv.mli 2005-08-01 17:51:09.000000000 +0200
+++ ocaml_bug2/asmcomp/compilenv.mli 2006-08-09 15:37:40.000000000 +0200
@@ -53,8 +53,8 @@
val current_unit_infos: unit -> unit_infos
(* Return the infos for the unit being compiled *)
-val current_unit_name: unit -> string
- (* Return the name of the unit being compiled *)
+val current_unit_glob: unit -> Lambda.lambda
+ (* Return the code to access the global for the current unit *)
val make_symbol: ?unitname:string -> string option -> string
(* [make_symbol ~unitname:u None] returns the asm symbol that
@@ -63,11 +63,8 @@
corresponds to symbol [id] in the compilation unit [u]
(or the current unit). *)
-val symbol_for_global: Ident.t -> string
- (* Return the asm symbol that refers to the given global identifier *)
-
val global_approx: Ident.t -> Clambda.value_approximation
- (* Return the approximation for the given global identifier *)
+ (* Return the approximation for the given global asm symbol *)
val set_global_approx: Clambda.value_approximation -> unit
(* Record the approximation of the unit being compiled *)
diff -ur ocaml/bug/b.ml ocaml_bug2/bug/b.ml
--- ocaml/bug/b.ml 2006-08-09 14:34:59.000000000 +0200
+++ ocaml_bug2/bug/b.ml 2006-08-08 17:11:11.000000000 +0200
@@ -1 +1 @@
-incr A.x
+let () = Printf.printf "%i\n" (A.A.f 2)
diff -ur ocaml/bytecomp/lambda.ml ocaml_bug2/bytecomp/lambda.ml
--- ocaml/bytecomp/lambda.ml 2005-08-25 17:35:16.000000000 +0200
+++ ocaml_bug2/bytecomp/lambda.ml 2006-08-09 13:03:25.000000000 +0200
@@ -344,11 +344,19 @@
Levent (patch_guarded patch lam, ev)
| _ -> fatal_error "Lambda.patch_guarded"
+
+(* Translate globals *)
+
+let transl_global = ref (fun id -> id)
+let getglobal_sym sym = Lprim(Pgetglobal sym, [])
+let getglobal id = getglobal_sym (!transl_global id)
+let setglobal id v = Lprim(Psetglobal (!transl_global id), [v])
+
(* Translate an access path *)
let rec transl_path = function
Pident id ->
- if Ident.global id then Lprim(Pgetglobal id, []) else Lvar id
+ if Ident.global id then getglobal id else Lvar id
| Pdot(p, s, pos) ->
Lprim(Pfield pos, [transl_path p])
| Papply(p1, p2) ->
diff -ur ocaml/bytecomp/lambda.mli ocaml_bug2/bytecomp/lambda.mli
--- ocaml/bytecomp/lambda.mli 2005-08-25 17:35:16.000000000 +0200
+++ ocaml_bug2/bytecomp/lambda.mli 2006-08-09 13:03:49.000000000 +0200
@@ -175,6 +175,18 @@
val is_guarded: lambda -> bool
val patch_guarded : lambda -> lambda -> lambda
+val transl_global: (Ident.t -> Ident.t) ref
+ (* Translation from global idents (as produced by the type checker)
+ into global symbols. By default and for bytecode, this is the identity.
+ ocamlopt changes it to look for the symbol name in the corresponding .cmx
+ file. *)
+val setglobal: Ident.t -> lambda -> lambda
+ (* The argument is a global ident. *)
+val getglobal: Ident.t -> lambda
+ (* The argument is a global ident. *)
+val getglobal_sym: Ident.t -> lambda
+ (* The argument is a global symbol. *)
+
val iter: (lambda -> unit) -> lambda -> unit
module IdentSet: Set.S with type elt = Ident.t
val free_variables: lambda -> IdentSet.t
diff -ur ocaml/bytecomp/translmod.ml ocaml_bug2/bytecomp/translmod.ml
--- ocaml/bytecomp/translmod.ml 2006-04-05 04:28:12.000000000 +0200
+++ ocaml_bug2/bytecomp/translmod.ml 2006-08-09 13:43:36.000000000 +0200
@@ -359,7 +359,8 @@
"map" is a table from defined idents to (pos in global block, coercion).
"prim" is a list of (pos in global block, primitive declaration). *)
-let transl_store_structure glob map prims str =
+let transl_store_structure module_id glob map prims str =
+ let path = global_path module_id in
let rec transl_store subst = function
[] ->
lambda_unit
@@ -381,7 +382,7 @@
| Tstr_type(decls) :: rem ->
transl_store subst rem
| Tstr_exception(id, decl) :: rem ->
- let lam = transl_exception id (field_path (global_path glob) id) decl in
+ let lam = transl_exception id (field_path path id) decl in
Lsequence(Llet(Strict, id, lam, store_ident id),
transl_store (add_ident false id subst) rem)
| Tstr_exn_rebind(id, path) :: rem ->
@@ -390,7 +391,7 @@
transl_store (add_ident false id subst) rem)
| Tstr_module(id, modl) :: rem ->
let lam =
- transl_module Tcoerce_none (field_path (global_path glob) id) modl in
+ transl_module Tcoerce_none (field_path path id) modl in
(* Careful: the module value stored in the global may be different
from the local module value, in case a coercion is applied.
If so, keep using the local module value (id) in the remainder of
@@ -405,7 +406,7 @@
(fun id modl ->
subst_lambda subst
(transl_module Tcoerce_none
- (field_path (global_path glob) id) modl))
+ (field_path path id) modl))
bindings
(Lsequence(store_idents ids,
transl_store (add_idents true ids subst) rem))
@@ -440,7 +441,7 @@
try
let (pos, cc) = Ident.find_same id map in
let init_val = apply_coercion cc (Lvar id) in
- Lprim(Psetfield(pos, false), [Lprim(Pgetglobal glob, []); init_val])
+ Lprim(Psetfield(pos, false), [glob; init_val])
with Not_found ->
fatal_error("Translmod.store_ident: " ^ Ident.unique_name id)
@@ -452,7 +453,7 @@
let (pos, cc) = Ident.find_same id map in
match cc with
Tcoerce_none ->
- Ident.add id (Lprim(Pfield pos, [Lprim(Pgetglobal glob, [])])) subst
+ Ident.add id (Lprim(Pfield pos, [glob])) subst
| _ ->
if may_coerce then subst else assert false
with Not_found ->
@@ -463,7 +464,7 @@
and store_primitive (pos, prim) cont =
Lsequence(Lprim(Psetfield(pos, false),
- [Lprim(Pgetglobal glob, []); transl_primitive prim]),
+ [glob; transl_primitive prim]),
cont)
in List.fold_right store_primitive prims (transl_store Ident.empty str)
@@ -528,13 +529,13 @@
(* Compile an implementation using transl_store_structure
(for the native-code compiler). *)
-let transl_store_implementation module_name (str, restr) =
+let transl_store_implementation module_name glob (str, restr) =
reset_labels ();
primitive_declarations := [];
let module_id = Ident.create_persistent module_name in
let (map, prims, size) = build_ident_map restr (defined_idents str) in
- transl_store_label_init module_id size
- (transl_store_structure module_id map prims) str
+ transl_store_label_init glob size
+ (transl_store_structure module_id glob map prims) str
(*size, transl_label_init (transl_store_structure module_id map prims str)*)
(* Compile a toplevel phrase *)
@@ -555,12 +556,12 @@
let toploop_getvalue id =
Lapply(Lprim(Pfield toploop_getvalue_pos,
- [Lprim(Pgetglobal toploop_ident, [])]),
+ [Lambda.getglobal toploop_ident]),
[Lconst(Const_base(Const_string (toplevel_name id)))])
let toploop_setvalue id lam =
Lapply(Lprim(Pfield toploop_setvalue_pos,
- [Lprim(Pgetglobal toploop_ident, [])]),
+ [Lambda.getglobal toploop_ident]),
[Lconst(Const_base(Const_string (toplevel_name id))); lam])
let toploop_setvalue_id id = toploop_setvalue id (Lvar id)
@@ -635,7 +636,7 @@
let get_component = function
None -> Lconst const_unit
- | Some id -> Lprim(Pgetglobal id, [])
+ | Some id -> Lambda.getglobal id
let transl_package component_names target_name coercion =
let components =
@@ -651,7 +652,7 @@
assert false in
Lprim(Psetglobal target_name, [Lprim(Pmakeblock(0, Immutable), components)])
-let transl_store_package component_names target_name coercion =
+let transl_store_package component_names glob coercion =
let rec make_sequence fn pos arg =
match arg with
[] -> lambda_unit
@@ -662,7 +663,7 @@
make_sequence
(fun pos id ->
Lprim(Psetfield(pos, false),
- [Lprim(Pgetglobal target_name, []);
+ [glob;
get_component id]))
0 component_names)
| Tcoerce_structure pos_cc_list ->
@@ -671,7 +672,7 @@
make_sequence
(fun dst (src, cc) ->
Lprim(Psetfield(dst, false),
- [Lprim(Pgetglobal target_name, []);
+ [glob;
apply_coercion cc (get_component id.(src))]))
0 pos_cc_list)
| _ -> assert false
diff -ur ocaml/bytecomp/translmod.mli ocaml_bug2/bytecomp/translmod.mli
--- ocaml/bytecomp/translmod.mli 2004-04-09 15:32:27.000000000 +0200
+++ ocaml_bug2/bytecomp/translmod.mli 2006-08-09 13:12:44.000000000 +0200
@@ -20,12 +20,17 @@
val transl_implementation: string -> structure * module_coercion -> lambda
val transl_store_implementation:
- string -> structure * module_coercion -> int * lambda
+ string -> lambda -> structure * module_coercion -> int * lambda
+ (* Arguments: module name (for naming exceptions), access to the
+ global for the unit, structure to be compiled *)
+
val transl_toplevel_definition: structure -> lambda
val transl_package:
Ident.t option list -> Ident.t -> module_coercion -> lambda
val transl_store_package:
- Ident.t option list -> Ident.t -> module_coercion -> int * lambda
+ Ident.t option list -> lambda -> module_coercion -> int * lambda
+ (* The second argument is the code to access the global for the
+ package unit *)
val toplevel_name: Ident.t -> string
diff -ur ocaml/bytecomp/translobj.ml ocaml_bug2/bytecomp/translobj.ml
--- ocaml/bytecomp/translobj.ml 2004-05-26 13:10:51.000000000 +0200
+++ ocaml_bug2/bytecomp/translobj.ml 2006-08-09 13:05:51.000000000 +0200
@@ -105,14 +105,14 @@
expr
let transl_store_label_init glob size f arg =
- method_cache := Lprim(Pfield size, [Lprim(Pgetglobal glob, [])]);
+ method_cache := Lprim(Pfield size, [glob]);
let expr = f arg in
let (size, expr) =
if !method_count = 0 then (size, expr) else
(size+1,
Lsequence(
Lprim(Psetfield(size, false),
- [Lprim(Pgetglobal glob, []);
+ [glob;
Lprim (Pccall prim_makearray, [int !method_count; int 0])]),
expr))
in
diff -ur ocaml/bytecomp/translobj.mli ocaml_bug2/bytecomp/translobj.mli
--- ocaml/bytecomp/translobj.mli 2004-05-26 13:10:51.000000000 +0200
+++ ocaml_bug2/bytecomp/translobj.mli 2006-08-09 13:05:33.000000000 +0200
@@ -22,7 +22,8 @@
val reset_labels: unit -> unit
val transl_label_init: lambda -> lambda
val transl_store_label_init:
- Ident.t -> int -> ('a -> lambda) -> 'a -> int * lambda
+ lambda -> int -> ('a -> lambda) -> 'a -> int * lambda
+ (* The first argument gets the global slot for the current unit *)
val oo_wrap: Env.t -> bool -> ('a -> lambda) -> 'a -> lambda
val oo_add_class: Ident.t -> Env.t * bool
diff -ur ocaml/driver/optcompile.ml ocaml_bug2/driver/optcompile.ml
--- ocaml/driver/optcompile.ml 2005-08-08 11:41:51.000000000 +0200
+++ ocaml_bug2/driver/optcompile.ml 2006-08-09 13:18:13.000000000 +0200
@@ -97,7 +97,8 @@
++ print_if ppf Clflags.dump_parsetree Printast.implementation
++ Unused_var.warn ppf
++ Typemod.type_implementation sourcefile outputprefix modulename env
- ++ Translmod.transl_store_implementation modulename
+ ++ Translmod.transl_store_implementation modulename
+ (Compilenv.current_unit_glob ())
+++ print_if ppf Clflags.dump_rawlambda Printlambda.lambda
+++ Simplif.simplify_lambda
+++ print_if ppf Clflags.dump_lambda Printlambda.lambda
diff -ur ocaml/utils/warnings.ml ocaml_bug2/utils/warnings.ml
--- ocaml/utils/warnings.ml 2006-07-23 15:25:41.000000000 +0200
+++ ocaml_bug2/utils/warnings.ml 2006-08-09 15:21:05.000000000 +0200
@@ -38,6 +38,7 @@
| Camlp4 of string
| All_clauses_guarded
| Useless_record_with
+ | Cmx_not_found of string
| Unused_var of string (* Y *)
| Unused_var_strict of string (* Z *)
;;
@@ -65,6 +66,7 @@
| Nonreturning_statement
| Camlp4 _
| Useless_record_with
+ | Cmx_not_found _
| All_clauses_guarded -> 'x'
| Unused_var _ -> 'y'
| Unused_var_strict _ -> 'z'
@@ -158,6 +160,10 @@
| Useless_record_with ->
"this record is defined by a `with' expression,\n\
but no fields are borrowed from the original."
+ | Cmx_not_found m ->
+ ".cmx file not found for module " ^ m ^ ": it will break if it has\n\
+ been compiled with -for-pack, and inter-module optimizations are\n\
+ disabled anyway."
;;
let nerrors = ref 0;;
diff -ur ocaml/utils/warnings.mli ocaml_bug2/utils/warnings.mli
--- ocaml/utils/warnings.mli 2006-04-05 04:28:13.000000000 +0200
+++ ocaml_bug2/utils/warnings.mli 2006-08-09 15:00:36.000000000 +0200
@@ -38,6 +38,7 @@
| Camlp4 of string
| All_clauses_guarded
| Useless_record_with
+ | Cmx_not_found of string
| Unused_var of string (* Y *)
| Unused_var_strict of string (* Z *)
;;
|