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 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
|
(****************************************************************************)
(* the diy toolsuite *)
(* *)
(* Jade Alglave, University College London, UK. *)
(* Luc Maranget, INRIA Paris-Rocquencourt, France. *)
(* *)
(* Copyright 2010-present Institut National de Recherche en Informatique et *)
(* en Automatique and the authors. All rights reserved. *)
(* *)
(* This software is governed by the CeCILL-B license under French law and *)
(* abiding by the rules of distribution of free software. You can use, *)
(* modify and/ or redistribute the software under the terms of the CeCILL-B *)
(* license as circulated by CEA, CNRS and INRIA at the following URL *)
(* "http://www.cecill.info". We also give a copy in LICENSE.txt. *)
(****************************************************************************)
(**************)
(* Digest Env *)
(**************)
type hinfo = { hash : string ; filename : string; }
type env = hinfo StringMap.t
exception Seen
let check_env env name filename hash =
try
let ohash = StringMap.find name env in
if hash = ohash.hash then raise Seen
else Warn.user_error "Different hashes for test %s (previous file %s)"
name ohash.filename
with Not_found ->
StringMap.add name {hash;filename;} env
(***************************)
(* Digest of initial state *)
(***************************)
open Printf
module type PteVal = sig
val hash_pteval : ParsedPteVal.t -> string
end
module HashUtils(P:PteVal) = struct
(* Backward compatible identifier and value printing functions *)
open MiscParser
let dump_location = function
| Location_reg (i,r) -> Printf.sprintf "%i:%s" i r
| Location_sreg s -> s
| Location_global v -> ParsedConstant.pp_v_old v
and pp_v v =
let open Constant in
match v with
| PteVal p -> P.hash_pteval p
| _ -> ParsedConstant.pp_v_old v
let digest_init debug init =
let open TestType in
let init =
List.sort
(fun (loc1,(t1,v1)) (loc2,(t2,v2)) ->
match location_compare loc1 loc2 with
| 0 ->
if
ParsedConstant.compare v1 v2 <> 0 &&
compare t1 t2 <> 0
then begin
Warn.fatal
"Location %s non-unique in init state"
(dump_location loc1)
end ;
0
| c -> c)
init in
let init =
Misc.rem_dups
(fun (loc1,_) (loc2,_) -> location_compare loc1 loc2 = 0)
init in
(* We perform explicit printing to be more robust
against pretty printer changes *)
let pp =
(String.concat "; "
(List.map
(fun (loc,(t,v)) ->
match t with
| TyDef ->
sprintf "%s=%s"
(dump_location loc) (pp_v v)
| TyDefPointer ->
sprintf "*%s=%s"
(dump_location loc) (pp_v v)
| Ty t ->
sprintf "%s %s=%s" t
(dump_location loc) (pp_v v)
| Atomic t ->
sprintf "_Atomic %s %s=%s" t
(dump_location loc) (pp_v v)
| Pointer t ->
sprintf "%s *%s=%s" t
(dump_location loc) (pp_v v)
| TyArray (t,sz) ->
sprintf "%s %s[%i]" t (dump_location loc) sz)
init)) in
debug "INIT" pp ;
Digest.string pp
end
module NoPteValHU = HashUtils(struct let hash_pteval _ = assert false end)
let digest_init debug init = NoPteValHU.digest_init debug init
let key_compare k1 k2 =
if MiscParser.key_match k1 k2 then
Warn.user_error "Duplicated meta-data on key %s\n" k2 ;
String.compare k1 k2
let do_digest_info verbose i =
let i = List.stable_sort (fun (k1,_) (k2,_) -> key_compare k1 k2) i in
let ds =
List.fold_left
(fun ds (k,i) ->
if MiscParser.digest_mem k then
sprintf "%s=%s" (Misc.lowercase k) i::ds
else ds)
[] i in
match ds with
| [] -> "" (* Backward compatibility *)
| _::_ ->
let i = String.concat "" ds in
let d = Digest.string i in
if verbose > 0 then
eprintf "INFO:\n%s\nDigest=\"%s\"\n\n"
i (Digest.to_hex d) ;
d
let digest_info = do_digest_info 0
(**********)
(* Digest *)
(**********)
module Make(A:ArchBase.S)
= struct
type init = MiscParser.state
type prog = (MiscParser.proc * A.pseudo list) list
type rlocations = MiscParser.RLocSet.t
let verbose = 0
let debug tag s =
if verbose > 0 then
eprintf "%s:\n%s\nDigest=\"%s\"\n\n"
tag s (Digest.to_hex (Digest.string s))
else ()
let digest_info = do_digest_info verbose
module HU=HashUtils(A)
let digest_init init = HU.digest_init debug init
(* Code digest *)
let all_labels =
List.fold_left
(fun k (_,code) ->
List.fold_left
(A.fold_labels (fun k lbl -> StringSet.add lbl k))
k code)
StringSet.empty
let change_labels f =
List.map
(fun (p,code) ->
let code = List.map (A.map_labels f) code in
p,code)
let refresh_labels pref prog =
let lbls = all_labels prog in
let next = ref 0 in
let env =
StringSet.fold
(fun lbl env ->
let new_lbl = sprintf "L%s%02i" pref !next in
incr next ;
StringMap.add lbl new_lbl env)
lbls StringMap.empty in
change_labels
(fun lbl ->
try StringMap.find lbl env
with Not_found -> assert false)
prog
let norm_labels = refresh_labels ""
let norm_instructions =
List.map
(fun (p,code) ->
let code = List.map (A.pseudo_map A.norm_ins) code in
p,code)
let dump_pseudo =
let rec dump_rec p k = match p with
| A.Nop -> k
| A.Instruction i -> A.dump_instruction_hash i::k
| A.Label (lbl,p) -> sprintf "%s:" lbl::dump_rec p k
| A.Symbolic s -> sprintf "codevar:%s" s::k
| A.Macro _ -> assert false (* applied after macro expansion *) in
fun (_,ps) ->
List.fold_right dump_rec ps []
let digest_code code =
(* Because I have introduced 64bits instructions,
which we can remap to 32bits ones... *)
let code = norm_instructions code in
(* Because labels may change, when generated by macro
expansion *)
let code = norm_labels code in
(* Just pretty_print code in a normalized way *)
let code = List.map dump_pseudo code in
let pp = Misc.string_of_prog code in
debug "CODE" pp ;
Digest.string pp
(* Observed locations digest *)
let digest_observed locs =
let locs = MiscParser.RLocSet.elements locs in
let pp =
String.concat "; "
(List.map (ConstrGen.dump_rloc HU.dump_location) locs) in
debug "LOCS" pp ;
Digest.string pp
let digest info init code observed =
Digest.to_hex
(Digest.string
(String.concat ""
[digest_info info; digest_init init;
digest_code code; digest_observed observed;]))
end
|