diff options
-rw-r--r-- | .depend | 51 | ||||
-rw-r--r-- | bytecomp/bytegen.ml | 41 | ||||
-rw-r--r-- | bytecomp/bytelink.ml | 49 | ||||
-rw-r--r-- | bytecomp/emitcode.ml | 18 | ||||
-rw-r--r-- | bytecomp/emitcode.mli | 7 | ||||
-rw-r--r-- | bytecomp/instruct.ml | 18 | ||||
-rw-r--r-- | bytecomp/instruct.mli | 32 | ||||
-rw-r--r-- | bytecomp/lambda.ml | 12 | ||||
-rw-r--r-- | bytecomp/lambda.mli | 10 | ||||
-rw-r--r-- | bytecomp/printinstr.ml | 1 | ||||
-rw-r--r-- | bytecomp/printlambda.ml | 11 | ||||
-rw-r--r-- | bytecomp/simplif.ml | 4 | ||||
-rw-r--r-- | bytecomp/symtable.ml | 4 | ||||
-rw-r--r-- | bytecomp/symtable.mli | 1 | ||||
-rw-r--r-- | bytecomp/translcore.ml | 56 | ||||
-rw-r--r-- | byterun/Makefile | 3 | ||||
-rw-r--r-- | byterun/fix_code.c | 53 | ||||
-rw-r--r-- | byterun/fix_code.h | 7 | ||||
-rw-r--r-- | byterun/instruct.h | 4 | ||||
-rw-r--r-- | byterun/interp.c | 56 | ||||
-rw-r--r-- | byterun/stacks.c | 3 | ||||
-rw-r--r-- | byterun/stacks.h | 1 | ||||
-rw-r--r-- | byterun/startup.c | 17 | ||||
-rw-r--r-- | byterun/sys.c | 2 | ||||
-rw-r--r-- | driver/main.ml | 1 | ||||
-rw-r--r-- | typing/env.ml | 116 | ||||
-rw-r--r-- | typing/env.mli | 16 | ||||
-rw-r--r-- | utils/clflags.ml | 1 |
28 files changed, 476 insertions, 119 deletions
@@ -155,13 +155,13 @@ typing/typecore.cmx: parsing/asttypes.cmi typing/ctype.cmx typing/env.cmx \ typing/typedecl.cmo: utils/config.cmi typing/ctype.cmi typing/env.cmi \ typing/ident.cmi typing/includecore.cmi parsing/location.cmi \ parsing/parsetree.cmi typing/primitive.cmi typing/printtyp.cmi \ - typing/typedtree.cmi typing/types.cmi typing/typetexp.cmi \ - typing/typedecl.cmi + typing/subst.cmi typing/typedtree.cmi typing/types.cmi \ + typing/typetexp.cmi typing/typedecl.cmi typing/typedecl.cmx: utils/config.cmx typing/ctype.cmx typing/env.cmx \ typing/ident.cmx typing/includecore.cmx parsing/location.cmx \ parsing/parsetree.cmi typing/primitive.cmx typing/printtyp.cmx \ - typing/typedtree.cmx typing/types.cmx typing/typetexp.cmx \ - typing/typedecl.cmi + typing/subst.cmx typing/typedtree.cmx typing/types.cmx \ + typing/typetexp.cmx typing/typedecl.cmi typing/typedtree.cmo: parsing/asttypes.cmi typing/env.cmi typing/ident.cmi \ parsing/location.cmi utils/misc.cmi typing/path.cmi typing/primitive.cmi \ typing/types.cmi typing/typedtree.cmi @@ -194,9 +194,10 @@ bytecomp/bytegen.cmi: bytecomp/instruct.cmi bytecomp/lambda.cmi bytecomp/bytelink.cmi: bytecomp/emitcode.cmi bytecomp/symtable.cmi bytecomp/emitcode.cmi: typing/ident.cmi bytecomp/instruct.cmi \ bytecomp/lambda.cmi -bytecomp/instruct.cmi: typing/ident.cmi bytecomp/lambda.cmi -bytecomp/lambda.cmi: parsing/asttypes.cmi typing/ident.cmi typing/path.cmi \ - typing/primitive.cmi +bytecomp/instruct.cmi: typing/env.cmi typing/ident.cmi bytecomp/lambda.cmi \ + typing/types.cmi +bytecomp/lambda.cmi: parsing/asttypes.cmi typing/env.cmi typing/ident.cmi \ + typing/path.cmi typing/primitive.cmi typing/types.cmi bytecomp/matching.cmi: typing/ident.cmi bytecomp/lambda.cmi \ parsing/location.cmi typing/typedtree.cmi bytecomp/printinstr.cmi: bytecomp/instruct.cmi @@ -211,21 +212,23 @@ bytecomp/translcore.cmi: parsing/asttypes.cmi typing/ident.cmi \ bytecomp/translmod.cmi: bytecomp/lambda.cmi typing/typedtree.cmi bytecomp/translobj.cmi: typing/ident.cmi bytecomp/lambda.cmi bytecomp/bytegen.cmo: parsing/asttypes.cmi typing/ident.cmi \ - bytecomp/instruct.cmi bytecomp/lambda.cmi utils/misc.cmi \ - typing/primitive.cmi typing/types.cmi bytecomp/bytegen.cmi + bytecomp/instruct.cmi bytecomp/lambda.cmi parsing/location.cmi \ + utils/misc.cmi typing/primitive.cmi typing/types.cmi bytecomp/bytegen.cmi bytecomp/bytegen.cmx: parsing/asttypes.cmi typing/ident.cmx \ - bytecomp/instruct.cmx bytecomp/lambda.cmx utils/misc.cmx \ - typing/primitive.cmx typing/types.cmx bytecomp/bytegen.cmi + bytecomp/instruct.cmx bytecomp/lambda.cmx parsing/location.cmx \ + utils/misc.cmx typing/primitive.cmx typing/types.cmx bytecomp/bytegen.cmi bytecomp/bytelibrarian.cmo: utils/clflags.cmo utils/config.cmi \ bytecomp/emitcode.cmi utils/misc.cmi bytecomp/bytelibrarian.cmi bytecomp/bytelibrarian.cmx: utils/clflags.cmx utils/config.cmx \ bytecomp/emitcode.cmx utils/misc.cmx bytecomp/bytelibrarian.cmi bytecomp/bytelink.cmo: utils/ccomp.cmi utils/clflags.cmo utils/config.cmi \ - bytecomp/emitcode.cmi typing/ident.cmi utils/misc.cmi \ - bytecomp/opcodes.cmo bytecomp/symtable.cmi bytecomp/bytelink.cmi + bytecomp/emitcode.cmi typing/ident.cmi bytecomp/instruct.cmi \ + utils/misc.cmi bytecomp/opcodes.cmo bytecomp/symtable.cmi \ + bytecomp/bytelink.cmi bytecomp/bytelink.cmx: utils/ccomp.cmx utils/clflags.cmx utils/config.cmx \ - bytecomp/emitcode.cmx typing/ident.cmx utils/misc.cmx \ - bytecomp/opcodes.cmx bytecomp/symtable.cmx bytecomp/bytelink.cmi + bytecomp/emitcode.cmx typing/ident.cmx bytecomp/instruct.cmx \ + utils/misc.cmx bytecomp/opcodes.cmx bytecomp/symtable.cmx \ + bytecomp/bytelink.cmi bytecomp/emitcode.cmo: parsing/asttypes.cmi utils/config.cmi typing/env.cmi \ typing/ident.cmi bytecomp/instruct.cmi bytecomp/lambda.cmi \ bytecomp/meta.cmi utils/misc.cmi bytecomp/opcodes.cmo \ @@ -234,14 +237,16 @@ bytecomp/emitcode.cmx: parsing/asttypes.cmi utils/config.cmx typing/env.cmx \ typing/ident.cmx bytecomp/instruct.cmx bytecomp/lambda.cmx \ bytecomp/meta.cmx utils/misc.cmx bytecomp/opcodes.cmx \ bytecomp/translmod.cmx bytecomp/emitcode.cmi -bytecomp/instruct.cmo: typing/ident.cmi bytecomp/lambda.cmi \ - bytecomp/instruct.cmi -bytecomp/instruct.cmx: typing/ident.cmx bytecomp/lambda.cmx \ - bytecomp/instruct.cmi -bytecomp/lambda.cmo: parsing/asttypes.cmi typing/ident.cmi utils/misc.cmi \ - typing/path.cmi typing/primitive.cmi bytecomp/lambda.cmi -bytecomp/lambda.cmx: parsing/asttypes.cmi typing/ident.cmx utils/misc.cmx \ - typing/path.cmx typing/primitive.cmx bytecomp/lambda.cmi +bytecomp/instruct.cmo: typing/env.cmi typing/ident.cmi bytecomp/lambda.cmi \ + typing/types.cmi bytecomp/instruct.cmi +bytecomp/instruct.cmx: typing/env.cmx typing/ident.cmx bytecomp/lambda.cmx \ + typing/types.cmx bytecomp/instruct.cmi +bytecomp/lambda.cmo: parsing/asttypes.cmi typing/env.cmi typing/ident.cmi \ + utils/misc.cmi typing/path.cmi typing/primitive.cmi typing/types.cmi \ + bytecomp/lambda.cmi +bytecomp/lambda.cmx: parsing/asttypes.cmi typing/env.cmx typing/ident.cmx \ + utils/misc.cmx typing/path.cmx typing/primitive.cmx typing/types.cmx \ + bytecomp/lambda.cmi bytecomp/matching.cmo: parsing/asttypes.cmi typing/ctype.cmi typing/ident.cmi \ bytecomp/lambda.cmi parsing/location.cmi utils/misc.cmi typing/predef.cmi \ typing/primitive.cmi typing/typedtree.cmi typing/types.cmi \ diff --git a/bytecomp/bytegen.ml b/bytecomp/bytegen.ml index 8e54fdc22..5624d4715 100644 --- a/bytecomp/bytegen.ml +++ b/bytecomp/bytegen.ml @@ -27,17 +27,7 @@ let label_counter = ref 0 let new_label () = incr label_counter; !label_counter -(**** Structure of the compilation environment. ****) - -type compilation_env = - { ce_stack: int Ident.tbl; (* Positions of variables in the stack *) - ce_heap: int Ident.tbl } (* Structure of the heap-allocated env *) - -(* The ce_stack component gives locations of variables residing - in the stack. The locations are offsets w.r.t. the origin of the - stack frame. - The ce_heap component gives the positions of variables residing in the - heap-allocated environment. *) +(**** Operations on compilation environments. ****) let empty_env = { ce_stack = Ident.empty; ce_heap = Ident.empty } @@ -402,7 +392,34 @@ let rec comp_expr env exp sz cont = with Not_found -> fatal_error "Bytegen.comp_expr: assign" end - + | Levent(lam, lev) -> + let ev = + { ev_pos = 0; (* patched in emitcode *) + ev_file = !Location.input_name; + ev_char = lev.lev_loc; + ev_kind = begin match lev.lev_kind with + Lev_before -> Event_before + | Lev_after ty -> Event_after ty + end; + ev_typenv = lev.lev_env; + ev_compenv = env; + ev_stacksize = sz } in + begin match lev.lev_kind with + Lev_before -> + let c = comp_expr env lam sz cont in + begin match c with + (* Keep following event, supposedly more informative *) + Kevent _ :: _ -> c + | _ -> Kevent ev :: c + end + | Lev_after ty -> + let cont1 = + (* Discard following events, supposedly less informative *) + match cont with + Kevent _ :: c -> c + | _ -> cont in + comp_expr env lam sz (Kevent ev :: cont1) + end (* Compile a list of arguments [e1; ...; eN] to a primitive operation. The values of eN ... e2 are pushed on the stack, e2 at top of stack, diff --git a/bytecomp/bytelink.ml b/bytecomp/bytelink.ml index 4176d26cd..476278e26 100644 --- a/bytecomp/bytelink.ml +++ b/bytecomp/bytelink.ml @@ -16,6 +16,7 @@ open Sys open Misc open Config +open Instruct open Emitcode type error = @@ -111,6 +112,8 @@ let scan_file obj_name tolink = (* Second pass: link in the required units *) +let debug_info = ref ([] : debug_event list list) + (* Consistency check between interfaces *) let crc_interfaces = @@ -130,24 +133,35 @@ let check_consistency file_name cu = cu.cu_imports; Hashtbl.add crc_interfaces cu.cu_name (file_name, cu.cu_interface) +(* Relocate and record compilation events *) + +let debug_info = ref ([] : debug_event list list) + +let record_events orig evl = + if evl <> [] then begin + List.iter (fun ev -> ev.ev_pos <- orig + ev.ev_pos) evl; + debug_info := evl :: !debug_info + end + (* Link in a compilation unit *) -let link_compunit output_fun inchan file_name compunit = +let link_compunit output_fun currpos_fun inchan file_name compunit = check_consistency file_name compunit; seek_in inchan compunit.cu_pos; let code_block = String.create compunit.cu_codesize in really_input inchan code_block 0 compunit.cu_codesize; Symtable.patch_object code_block compunit.cu_reloc; + if !Clflags.debug then record_events (currpos_fun()) compunit.cu_events; output_fun code_block; if !Clflags.link_everything then List.iter Symtable.require_primitive compunit.cu_primitives (* Link in a .cmo file *) -let link_object output_fun file_name compunit = +let link_object output_fun currpos_fun file_name compunit = let inchan = open_in_bin file_name in try - link_compunit output_fun inchan file_name compunit; + link_compunit output_fun currpos_fun inchan file_name compunit; close_in inchan with Symtable.Error msg -> @@ -157,10 +171,12 @@ let link_object output_fun file_name compunit = (* Link in a .cma file *) -let link_archive output_fun file_name units_required = +let link_archive output_fun currpos_fun file_name units_required = let inchan = open_in_bin file_name in try - List.iter (link_compunit output_fun inchan file_name) units_required; + List.iter + (link_compunit output_fun currpos_fun inchan file_name) + units_required; close_in inchan with Symtable.Error msg -> @@ -170,9 +186,11 @@ let link_archive output_fun file_name units_required = (* Link in a .cmo or .cma file *) -let link_file output_fun = function - Link_object(file_name, unit) -> link_object output_fun file_name unit - | Link_archive(file_name, units) -> link_archive output_fun file_name units +let link_file output_fun currpos_fun = function + Link_object(file_name, unit) -> + link_object output_fun currpos_fun file_name unit + | Link_archive(file_name, units) -> + link_archive output_fun currpos_fun file_name units (* Create a bytecode executable file *) @@ -198,7 +216,9 @@ let link_bytecode objfiles exec_name copy_header = let pos1 = pos_out outchan in Symtable.init(); Hashtbl.clear crc_interfaces; - List.iter (link_file (output_string outchan)) tolink; + let output_fun = output_string outchan + and currpos_fun () = pos_out outchan - pos1 in + List.iter (link_file output_fun currpos_fun) tolink; (* The final STOP instruction *) output_byte outchan Opcodes.opSTOP; output_byte outchan 0; output_byte outchan 0; output_byte outchan 0; @@ -208,12 +228,15 @@ let link_bytecode objfiles exec_name copy_header = (* The map of global identifiers *) let pos3 = pos_out outchan in Symtable.output_global_map outchan; - (* The trailer *) + (* Debug info *) let pos4 = pos_out outchan in + if !Clflags.debug then output_value outchan !debug_info; + (* The trailer *) + let pos5 = pos_out outchan in output_binary_int outchan (pos2 - pos1); output_binary_int outchan (pos3 - pos2); output_binary_int outchan (pos4 - pos3); - output_binary_int outchan 0; + output_binary_int outchan (pos5 - pos4); output_string outchan exec_magic_number; close_out outchan with x -> @@ -267,7 +290,9 @@ let link_bytecode_as_c objfiles outfile = output_string outchan "static int caml_code[] = {\n"; Symtable.init(); Hashtbl.clear crc_interfaces; - List.iter (link_file (output_code_string outchan)) tolink; + let output_fun = output_code_string outchan + and currpos_fun () = fatal_error "Bytelink.link_bytecode_as_c" in + List.iter (link_file output_fun currpos_fun) tolink; (* The final STOP instruction *) Printf.fprintf outchan "\n0x%x};\n\n" Opcodes.opSTOP; (* The table of global data *) diff --git a/bytecomp/emitcode.ml b/bytecomp/emitcode.ml index e03a20dbc..ffd7698a4 100644 --- a/bytecomp/emitcode.ml +++ b/bytecomp/emitcode.ml @@ -39,7 +39,8 @@ type compilation_unit = cu_interface: Digest.t; (* CRC of interface implemented *) cu_imports: (string * Digest.t) list; (* Names and CRC of intfs imported *) cu_primitives: string list; (* Primitives declared inside *) - mutable cu_force_link: bool } (* Must be linked even if unref'ed *) + mutable cu_force_link: bool; (* Must be linked even if unref'ed *) + cu_events: debug_event list } (* Debugging events *) (* Format of a .cmo file: magic number (Config.cmo_magic_number) @@ -135,12 +136,21 @@ and slot_for_c_prim name = enter (Reloc_primitive name); out_int 0 +(* Debugging events *) + +let events = ref ([] : debug_event list) + +let record_event ev = + ev.ev_pos <- !out_position; + events := ev :: !events + (* Initialization *) let init () = out_position := 0; label_table := Array.create 16 (Label_undefined []); - reloc_info := [] + reloc_info := []; + events := [] (* Emission of one instruction *) @@ -235,6 +245,7 @@ let emit_instr = function | Koffsetint n -> out opOFFSETINT; out_int n | Koffsetref n -> out opOFFSETREF; out_int n | Kgetmethod -> out opGETMETHOD + | Kevent ev -> record_event ev | Kstop -> out opSTOP (* Emission of a list of instructions. Include some peephole optimization. *) @@ -291,7 +302,8 @@ let to_file outchan unit_name crc_interface code = cu_interface = crc_interface; cu_imports = Env.imported_units(); cu_primitives = !Translmod.primitive_declarations; - cu_force_link = false } in + cu_force_link = false; + cu_events = !events } in init(); (* Free out_buffer and reloc_info *) let pos_compunit = pos_out outchan in output_value outchan compunit; diff --git a/bytecomp/emitcode.mli b/bytecomp/emitcode.mli index 87dcb1d6b..365286d55 100644 --- a/bytecomp/emitcode.mli +++ b/bytecomp/emitcode.mli @@ -20,8 +20,8 @@ open Instruct type reloc_info = Reloc_literal of structured_constant (* structured constant *) - | Reloc_getglobal of Ident.t (* reference to a global *) - | Reloc_setglobal of Ident.t (* definition of a global *) + | Reloc_getglobal of Ident.t (* reference to a global *) + | Reloc_setglobal of Ident.t (* definition of a global *) | Reloc_primitive of string (* C primitive number *) (* Descriptor for compilation units *) @@ -34,7 +34,8 @@ type compilation_unit = cu_interface: Digest.t; (* CRC of interface implemented *) cu_imports: (string * Digest.t) list; (* Names and CRC of intfs imported *) cu_primitives: string list; (* Primitives declared inside *) - mutable cu_force_link: bool } (* Must be linked even if unref'ed *) + mutable cu_force_link: bool; (* Must be linked even if unref'ed *) + cu_events: debug_event list } (* Debugging events *) (* Format of a .cmo file: magic number (Config.cmo_magic_number) diff --git a/bytecomp/instruct.ml b/bytecomp/instruct.ml index f3d7c9e7a..d86157ba3 100644 --- a/bytecomp/instruct.ml +++ b/bytecomp/instruct.ml @@ -13,6 +13,23 @@ open Lambda +type compilation_env = + { ce_stack: int Ident.tbl; + ce_heap: int Ident.tbl } + +type debug_event = + { mutable ev_pos: int; (* Position in bytecode *) + ev_file: string; (* Source file name *) + ev_char: int; (* Location in source file *) + ev_kind: debug_event_kind; (* Before/after event *) + ev_typenv: Env.summary; (* Typing environment *) + ev_compenv: compilation_env; (* Compilation environment *) + ev_stacksize: int } (* Size of stack frame *) + +and debug_event_kind = + Event_before + | Event_after of Types.type_expr + type label = int (* Symbolic code labels *) type instruction = @@ -61,6 +78,7 @@ type instruction = | Koffsetint of int | Koffsetref of int | Kgetmethod + | Kevent of debug_event | Kstop let immed_min = -0x40000000 diff --git a/bytecomp/instruct.mli b/bytecomp/instruct.mli index 5aabce887..1958551ff 100644 --- a/bytecomp/instruct.mli +++ b/bytecomp/instruct.mli @@ -15,7 +15,36 @@ open Lambda -type label = int (* Symbolic code labels *) +(* Structure of compilation environments *) + +type compilation_env = + { ce_stack: int Ident.tbl; (* Positions of variables in the stack *) + ce_heap: int Ident.tbl } (* Structure of the heap-allocated env *) + +(* The ce_stack component gives locations of variables residing + in the stack. The locations are offsets w.r.t. the origin of the + stack frame. + The ce_heap component gives the positions of variables residing in the + heap-allocated environment. *) + +(* Debugging events *) + +type debug_event = + { mutable ev_pos: int; (* Position in bytecode *) + ev_file: string; (* Source file name *) + ev_char: int; (* Location in source file *) + ev_kind: debug_event_kind; (* Before/after event *) + ev_typenv: Env.summary; (* Typing environment *) + ev_compenv: compilation_env; (* Compilation environment *) + ev_stacksize: int } (* Size of stack frame *) + +and debug_event_kind = + Event_before + | Event_after of Types.type_expr + +(* Abstract machine instructions *) + +type label = int (* Symbolic code labels *) type instruction = Klabel of label @@ -63,6 +92,7 @@ type instruction = | Koffsetint of int | Koffsetref of int | Kgetmethod + | Kevent of debug_event | Kstop val immed_min: int diff --git a/bytecomp/lambda.ml b/bytecomp/lambda.ml index 863a4439c..825389866 100644 --- a/bytecomp/lambda.ml +++ b/bytecomp/lambda.ml @@ -92,6 +92,7 @@ type lambda = | Lfor of Ident.t * lambda * lambda * direction_flag * lambda | Lassign of Ident.t * lambda | Lsend of lambda * lambda * lambda list + | Levent of lambda * lambda_event and lambda_switch = { sw_numconsts: int; @@ -100,6 +101,15 @@ and lambda_switch = sw_blocks: (int * lambda) list; sw_checked: bool } +and lambda_event = + { lev_loc: int; + lev_kind: lambda_event_kind; + lev_env: Env.summary } + +and lambda_event_kind = + Lev_before + | Lev_after of Types.type_expr + let const_unit = Const_pointer 0 let lambda_unit = Lconst const_unit @@ -165,6 +175,8 @@ let free_variables l = fv := IdentSet.add id !fv; freevars e | Lsend (met, obj, args) -> List.iter freevars (met::obj::args) + | Levent (lam, evt) -> + freevars lam in freevars l; !fv (* Check if an action has a "when" guard *) diff --git a/bytecomp/lambda.mli b/bytecomp/lambda.mli index 202d3e0b4..04aad3808 100644 --- a/bytecomp/lambda.mli +++ b/bytecomp/lambda.mli @@ -92,6 +92,7 @@ type lambda = | Lfor of Ident.t * lambda * lambda * direction_flag * lambda | Lassign of Ident.t * lambda | Lsend of lambda * lambda * lambda list + | Levent of lambda * lambda_event and lambda_switch = { sw_numconsts: int; (* Number of integer cases *) @@ -100,6 +101,15 @@ and lambda_switch = sw_blocks: (int * lambda) list; (* Tag block cases *) sw_checked: bool } (* True if bound checks needed *) +and lambda_event = + { lev_loc: int; + lev_kind: lambda_event_kind; + lev_env: Env.summary } + +and lambda_event_kind = + Lev_before + | Lev_after of Types.type_expr + val const_unit: structured_constant val lambda_unit: lambda val name_lambda: lambda -> (Ident.t -> lambda) -> lambda diff --git a/bytecomp/printinstr.ml b/bytecomp/printinstr.ml index 56b15763f..02882b96b 100644 --- a/bytecomp/printinstr.ml +++ b/bytecomp/printinstr.ml @@ -95,6 +95,7 @@ let instruction = function | Koffsetref n -> print_string "\toffsetref "; print_int n | Kgetmethod -> print_string "\tgetmethod" | Kstop -> print_string "\tstop" + | Kevent ev -> print_string "\tevent "; print_int ev.ev_char let rec instruction_list = function [] -> () diff --git a/bytecomp/printlambda.ml b/bytecomp/printlambda.ml index fa7135ef2..93700a444 100644 --- a/bytecomp/printlambda.ml +++ b/bytecomp/printlambda.ml @@ -258,6 +258,17 @@ let rec lambda = function List.iter (fun l -> print_space(); lambda l) largs; print_string ")"; close_box() + | Levent(lam, ev) -> + open_hovbox 2; + begin match ev.lev_kind with + Lev_before -> print_string "(before " + | Lev_after _ -> print_string "(after " + end; + print_int ev.lev_loc; + print_space(); + lambda lam; + print_string ")"; + close_box() and sequence = function Lsequence(l1, l2) -> diff --git a/bytecomp/simplif.ml b/bytecomp/simplif.ml index 32b5ab74e..a4fff40b8 100644 --- a/bytecomp/simplif.ml +++ b/bytecomp/simplif.ml @@ -75,6 +75,8 @@ let rec eliminate_ref id = function | Lsend(m, o, el) -> Lsend(eliminate_ref id m, eliminate_ref id o, List.map (eliminate_ref id) el) + | Levent(l, ev) -> + Levent(eliminate_ref id l, ev) (* Simplification of lets *) @@ -130,6 +132,7 @@ let simplify_lambda lam = v's refcount *) count l | Lsend(m, o, ll) -> List.iter count (m::o::ll) + | Levent(l, ev) -> count l in count lam; (* Second pass: remove Lalias bindings of unused variables, @@ -188,5 +191,6 @@ let simplify_lambda lam = Lfor(v, simplif l1, simplif l2, dir, simplif l3) | Lassign(v, l) -> Lassign(v, simplif l) | Lsend(m, o, ll) -> Lsend(simplif m, simplif o, List.map simplif ll) + | Levent(l, ev) -> Levent(simplif l, ev) in simplif lam diff --git a/bytecomp/symtable.ml b/bytecomp/symtable.ml index 9974aa2d2..6ba9278c6 100644 --- a/bytecomp/symtable.ml +++ b/bytecomp/symtable.ml @@ -209,9 +209,11 @@ let init_toplevel () = (* Find the value of a global identifier *) +let get_global_position id = slot_for_getglobal id + let get_global_value id = (Meta.global_data()).(slot_for_getglobal id) -and assign_global_value id v = +let assign_global_value id v = (Meta.global_data()).(slot_for_getglobal id) <- v (* Save and restore the current state *) diff --git a/bytecomp/symtable.mli b/bytecomp/symtable.mli index 29dcc4b67..5850f2f3e 100644 --- a/bytecomp/symtable.mli +++ b/bytecomp/symtable.mli @@ -30,6 +30,7 @@ val init_toplevel: unit -> unit val update_global_table: unit -> unit val get_global_value: Ident.t -> Obj.t val assign_global_value: Ident.t -> Obj.t -> unit +val get_global_position: Ident.t -> int type global_map diff --git a/bytecomp/translcore.ml b/bytecomp/translcore.ml index 4a02bae2f..8c15ff8f0 100644 --- a/bytecomp/translcore.ml +++ b/bytecomp/translcore.ml @@ -300,6 +300,22 @@ let rec name_pattern default = function | Tpat_alias(p, id) -> id | _ -> name_pattern default rem +(* Insertion of debugging events *) + +let event_before exp lam = + if !Clflags.debug + then Levent(lam, {lev_loc = exp.exp_loc.Location.loc_start; + lev_kind = Lev_before; + lev_env = Env.summary exp.exp_env}) + else lam + +let event_after exp lam = + if !Clflags.debug + then Levent(lam, {lev_loc = exp.exp_loc.Location.loc_end; + lev_kind = Lev_after exp.exp_type; + lev_env = Env.summary exp.exp_env}) + else lam + (* Translation of expressions *) let rec transl_exp e = @@ -313,7 +329,7 @@ let rec transl_exp e = | Texp_constant cst -> Lconst(Const_base cst) | Texp_let(rec_flag, pat_expr_list, body) -> - transl_let rec_flag pat_expr_list (transl_exp body) + transl_let rec_flag pat_expr_list (event_before body (transl_exp body)) | Texp_function pat_expr_list -> let (kind, params, body) = transl_function e.exp_loc !Clflags.native_code pat_expr_list in @@ -322,14 +338,15 @@ let rec transl_exp e = when List.length args = p.prim_arity -> Lprim(transl_prim p args, transl_list args) | Texp_apply(funct, args) -> - begin match transl_exp funct with - Lapply(lfunct, largs) -> - Lapply(lfunct, largs @ transl_list args) - | Lsend(lmet, lobj, largs) -> - Lsend(lmet, lobj, largs @ transl_list args) - | lexp -> - Lapply(lexp, transl_list args) - end + let lam = + match transl_exp funct with + Lsend(lmet, lobj, largs) -> + Lsend(lmet, lobj, largs @ transl_list args) + | Levent(Lsend(lmet, lobj, largs), _) -> + Lsend(lmet, lobj, largs @ transl_list args) + | lexp -> + Lapply(lexp, transl_list args) in + event_after e lam | Texp_match({exp_desc = Texp_tuple argl} as arg, pat_expr_list) -> Matching.for_multiple_match e.exp_loc (transl_list argl) (transl_cases pat_expr_list) @@ -419,19 +436,24 @@ let rec transl_exp e = fill_fields 1 (List.tl expr_list)) end | Texp_ifthenelse(cond, ifso, Some ifnot) -> - Lifthenelse(transl_exp cond, transl_exp ifso, transl_exp ifnot) + Lifthenelse(transl_exp cond, + event_before ifso (transl_exp ifso), + event_before ifnot (transl_exp ifnot)) | Texp_ifthenelse(cond, ifso, None) -> - Lifthenelse(transl_exp cond, transl_exp ifso, lambda_unit) + Lifthenelse(transl_exp cond, + event_before ifso (transl_exp ifso), + lambda_unit) | Texp_sequence(expr1, expr2) -> - Lsequence(transl_exp expr1, transl_exp expr2) + Lsequence(transl_exp expr1, event_before expr2 (transl_exp expr2)) | Texp_while(cond, body) -> - Lwhile(transl_exp cond, transl_exp body) + Lwhile(transl_exp cond, event_before body (transl_exp body)) | Texp_for(param, low, high, dir, body) -> - Lfor(param, transl_exp low, transl_exp high, dir, transl_exp body) + Lfor(param, transl_exp low, transl_exp high, dir, + event_before body (transl_exp body)) | Texp_when(cond, body) -> Lifthenelse(transl_exp cond, transl_exp body, Lstaticfail) | Texp_send(expr, met) -> - Lsend(Lvar (meth met), transl_exp expr, []) + event_after e (Lsend(Lvar (meth met), transl_exp expr, [])) | Texp_new cl -> Lprim(Pfield 0, [transl_path cl]) | Texp_instvar(path_self, path) -> @@ -454,7 +476,9 @@ and transl_list expr_list = List.map transl_exp expr_list and transl_cases pat_expr_list = - List.map (fun (pat, expr) -> (pat, transl_exp expr)) pat_expr_list + List.map + (fun (pat, expr) -> (pat, event_before expr (transl_exp expr))) + pat_expr_list and transl_tupled_cases patl_expr_list = List.map (fun (patl, expr) -> (patl, transl_exp expr)) patl_expr_list diff --git a/byterun/Makefile b/byterun/Makefile index 5f69ea498..2f13366b9 100644 --- a/byterun/Makefile +++ b/byterun/Makefile @@ -9,7 +9,7 @@ OBJS=interp.o misc.o stacks.o fix_code.o startup.o main.o \ fail.o signals.o printexc.o \ compare.o ints.o floats.o str.o array.o io.o extern.o intern.o \ hash.o sys.o meta.o parsing.o gc_ctrl.o terminfo.o md5.o obj.o \ - lexing.o callback.o + lexing.o callback.o debugger.o DOBJS=$(OBJS:.o=.d.o) instrtrace.d.o @@ -63,6 +63,7 @@ prims.c : primitives opnames.h : instruct.h sed -e '/\/\*/d' \ + -e '/^#/d' \ -e 's/enum /char * names_of_/' \ -e 's/{$$/[] = {/' \ -e 's/\([A-Z][A-Z_0-9]*\)/"\1"/g' instruct.h > opnames.h diff --git a/byterun/fix_code.c b/byterun/fix_code.c index 363fbbb5a..5713330d6 100644 --- a/byterun/fix_code.c +++ b/byterun/fix_code.c @@ -11,14 +11,51 @@ /* $Id$ */ -/* Translate a block of bytecode (endianness switch, threading). */ +/* Handling of blocks of bytecode (endianness switch, threading). */ #include "config.h" +#include "debugger.h" #include "fix_code.h" +#include "memory.h" #include "misc.h" #include "mlvalues.h" #include "instruct.h" #include "reverse.h" +#ifdef HAS_UNISTD +#include <unistd.h> +#endif + +code_t start_code; +asize_t code_size; +unsigned char * saved_code; + +/* Read the main bytecode block from a file */ + +void load_code(fd, len) + int fd; + asize_t len; +{ + int i; + + code_size = len; + start_code = (code_t) stat_alloc(code_size); + if (read(fd, (char *) start_code, code_size) != code_size) + fatal_error("Fatal error: truncated bytecode file.\n"); +#ifdef BIG_ENDIAN + fixup_endianness(start_code, code_size); +#endif + if (debugger_in_use) { + len /= sizeof(opcode_t); + saved_code = (unsigned char *) stat_alloc(len); + for (i = 0; i < len; i++) saved_code[i] = start_code[i]; + } +#ifdef THREADED_CODE + /* Better to thread now than at the beginning of interprete(), + since the debugger interface needs to perform SET_EVENT requests + on the code. */ + thread_code(start_code, code_size); +#endif +} /* This code is needed only if the processor is big endian */ @@ -86,4 +123,16 @@ void thread_code (code_t code, asize_t len) Assert(p == code + len); } -#endif /* THREAD_CODE */ +#endif /* THREADED_CODE */ + +void set_instruction(pos, instr) + code_t pos; + opcode_t instr; +{ +#ifdef THREADED_CODE + *pos = (opcode_t)((unsigned long)(instr_table[instr])); +#else + *pos = instr; +#endif +} + diff --git a/byterun/fix_code.h b/byterun/fix_code.h index c6ff34d27..b26f0fc71 100644 --- a/byterun/fix_code.h +++ b/byterun/fix_code.h @@ -11,7 +11,7 @@ /* $Id$ */ -/* Translate a block of bytecode (endianness switch, threading). */ +/* Handling of blocks of bytecode (endianness switch, threading). */ #ifndef _fix_code_ #define _fix_code_ @@ -21,12 +21,17 @@ #include "misc.h" #include "mlvalues.h" +extern code_t start_code; +extern asize_t code_size; +extern unsigned char * saved_code; #ifdef THREADED_CODE extern void ** instr_table; #endif +void load_code P((int fd, asize_t len)); void fixup_endianness P((code_t code, asize_t len)); void thread_code P((code_t code, asize_t len)); +void set_instruction P((code_t pos, opcode_t instr)); #endif diff --git a/byterun/instruct.h b/byterun/instruct.h index 68695f9f3..2f2010227 100644 --- a/byterun/instruct.h +++ b/byterun/instruct.h @@ -43,5 +43,7 @@ enum instructions { EQ, NEQ, LTINT, LEINT, GTINT, GEINT, OFFSETINT, OFFSETREF, GETMETHOD, - STOP + STOP, EVENT, BREAK }; + +#define Last_instruction BREAK diff --git a/byterun/interp.c b/byterun/interp.c index 20c79add2..5729d9879 100644 --- a/byterun/interp.c +++ b/byterun/interp.c @@ -15,6 +15,7 @@ #include "alloc.h" #include "callback.h" +#include "debugger.h" #include "fail.h" #include "fix_code.h" #include "instrtrace.h" @@ -65,6 +66,24 @@ sp is a local copy of the global variable extern_sp. */ #define Setup_for_c_call { *--sp = env; extern_sp = sp; } #define Restore_after_c_call { sp = extern_sp; env = *sp++; } +/* Debugger interface */ + +#define Setup_for_debugger \ + { sp -= 4; \ + sp[0] = accu; sp[1] = (value)(pc - 1); \ + sp[2] = env; sp[3] = Val_long(extra_args); \ + extern_sp = sp; } +#define Restore_after_debugger { sp += 4; } + +#ifdef THREADED_CODE +#define Restart_curr_instr \ + goto *(jumptable[saved_code[pc - 1 - start_code]]) +#else +#define Restart_curr_instr \ + curr_instr = saved_code[pc - 1 - start_code]; \ + goto dispatch_instr +#endif + /* Register optimization. Many compilers underestimate the use of the local variables representing the abstract machine registers, and don't put them in hardware registers, @@ -133,6 +152,7 @@ value interprete(prog, prog_size) int initial_callback_depth; struct longjmp_buffer raise_buf; value * modify_dest, modify_newval; + opcode_t curr_instr; #ifdef THREADED_CODE static void * jumptable[] = { @@ -140,11 +160,15 @@ value interprete(prog, prog_size) }; #endif + if (prog == NULL) { /* Interpreter is initializing */ #ifdef THREADED_CODE - if (prog[0] <= STOP) { instr_table = jumptable; - thread_code(prog, prog_size); +#endif + return Val_unit; } + +#ifdef THREADED_CODE + if (prog[0] <= STOP) thread_code(prog, prog_size); #endif sp = extern_sp; @@ -160,6 +184,7 @@ value interprete(prog, prog_size) local_roots = initial_local_roots; callback_depth = initial_callback_depth; accu = exn_bucket; + sp = extern_sp; goto raise_exception; } external_raise = &raise_buf; @@ -182,7 +207,9 @@ value interprete(prog, prog_size) Assert(sp >= stack_low); Assert(sp <= stack_high); #endif - switch(*pc++) { + curr_instr = *pc++; + dispatch_instr: + switch(curr_instr) { #endif /* Basic stack operations */ @@ -657,8 +684,13 @@ value interprete(prog, prog_size) sp += 4; Next; - Instruct(RAISE): /* arg */ + Instruct(RAISE): raise_exception: + if (trapsp >= trap_barrier) { + Setup_for_debugger; + debugger(TRAP_BARRIER); + Restore_after_debugger; + } sp = trapsp; if (sp >= stack_high - initial_sp_offset) { exn_bucket = accu; @@ -863,13 +895,27 @@ value interprete(prog, prog_size) accu = Lookup(sp[0], accu); Next; -/* Machine control */ +/* Debugging and machine control */ Instruct(STOP): external_raise = initial_external_raise; extern_sp = sp; return accu; + Instruct(EVENT): + if (--event_count == 0) { + Setup_for_debugger; + debugger(EVENT_COUNT); + Restore_after_debugger; + } + Restart_curr_instr; + + Instruct(BREAK): + Setup_for_debugger; + debugger(BREAKPOINT); + Restore_after_debugger; + Restart_curr_instr; + #ifndef THREADED_CODE default: fatal_error_arg("Fatal error: bad opcode (%lx)\n", (char *) *(pc-1)); diff --git a/byterun/stacks.c b/byterun/stacks.c index 40aba8cdd..cc059b61f 100644 --- a/byterun/stacks.c +++ b/byterun/stacks.c @@ -25,6 +25,7 @@ value * stack_high; value * stack_threshold; value * extern_sp; value * trapsp; +value * trap_barrier; value global_data; void init_stack() @@ -34,6 +35,7 @@ void init_stack() stack_threshold = stack_low + Stack_threshold / sizeof (value); extern_sp = stack_high; trapsp = stack_high; + trap_barrier = stack_high + 1; } void realloc_stack() @@ -61,6 +63,7 @@ void realloc_stack() (stack_high - extern_sp) * sizeof(value)); stat_free((char *) stack_low); trapsp = (value *) shift(trapsp); + trap_barrier = (value *) shift(trap_barrier); for (p = trapsp; p < new_high; p = Trap_link(p)) Trap_link(p) = (value *) shift(Trap_link(p)); stack_low = new_low; diff --git a/byterun/stacks.h b/byterun/stacks.h index 637fc16d6..a695f3243 100644 --- a/byterun/stacks.h +++ b/byterun/stacks.h @@ -26,6 +26,7 @@ extern value * stack_high; extern value * stack_threshold; extern value * extern_sp; extern value * trapsp; +extern value * trap_barrier; #define Trap_pc(tp) (((code_t *)(tp))[0]) #define Trap_link(tp) (((value **)(tp))[1]) diff --git a/byterun/startup.c b/byterun/startup.c index 7d611d642..ff31db569 100644 --- a/byterun/startup.c +++ b/byterun/startup.c @@ -22,6 +22,7 @@ #include <unistd.h> #endif #include "alloc.h" +#include "debugger.h" #include "exec.h" #include "fail.h" #include "fix_code.h" @@ -226,15 +227,14 @@ void caml_main(argv) verbose_init); init_stack(); init_atoms(); + /* Initialize the interpreter */ + interprete(NULL, 0); + /* Initialize the debugger, if needed */ + debugger_init(); /* Load the code */ lseek(fd, - (long) (TRAILER_SIZE + trail.code_size + trail.data_size + trail.symbol_size + trail.debug_size), 2); - start_code = (code_t) stat_alloc(trail.code_size); - if (read(fd, (char *) start_code, trail.code_size) != trail.code_size) - fatal_error("Fatal error: truncated bytecode file.\n"); -#ifdef ARCH_BIG_ENDIAN - fixup_endianness(start_code, trail.code_size); -#endif + load_code(fd, trail.code_size); /* Load the globals */ { struct channel * chan; Push_roots(r, 1); @@ -246,10 +246,13 @@ void caml_main(argv) } /* Ensure that the globals are in the major heap. */ oldify(global_data, &global_data); - /* Run the code */ + /* Record the command-line arguments */ sys_init(argv + pos); + /* Execute the program */ + debugger(PROGRAM_START); interprete(start_code, trail.code_size); } else { + debugger(UNCAUGHT_EXC); fatal_uncaught_exception(exn_bucket); } } diff --git a/byterun/sys.c b/byterun/sys.c index 97897d26e..313912706 100644 --- a/byterun/sys.c +++ b/byterun/sys.c @@ -27,6 +27,7 @@ #include <unistd.h> #endif #include "alloc.h" +#include "debugger.h" #include "fail.h" #include "instruct.h" #include "mlvalues.h" @@ -90,6 +91,7 @@ void sys_error(arg) value sys_exit(retcode) /* ML */ value retcode; { + debugger(PROGRAM_EXIT); #ifdef HAS_UI ui_exit(Int_val(retcode)); #else diff --git a/driver/main.ml b/driver/main.ml index d695cfecf..ab39a4053 100644 --- a/driver/main.ml +++ b/driver/main.ml @@ -60,6 +60,7 @@ let main () = "-ccopt", Arg.String(fun s -> ccopts := s :: !ccopts), "<opt> Pass option <opt> to the C compiler and linker"; "-custom", Arg.Set custom_runtime, " Link in custom mode"; + "-g", Arg.Set debug, " Save debugging information"; "-i", Arg.Set print_types, " Print the types"; "-I", Arg.String(fun dir -> include_dirs := dir :: !include_dirs), "<dir> Add <dir> to the list of include directories"; diff --git a/typing/env.ml b/typing/env.ml index d52e42464..9cb106d74 100644 --- a/typing/env.ml +++ b/typing/env.ml @@ -29,6 +29,16 @@ type error = exception Error of error +type summary = + Env_empty + | Env_value of summary * Ident.t * value_description + | Env_type of summary * Ident.t * type_declaration + | Env_exception of summary * Ident.t * exception_declaration + | Env_module of summary * Ident.t * module_type + | Env_modtype of summary * Ident.t * modtype_declaration + | Env_class of summary * Ident.t * class_type + | Env_open of summary * Path.t + type t = { values: (Path.t * value_description) Ident.tbl; constrs: constructor_description Ident.tbl; @@ -37,7 +47,8 @@ type t = { modules: (Path.t * module_type) Ident.tbl; modtypes: (Path.t * modtype_declaration) Ident.tbl; components: (Path.t * module_components) Ident.tbl; - classes: (Path.t * class_type) Ident.tbl + classes: (Path.t * class_type) Ident.tbl; + summary: summary } and module_components = @@ -66,7 +77,8 @@ let empty = { values = Ident.empty; constrs = Ident.empty; labels = Ident.empty; types = Ident.empty; modules = Ident.empty; modtypes = Ident.empty; - components = Ident.empty; classes = Ident.empty } + components = Ident.empty; classes = Ident.empty; + summary = Env_empty } (* Persistent structure descriptions *) @@ -174,6 +186,27 @@ and find_type = find (fun env -> env.types) (fun sc -> sc.comp_types) and find_modtype = find (fun env -> env.modtypes) (fun sc -> sc.comp_modtypes) and find_class = find (fun env -> env.classes) (fun sc -> sc.comp_classes) +let find_module path env = + match path with + Pident id -> + begin try + let (p, data) = Ident.find_same id env.modules + in data + with Not_found -> + if Ident.persistent id + then Tmty_signature((find_pers_struct (Ident.name id)).ps_sig) + else raise Not_found + end + | Pdot(p, s, pos) -> + begin match find_module_descr p env with + Structure_comps c -> + let (data, pos) = Tbl.find s c.comp_modules in data + | Functor_comps f -> + raise Not_found + end + | Papply(p1, p2) -> + raise Not_found (* not right *) + (* Lookup by name *) let rec lookup_module_descr lid env = @@ -432,7 +465,8 @@ and store_value id path decl env = modules = env.modules; modtypes = env.modtypes; components = env.components; - classes = env.classes } + classes = env.classes; + summary = Env_value(env.summary, id, decl) } and store_type id path info env = { values = env.values; @@ -452,7 +486,8 @@ and store_type id path info env = modules = env.modules; modtypes = env.modtypes; components = env.components; - classes = env.classes } + classes = env.classes; + summary = Env_type(env.summary, id, info) } and store_exception id path decl env = { values = env.values; @@ -462,7 +497,8 @@ and store_exception id path decl env = modules = env.modules; modtypes = env.modtypes; components = env.components; - classes = env.classes } + classes = env.classes; + summary = Env_exception(env.summary, id, decl) } and store_module id path mty env = { values = env.values; @@ -474,7 +510,8 @@ and store_module id path mty env = components = Ident.add id (path, components_of_module env Subst.identity path mty) env.components; - classes = env.classes } + classes = env.classes; + summary = Env_module(env.summary, id, mty) } and store_modtype id path info env = { values = env.values; @@ -484,7 +521,8 @@ and store_modtype id path info env = modules = env.modules; modtypes = Ident.add id (path, info) env.modtypes; components = env.components; - classes = env.classes } + classes = env.classes; + summary = Env_modtype(env.summary, id, info) } and store_components id path comps env = { values = env.values; @@ -494,7 +532,8 @@ and store_components id path comps env = modules = env.modules; modtypes = env.modtypes; components = Ident.add id (path, comps) env.components; - classes = env.classes } + classes = env.classes; + summary = env.summary } and store_class id path desc env = { values = env.values; @@ -504,7 +543,8 @@ and store_class id path desc env = modules = env.modules; modtypes = env.modtypes; components = env.components; - classes = Ident.add id (path, desc) env.classes } + classes = Ident.add id (path, desc) env.classes; + summary = Env_class(env.summary, id, desc) } (* Memoized function to compute the components of a functor application in a path. *) @@ -580,28 +620,38 @@ let open_signature root sg env = (* First build the paths and substitution *) let (pl, sub) = prefix_idents root 0 Subst.identity sg in (* Then enter the components in the environment after substitution *) - List.fold_left2 - (fun env item p -> - match item with - Tsig_value(id, decl) -> - store_value (Ident.hide id) p - (Subst.value_description sub decl) env - | Tsig_type(id, decl) -> - store_type (Ident.hide id) p - (Subst.type_declaration sub decl) env - | Tsig_exception(id, decl) -> - store_exception (Ident.hide id) p - (Subst.exception_declaration sub decl) env - | Tsig_module(id, mty) -> - store_module (Ident.hide id) p (Subst.modtype sub mty) env - | Tsig_modtype(id, decl) -> - store_modtype (Ident.hide id) p - (Subst.modtype_declaration sub decl) env - | Tsig_class(id, decl) -> - store_class (Ident.hide id) p - (Subst.class_type sub decl) env) - env sg pl - + let newenv = + List.fold_left2 + (fun env item p -> + match item with + Tsig_value(id, decl) -> + store_value (Ident.hide id) p + (Subst.value_description sub decl) env + | Tsig_type(id, decl) -> + store_type (Ident.hide id) p + (Subst.type_declaration sub decl) env + | Tsig_exception(id, decl) -> + store_exception (Ident.hide id) p + (Subst.exception_declaration sub decl) env + | Tsig_module(id, mty) -> + store_module (Ident.hide id) p (Subst.modtype sub mty) env + | Tsig_modtype(id, decl) -> + store_modtype (Ident.hide id) p + (Subst.modtype_declaration sub decl) env + | Tsig_class(id, decl) -> + store_class (Ident.hide id) p + (Subst.class_type sub decl) env) + env sg pl in + { values = newenv.values; + constrs = newenv.constrs; + labels = newenv.labels; + types = newenv.types; + modules = newenv.modules; + modtypes = newenv.modtypes; + components = newenv.components; + classes = newenv.classes; + summary = Env_open(env.summary, root) } + (* Open a signature from a file *) let open_pers_signature name env = @@ -639,6 +689,10 @@ let initial = Predef.build_initial_env add_type add_exception empty let imported_units() = !imported_units +(* Return the environment summary *) + +let summary env = env.summary + (* Error report *) let report_error = function diff --git a/typing/env.mli b/typing/env.mli index fe12606ef..3fa55f24d 100644 --- a/typing/env.mli +++ b/typing/env.mli @@ -24,6 +24,7 @@ val initial: t val find_value: Path.t -> t -> value_description val find_type: Path.t -> t -> type_declaration +val find_module: Path.t -> t -> module_type val find_modtype: Path.t -> t -> modtype_declaration val find_class: Path.t -> t -> class_type @@ -84,6 +85,21 @@ val save_signature: signature -> string -> string -> Digest.t val imported_units: unit -> (string * Digest.t) list +(* Summaries -- compact representation of an environment, to be + exported in debugging information. *) + +type summary = + Env_empty + | Env_value of summary * Ident.t * value_description + | Env_type of summary * Ident.t * type_declaration + | Env_exception of summary * Ident.t * exception_declaration + | Env_module of summary * Ident.t * module_type + | Env_modtype of summary * Ident.t * modtype_declaration + | Env_class of summary * Ident.t * class_type + | Env_open of summary * Path.t + +val summary: t -> summary + (* Error report *) type error = diff --git a/utils/clflags.ml b/utils/clflags.ml index 160f59117..6ac450029 100644 --- a/utils/clflags.ml +++ b/utils/clflags.ml @@ -23,6 +23,7 @@ and object_name = ref ("camlprog" ^ Config.ext_obj) (* -o *) and include_dirs = ref ([] : string list)(* -I *) and print_types = ref false (* -i *) and make_archive = ref false (* -a *) +and debug = ref false (* -g *) and fast = ref false (* -unsafe *) and link_everything = ref false (* -linkall *) and custom_runtime = ref false (* -custom *) |