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
(* SPDX-License-Identifier: AGPL-3.0-or-later *)
(* Copyright © 2021-2024 OCamlPro *)
(* Written by the Owi programmers *)

module MakeP
    (Memory : Symbolic_memory_intf.S)
    (Thread : Thread.S with type Memory.collection = Memory.collection)
    (Choice :
      Choice_intf.Complete
        with module V := Symbolic_value
         and type thread := Thread.t) =
struct
  module Value = Symbolic_value
  module Choice = Choice
  module Extern_func = Concrete_value.Make_extern_func (Value) (Choice) (Memory)
  module Global = Symbolic_global
  module Table = Symbolic_table

  type thread = Thread.t

  let select (c : Value.vbool) ~(if_true : Value.t) ~(if_false : Value.t) :
    Value.t Choice.t =
    match (if_true, if_false) with
    | I32 if_true, I32 if_false ->
      Choice.return (Value.I32 (Value.Bool.select_expr c ~if_true ~if_false))
    | I64 if_true, I64 if_false ->
      Choice.return (Value.I64 (Value.Bool.select_expr c ~if_true ~if_false))
    | F32 if_true, F32 if_false ->
      Choice.return (Value.F32 (Value.Bool.select_expr c ~if_true ~if_false))
    | F64 if_true, F64 if_false ->
      Choice.return (Value.F64 (Value.Bool.select_expr c ~if_true ~if_false))
    | Ref _, Ref _ ->
      let open Choice in
      let+ b = select c in
      if b then if_true else if_false
    | _, _ -> assert false

  module Elem = struct
    type t = Link_env.elem

    let get (elem : t) i : Value.ref_value =
      match elem.value.(i) with Funcref f -> Funcref f | _ -> assert false

    let size (elem : t) = Array.length elem.value
  end

  module Memory = struct
    include Memory

    let load_8_s m a = Choice.lift_mem @@ load_8_s m a

    let load_8_u m a = Choice.lift_mem @@ load_8_u m a

    let load_16_s m a = Choice.lift_mem @@ load_16_s m a

    let load_16_u m a = Choice.lift_mem @@ load_16_u m a

    let load_32 m a = Choice.lift_mem @@ load_32 m a

    let load_64 m a = Choice.lift_mem @@ load_64 m a

    let store_8 m ~addr v = Choice.lift_mem @@ store_8 m ~addr v

    let store_16 m ~addr v = Choice.lift_mem @@ store_16 m ~addr v

    let store_32 m ~addr v = Choice.lift_mem @@ store_32 m ~addr v

    let store_64 m ~addr v = Choice.lift_mem @@ store_64 m ~addr v
  end

  module Data = struct
    type t = Link_env.data

    let value data = data.Link_env.value
  end

  module Env = struct
    type t = Extern_func.extern_func Link_env.t

    type t' = Env_id.t

    let get_memory env id =
      let orig_mem = Link_env.get_memory env id in
      let f (t : thread) =
        let memories = Thread.memories t in
        Memory.get_memory (Link_env.id env) orig_mem memories id
      in
      Choice.with_thread f

    let get_func = Link_env.get_func

    let get_extern_func = Link_env.get_extern_func

    let get_table (env : t) i : Table.t Choice.t =
      let orig_table = Link_env.get_table env i in
      let f (t : thread) =
        let tables = Thread.tables t in
        Symbolic_table.get_table (Link_env.id env) orig_table tables i
      in
      Choice.with_thread f

    let get_elem env i = Link_env.get_elem env i

    let get_data env n =
      let data = Link_env.get_data env n in
      Choice.return data

    let get_global (env : t) i : Global.t Choice.t =
      let orig_global = Link_env.get_global env i in
      let f (t : thread) =
        let globals = Thread.globals t in
        Symbolic_global.get_global (Link_env.id env) orig_global globals i
      in
      Choice.with_thread f

    let drop_elem _ =
      (* TODO *)
      ()

    let drop_data = Link_env.drop_data
  end

  module Module_to_run = struct
    (** runnable module *)
    type t =
      { id : string option
      ; env : Env.t
      ; to_run : Types.binary Types.expr list
      }

    let env (t : t) = t.env

    let id (t : t) = t.id

    let to_run (t : t) = t.to_run
  end
end

module P =
  MakeP [@inlined hint] (Symbolic_memory_concretizing) (Thread_with_memory)
    (Symbolic_choice_with_memory)
module M =
  MakeP [@inlined hint] (Symbolic_memory_concretizing) (Thread_with_memory)
    (Symbolic_choice_minimalist)

let convert_module_to_run (m : 'f Link.module_to_run) =
  P.Module_to_run.{ id = m.id; env = m.env; to_run = m.to_run }

let convert_module_to_run_minimalist (m : 'f Link.module_to_run) =
  M.Module_to_run.{ id = m.id; env = m.env; to_run = m.to_run }