File: testHash.ml

package info (click to toggle)
herdtools7 7.58-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,732 kB
  • sloc: ml: 128,583; ansic: 3,827; makefile: 670; python: 407; sh: 212; awk: 14
file content (254 lines) | stat: -rw-r--r-- 7,723 bytes parent folder | download
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