summaryrefslogtreecommitdiff
path: root/checker/votour.ml
diff options
context:
space:
mode:
Diffstat (limited to 'checker/votour.ml')
-rw-r--r--checker/votour.ml140
1 files changed, 122 insertions, 18 deletions
diff --git a/checker/votour.ml b/checker/votour.ml
index 7c954d6f..4aecb28f 100644
--- a/checker/votour.ml
+++ b/checker/votour.ml
@@ -21,32 +21,91 @@ sig
type obj
val input : in_channel -> obj
val repr : obj -> obj repr
- val size : int list -> int
+ val size : obj -> int
end
-module Repr : S =
+module ReprObj : S =
struct
- type obj = Obj.t
+ type obj = Obj.t * int list
let input chan =
let obj = input_value chan in
let () = CObj.register_shared_size obj in
- obj
+ (obj, [])
- let repr obj =
+ let repr (obj, pos) =
if Obj.is_block obj then
let tag = Obj.tag obj in
if tag = Obj.string_tag then STRING (Obj.magic obj)
else if tag < Obj.no_scan_tag then
- let data = Obj.dup obj in
- let () = Obj.set_tag data 0 in
+ let init i = (Obj.field obj i, i :: pos) in
+ let data = Array.init (Obj.size obj) init in
BLOCK (tag, Obj.magic data)
else OTHER
else INT (Obj.magic obj)
- let size p = CObj.shared_size_of_pos p
+ let size (_, p) = CObj.shared_size_of_pos p
+end
+
+module ReprMem : S =
+struct
+ open Analyze
+
+ type obj = data
+
+ let memory = ref [||]
+ let sizes = ref [||]
+ (** size, in words *)
+
+ let ws = Sys.word_size / 8
+
+ let rec init_size seen = function
+ | Int _ | Atm _ | Fun _ -> 0
+ | Ptr p ->
+ if seen.(p) then 0
+ else
+ let () = seen.(p) <- true in
+ match (!memory).(p) with
+ | Struct (tag, os) ->
+ let fold accu o = accu + 1 + init_size seen o in
+ let size = Array.fold_left fold 1 os in
+ let () = (!sizes).(p) <- size in
+ size
+ | String s ->
+ let size = 2 + (String.length s / ws) in
+ let () = (!sizes).(p) <- size in
+ size
+
+ let size = function
+ | Int _ | Atm _ | Fun _ -> 0
+ | Ptr p -> (!sizes).(p)
+
+ let repr = function
+ | Int i -> INT i
+ | Atm t -> BLOCK (t, [||])
+ | Fun _ -> OTHER
+ | Ptr p ->
+ match (!memory).(p) with
+ | Struct (tag, os) -> BLOCK (tag, os)
+ | String s -> STRING s
+
+ let input ch =
+ let obj, mem = parse_channel ch in
+ let () = memory := mem in
+ let () = sizes := Array.make (Array.length mem) (-1) in
+ let seen = Array.make (Array.length mem) false in
+ let _ = init_size seen obj in
+ obj
+
end
+module Visit (Repr : S) :
+sig
+ val init : unit -> unit
+ val visit : Values.value -> Repr.obj -> int list -> unit
+end =
+struct
+
(** Name of a value *)
let rec get_name ?(extra=false) = function
@@ -92,7 +151,7 @@ let rec get_details v o = match v, Repr.repr o with
let node_info (v,o,p) =
get_name ~extra:true v ^ get_details v o ^
- " (size "^ string_of_int (Repr.size p)^"w)"
+ " (size "^ string_of_int (Repr.size o)^"w)"
(** Children of a block : type, object, position.
For lists, we collect all elements of the list at once *)
@@ -201,14 +260,49 @@ let rec visit v o pos =
| Failure "forbidden" -> let info = pop () in visit info.typ info.obj info.pos
| Failure _ | Invalid_argument _ -> visit v o pos
+end
+
(** Loading the vo *)
+type header = {
+ magic : string;
+ (** Magic number of the marshaller *)
+ length : int;
+ (** Size on disk in bytes *)
+ size32 : int;
+ (** Size in words when loaded on 32-bit systems *)
+ size64 : int;
+ (** Size in words when loaded on 64-bit systems *)
+ objects : int;
+ (** Number of blocks defined in the marshalled structure *)
+}
+
+let dummy_header = {
+ magic = "\000\000\000\000";
+ length = 0;
+ size32 = 0;
+ size64 = 0;
+ objects = 0;
+}
+
+let parse_header chan =
+ let magic = String.create 4 in
+ let () = for i = 0 to 3 do magic.[i] <- input_char chan done in
+ let length = input_binary_int chan in
+ let objects = input_binary_int chan in
+ let size32 = input_binary_int chan in
+ let size64 = input_binary_int chan in
+ { magic; length; size32; size64; objects }
+
type segment = {
name : string;
mutable pos : int;
typ : Values.value;
+ mutable header : header;
}
+let make_seg name typ = { name; typ; pos = 0; header = dummy_header }
+
let visit_vo f =
Printf.printf "\nWelcome to votour !\n";
Printf.printf "Enjoy your guided tour of a Coq .vo or .vi file\n";
@@ -216,12 +310,19 @@ let visit_vo f =
Printf.printf
"At prompt, <n> enters the <n>-th child, u goes up 1 level, x exits\n\n%!";
let segments = [|
- {name="library"; pos=0; typ=Values.v_lib};
- {name="univ constraints of opaque proofs"; pos=0;typ=Values.v_univopaques};
- {name="discharging info"; pos=0; typ=Opt Any};
- {name="STM tasks"; pos=0; typ=Opt Values.v_stm_seg};
- {name="opaque proofs"; pos=0; typ=Values.v_opaques};
+ make_seg "summary" Values.v_libsum;
+ make_seg "library" Values.v_lib;
+ make_seg "univ constraints of opaque proofs" Values.v_univopaques;
+ make_seg "discharging info" (Opt Any);
+ make_seg "STM tasks" (Opt Values.v_stm_seg);
+ make_seg "opaque proofs" Values.v_opaques;
|] in
+ let repr =
+ if Sys.word_size = 64 then (module ReprMem : S) else (module ReprObj : S)
+ (** On 32-bit machines, representation may exceed the max size of arrays *)
+ in
+ let module Repr = (val repr : S) in
+ let module Visit = Visit(Repr) in
while true do
let ch = open_in_bin f in
let magic = input_binary_int ch in
@@ -229,21 +330,24 @@ let visit_vo f =
for i=0 to Array.length segments - 1 do
let pos = input_binary_int ch in
segments.(i).pos <- pos_in ch;
+ let header = parse_header ch in
+ segments.(i).header <- header;
seek_in ch pos;
ignore(Digest.input ch);
done;
Printf.printf "The file has %d segments, choose the one to visit:\n"
(Array.length segments);
- Array.iteri (fun i { name; pos } ->
- Printf.printf " %d: %s, starting at byte %d\n" i name pos)
+ Array.iteri (fun i { name; pos; header } ->
+ let size = if Sys.word_size = 64 then header.size64 else header.size32 in
+ Printf.printf " %d: %s, starting at byte %d (size %iw)\n" i name pos size)
segments;
Printf.printf "# %!";
let l = read_line () in
let seg = int_of_string l in
seek_in ch segments.(seg).pos;
let o = Repr.input ch in
- let () = init () in
- visit segments.(seg).typ o []
+ let () = Visit.init () in
+ Visit.visit segments.(seg).typ o []
done
let main =