Theory Wasm_Base_Defs

section ‹WebAssembly Base Definitions›

theory Wasm_Base_Defs imports Wasm_Ast Wasm_Type_Abs begin

instantiation i32 :: wasm_int begin instance .. end
instantiation i64 :: wasm_int begin instance .. end
instantiation f32 :: wasm_float begin instance .. end
instantiation f64 :: wasm_float begin instance .. end

consts
  (* inter-type conversions *)
  (* float to i32 *)
  ui32_trunc_f32 :: "f32  i32 option"
  si32_trunc_f32 :: "f32  i32 option"
  ui32_trunc_f64 :: "f64  i32 option"
  si32_trunc_f64 :: "f64  i32 option"
  (* float to i64 *)
  ui64_trunc_f32 :: "f32  i64 option"
  si64_trunc_f32 :: "f32  i64 option"
  ui64_trunc_f64 :: "f64  i64 option"
  si64_trunc_f64 :: "f64  i64 option"
  (* int to f32 *)
  f32_convert_ui32 :: "i32  f32"
  f32_convert_si32 :: "i32  f32"
  f32_convert_ui64 :: "i64  f32"
  f32_convert_si64 :: "i64  f32"
  (* int to f64 *)
  f64_convert_ui32 :: "i32  f64"
  f64_convert_si32 :: "i32  f64"
  f64_convert_ui64 :: "i64  f64"
  f64_convert_si64 :: "i64  f64"
  (* intra-{int/float} conversions *)
  wasm_wrap :: "i64  i32"
  wasm_extend_u :: "i32  i64"
  wasm_extend_s :: "i32  i64"
  wasm_demote :: "f64  f32"
  wasm_promote :: "f32  f64"
  (* boolean encoding *)
  serialise_i32 :: "i32  bytes"
  serialise_i64 :: "i64  bytes"
  serialise_f32 :: "f32  bytes"
  serialise_f64 :: "f64  bytes"
  wasm_bool :: "bool  i32"
  int32_minus_one :: i32

  (* memory *)
definition mem_size :: "mem  nat" where
  "mem_size m = length (Rep_mem m)"

definition mem_grow :: "mem  nat  mem" where
  "mem_grow m n = mem_append m (bytes_replicate (n * 64000) 0)"

definition load :: "mem  nat  off  nat  bytes option" where
  "load m n off l = (if (mem_size m  (n+off+l))
                       then Some (read_bytes m (n+off) l)
                       else None)"

definition sign_extend :: "sx  nat  bytes  bytes" where
  "sign_extend sx l bytes = (let msb = msb (msbyte bytes) in
                          let byte = (case sx of U  0 | S  if msb then -1 else 0) in
                          bytes_takefill byte l bytes)"

definition load_packed :: "sx  mem  nat  off  nat  nat  bytes option" where
  "load_packed sx m n off lp l = map_option (sign_extend sx l) (load m n off lp)"

definition store :: "mem  nat  off  bytes  nat  mem option" where
  "store m n off bs l = (if (mem_size m  (n+off+l))
                          then Some (write_bytes m (n+off) (bytes_takefill 0 l bs))
                          else None)"

definition store_packed :: "mem  nat  off  bytes  nat  mem option" where
  "store_packed = store"

consts
  wasm_deserialise :: "bytes  t  v"
  (* host *)
  host_apply :: "s  tf  host  v list  host_state  (s × v list) option"

definition typeof :: " v  t" where
  "typeof v = (case v of
                 ConstInt32 _  T_i32
               | ConstInt64 _  T_i64
               | ConstFloat32 _  T_f32
               | ConstFloat64 _  T_f64)"

definition option_projl :: "('a × 'b) option  'a option" where
  "option_projl x = map_option fst x"

definition option_projr :: "('a × 'b) option  'b option" where
  "option_projr x = map_option snd x"

definition t_length :: "t  nat" where
 "t_length t = (case t of
                  T_i32  4
                | T_i64  8
                | T_f32  4
                | T_f64  8)"

definition tp_length :: "tp  nat" where
 "tp_length tp = (case tp of
                 Tp_i8  1
               | Tp_i16  2
               | Tp_i32  4)"

definition is_int_t :: "t  bool" where
 "is_int_t t = (case t of
                  T_i32  True
                | T_i64  True
                | T_f32  False
                | T_f64  False)"

definition is_float_t :: "t  bool" where
 "is_float_t t = (case t of
                    T_i32  False
                  | T_i64  False
                  | T_f32  True
                  | T_f64  True)"

definition is_mut :: "tg  bool" where
  "is_mut tg = (tg_mut tg = T_mut)"

definition app_unop_i :: "unop_i  'i::wasm_int  'i::wasm_int" where
  "app_unop_i iop c =
     (case iop of
     Ctz  int_ctz c
   | Clz  int_clz c
   | Popcnt  int_popcnt c)"

definition app_unop_f :: "unop_f  'f::wasm_float  'f::wasm_float" where
  "app_unop_f fop c =
                 (case fop of
                    Neg  float_neg c
                  | Abs  float_abs c
                  | Ceil  float_ceil c
                  | Floor  float_floor c
                  | Trunc  float_trunc c
                  | Nearest  float_nearest c
                  | Sqrt  float_sqrt c)"

definition app_binop_i :: "binop_i  'i::wasm_int  'i::wasm_int  ('i::wasm_int) option" where
  "app_binop_i iop c1 c2 = (case iop of
                              Add  Some (int_add c1 c2)
                            | Sub  Some (int_sub c1 c2)
                            | Mul  Some (int_mul c1 c2)
                            | Div U  int_div_u c1 c2
                            | Div S  int_div_s c1 c2
                            | Rem U  int_rem_u c1 c2
                            | Rem S  int_rem_s c1 c2
                            | And  Some (int_and c1 c2)
                            | Or  Some (int_or c1 c2)
                            | Xor  Some (int_xor c1 c2)
                            | Shl  Some (int_shl c1 c2)
                            | Shr U  Some (int_shr_u c1 c2)
                            | Shr S  Some (int_shr_s c1 c2)
                            | Rotl  Some (int_rotl c1 c2)
                            | Rotr  Some (int_rotr c1 c2))"

definition app_binop_f :: "binop_f  'f::wasm_float  'f::wasm_float  ('f::wasm_float) option" where
  "app_binop_f fop c1 c2 = (case fop of
                              Addf  Some (float_add c1 c2)
                            | Subf  Some (float_sub c1 c2)
                            | Mulf  Some (float_mul c1 c2)
                            | Divf  Some (float_div c1 c2)
                            | Min  Some (float_min c1 c2)
                            | Max  Some (float_max c1 c2)
                            | Copysign  Some (float_copysign c1 c2))"

definition app_testop_i :: "testop  'i::wasm_int  bool" where
  "app_testop_i testop c = (case testop of Eqz  int_eqz c)"

definition app_relop_i :: "relop_i  'i::wasm_int  'i::wasm_int  bool" where
  "app_relop_i rop c1 c2 = (case rop of
                              Eq  int_eq c1 c2
                            | Ne  int_ne c1 c2
                            | Lt U  int_lt_u c1 c2
                            | Lt S  int_lt_s c1 c2
                            | Gt U  int_gt_u c1 c2
                            | Gt S  int_gt_s c1 c2
                            | Le U  int_le_u c1 c2
                            | Le S  int_le_s c1 c2
                            | Ge U  int_ge_u c1 c2
                            | Ge S  int_ge_s c1 c2)"

definition app_relop_f :: "relop_f  'f::wasm_float  'f::wasm_float  bool" where
  "app_relop_f rop c1 c2 = (case rop of
                              Eqf  float_eq c1 c2
                            | Nef  float_ne c1 c2
                            | Ltf  float_lt c1 c2
                            | Gtf  float_gt c1 c2
                            | Lef  float_le c1 c2
                            | Gef  float_ge c1 c2)" 

definition types_agree :: "t  v  bool" where
  "types_agree t v = (typeof v = t)"

definition cl_type :: "cl  tf" where
  "cl_type cl = (case cl of Func_native _ tf _ _  tf | Func_host tf _  tf)"

definition rglob_is_mut :: "global  bool" where
  "rglob_is_mut g = (g_mut g = T_mut)"

definition stypes :: "s  nat  nat  tf" where
  "stypes s i j = ((types ((inst s)!i))!j)"
  
definition sfunc_ind :: "s  nat  nat  nat" where
  "sfunc_ind s i j = ((inst.funcs ((inst s)!i))!j)"

definition sfunc :: "s  nat  nat  cl" where
  "sfunc s i j = (funcs s)!(sfunc_ind s i j)"

definition sglob_ind :: "s  nat  nat  nat" where
  "sglob_ind s i j = ((inst.globs ((inst s)!i))!j)"
  
definition sglob :: "s  nat  nat  global" where
  "sglob s i j = (globs s)!(sglob_ind s i j)"

definition sglob_val :: "s  nat  nat  v" where
  "sglob_val s i j = g_val (sglob s i j)"

definition smem_ind :: "s  nat  nat option" where
  "smem_ind s i = (inst.mem ((inst s)!i))"

definition stab_s :: "s  nat  nat  cl option" where
  "stab_s s i j = (let stabinst = ((tab s)!i) in  (if (length (stabinst) > j) then (stabinst!j) else None))"

definition stab :: "s  nat  nat  cl option" where
  "stab s i j = (case (inst.tab ((inst s)!i)) of Some k => stab_s s k j | None => None)"

definition supdate_glob_s :: "s  nat  v  s" where
  "supdate_glob_s s k v = sglobs := (globs s)[k:=((globs s)!k)g_val := v]"

definition supdate_glob :: "s  nat  nat  v  s" where
  "supdate_glob s i j v = (let k = sglob_ind s i j in supdate_glob_s s k v)"

definition is_const :: "e  bool" where
  "is_const e = (case e of Basic (C _)  True | _  False)"
    
definition const_list :: "e list  bool" where
  "const_list xs = list_all is_const xs"

inductive store_extension :: "s  s  bool" where
"insts = insts'; fs = fs'; tclss = tclss'; list_all2 (λbs bs'. mem_size bs  mem_size bs') bss bss'; gs = gs' 
  store_extension s.inst = insts, s.funcs = fs, s.tab = tclss, s.mem = bss, s.globs = gs
                    s.inst = insts', s.funcs = fs', s.tab = tclss', s.mem = bss', s.globs = gs'"

abbreviation to_e_list :: "b_e list  e list" ("$* _" 60) where
  "to_e_list b_es  map Basic b_es"

abbreviation v_to_e_list :: "v list  e list" ("$$* _" 60) where
  "v_to_e_list ves  map (λv. $C v) ves"

  (* Lfilled depth thing-to-fill fill-with result *)
inductive Lfilled :: "nat  Lholed  e list  e list  bool" where
  (* "Lfill (LBase vs es') es = vs @ es @ es'" *)
  L0:"const_list vs; lholed = (LBase vs es')  Lfilled 0 lholed es (vs @ es @ es')"
  (* "Lfill (LRec vs ts es' l es'') es = vs @ [Label ts es' (Lfill l es)] @ es''" *)
| LN:"const_list vs; lholed = (LRec vs n es' l es''); Lfilled k l es lfilledk  Lfilled (k+1) lholed es (vs @ [Label n es' lfilledk] @ es'')"

  (* Lfilled depth thing-to-fill fill-with result *)
inductive Lfilled_exact :: "nat  Lholed  e list  e list  bool" where
  (* "Lfill (LBase vs es') es = vs @ es @ es'" *)
  L0:"lholed = (LBase [] [])  Lfilled_exact 0 lholed es es"
  (* "Lfill (LRec vs ts es' l es'') es = vs @ [Label ts es' (Lfill l es)] @ es''" *)
| LN:"const_list vs; lholed = (LRec vs n es' l es''); Lfilled_exact k l es lfilledk  Lfilled_exact (k+1) lholed es (vs @ [Label n es' lfilledk] @ es'')"

definition load_store_t_bounds :: "a  tp option  t  bool" where
  "load_store_t_bounds a tp t = (case tp of
                                   None  2^a  t_length t
                                 | Some tp  2^a  tp_length tp  tp_length tp < t_length t   is_int_t t)"

definition cvt_i32 :: "sx option  v  i32 option" where
  "cvt_i32 sx v = (case v of
                   ConstInt32 c  None
                 | ConstInt64 c  Some (wasm_wrap c)
                 | ConstFloat32 c  (case sx of
                                        Some U  ui32_trunc_f32 c
                                      | Some S  si32_trunc_f32 c
                                      | None  None)
                 | ConstFloat64 c  (case sx of
                                        Some U  ui32_trunc_f64 c
                                      | Some S  si32_trunc_f64 c
                                      | None  None))"

definition cvt_i64 :: "sx option  v  i64 option" where
  "cvt_i64 sx v = (case v of
                   ConstInt32 c  (case sx of
                                        Some U  Some (wasm_extend_u c)
                                      | Some S  Some (wasm_extend_s c)
                                      | None  None)
                 | ConstInt64 c  None
                 | ConstFloat32 c  (case sx of
                                        Some U  ui64_trunc_f32 c
                                      | Some S  si64_trunc_f32 c
                                      | None  None)
                 | ConstFloat64 c  (case sx of
                                        Some U  ui64_trunc_f64 c
                                      | Some S  si64_trunc_f64 c
                                      | None  None))"

definition cvt_f32 :: "sx option  v  f32 option" where
  "cvt_f32 sx v = (case v of
                   ConstInt32 c  (case sx of
                                      Some U  Some (f32_convert_ui32 c)
                                    | Some S  Some (f32_convert_si32 c)
                                    | _  None)
                 | ConstInt64 c  (case sx of
                                      Some U  Some (f32_convert_ui64 c)
                                    | Some S  Some (f32_convert_si64 c)
                                    | _  None)
                 | ConstFloat32 c  None
                 | ConstFloat64 c  Some (wasm_demote c))"

definition cvt_f64 :: "sx option  v  f64 option" where
  "cvt_f64 sx v = (case v of
                   ConstInt32 c  (case sx of
                                      Some U  Some (f64_convert_ui32 c)
                                    | Some S  Some (f64_convert_si32 c)
                                    | _  None)
                 | ConstInt64 c  (case sx of
                                      Some U  Some (f64_convert_ui64 c)
                                    | Some S  Some (f64_convert_si64 c)
                                    | _  None)
                 | ConstFloat32 c  Some (wasm_promote c)
                 | ConstFloat64 c  None)"

definition cvt :: "t  sx option  v  v option" where
  "cvt t sx v = (case t of
                 T_i32  (case (cvt_i32 sx v) of Some c  Some (ConstInt32 c) | None  None)
               | T_i64  (case (cvt_i64 sx v) of Some c  Some (ConstInt64 c) | None  None) 
               | T_f32  (case (cvt_f32 sx v) of Some c  Some (ConstFloat32 c) | None  None)
               | T_f64  (case (cvt_f64 sx v) of Some c  Some (ConstFloat64 c) | None  None))"

definition bits :: "v  bytes" where
  "bits v = (case v of
               ConstInt32 c  (serialise_i32 c)
             | ConstInt64 c  (serialise_i64 c)
             | ConstFloat32 c  (serialise_f32 c)
             | ConstFloat64 c  (serialise_f64 c))"

definition bitzero :: "t  v" where
  "bitzero t = (case t of
                T_i32  ConstInt32 0
              | T_i64  ConstInt64 0
              | T_f32  ConstFloat32 0
              | T_f64  ConstFloat64 0)"

definition n_zeros :: "t list  v list" where
  "n_zeros ts = (map (λt. bitzero t) ts)"

lemma is_int_t_exists:
  assumes "is_int_t t"
  shows "t = T_i32  t = T_i64"
  using assms
  by (cases t) (auto simp add: is_int_t_def)

lemma is_float_t_exists:
  assumes "is_float_t t"
  shows "t = T_f32  t = T_f64"
  using assms
  by (cases t) (auto simp add: is_float_t_def)


lemma int_float_disjoint: "is_int_t t = -(is_float_t t)"
  by simp (metis is_float_t_def is_int_t_def t.exhaust t.simps(13-16))

lemma stab_unfold:
  assumes "stab s i j = Some cl"
  shows "k. inst.tab ((inst s)!i) = Some k  length ((tab s)!k) > j ((tab s)!k)!j = Some cl"
proof -
  obtain k where have_k:"(inst.tab ((inst s)!i)) = Some k"
    using assms
    unfolding stab_def
    by fastforce
  hence s_o:"stab s i j = stab_s s k j"
    using assms
    unfolding stab_def
    by simp
  then obtain stabinst where stabinst_def:"stabinst = ((tab s)!k)"
    by blast
  hence "stab_s s k j = (stabinst!j)  (length stabinst > j)"
    using assms s_o
    unfolding stab_s_def
    by (cases "(length stabinst > j)", auto)
  thus ?thesis
    using have_k stabinst_def assms s_o
    by auto
qed

lemma inj_basic: "inj Basic"
  by (meson e.inject(1) injI)

lemma inj_basic_econst: "inj (λv. $C v)"
  by (meson b_e.inject(16) e.inject(1) injI)

lemma to_e_list_1:"[$ a] = $* [a]"
  by simp

lemma to_e_list_2:"[$ a, $ b] = $* [a, b]"
  by simp

lemma to_e_list_3:"[$ a, $ b, $ c] = $* [a, b, c]"
  by simp

lemma v_exists_b_e:"ves. ($$*vs) = ($*ves)"
proof (induction vs)
  case (Cons a vs)
  thus ?case
  by (metis list.simps(9))
qed auto

lemma Lfilled_exact_imp_Lfilled:
  assumes "Lfilled_exact n lholed es LI"
  shows "Lfilled n lholed es LI"
  using assms
proof (induction rule: Lfilled_exact.induct)
  case (L0 lholed es)
  thus ?case
    using const_list_def Lfilled.intros(1)
    by fastforce
next
  case (LN vs lholed n es' l es'' k es lfilledk)
  thus ?case
    using Lfilled.intros(2)
    by fastforce
qed

lemma Lfilled_exact_app_imp_exists_Lfilled:
  assumes "const_list ves"
          "Lfilled_exact n lholed (ves@es) LI"
  shows "lholed'. Lfilled n lholed' es LI"
  using assms(2,1)
proof (induction "(ves@es)" LI rule: Lfilled_exact.induct)
  case (L0 lholed)
  show ?case
    using Lfilled.intros(1)[OF L0(2), of _ "[]"]
    by fastforce
next
  case (LN vs lholed n es' l es'' k lfilledk)
  thus ?case
    using Lfilled.intros(2)
    by fastforce
qed

lemma Lfilled_imp_exists_Lfilled_exact:
  assumes "Lfilled n lholed es LI"
  shows "lholed' ves es_c. const_list ves  Lfilled_exact n lholed' (ves@es@es_c) LI"
  using assms Lfilled_exact.intros
  by (induction rule: Lfilled.induct) fastforce+

lemma n_zeros_typeof:
  "n_zeros ts = vs  (ts = map typeof vs)"
proof (induction ts arbitrary: vs)
  case Nil
  thus ?case
    unfolding n_zeros_def
    by simp
next
  case (Cons t ts)
  obtain vs' where "n_zeros ts = vs'"
    using n_zeros_def
    by blast
  moreover
  have "typeof (bitzero t) = t"
    unfolding typeof_def bitzero_def
    by (cases t, simp_all)
  ultimately
  show ?case
    using Cons
    unfolding n_zeros_def
    by auto
qed

end