Skip to content

Commit 1b79b88

Browse files
authored
[interpreter] Revive heaptype on ref.null script literals (#2129)
1 parent 40490e3 commit 1b79b88

7 files changed

Lines changed: 91 additions & 43 deletions

File tree

interpreter/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ action:
453453
const:
454454
( <num_type>.const <num> ) ;; number value
455455
( <vec_type> <vec_shape> <num>+ ) ;; vector value
456-
( ref.null <ref_kind>? ) ;; null reference
456+
( ref.null <heap_type> ) ;; null reference
457457
( ref.host <nat> ) ;; host reference
458458
( ref.extern <nat> ) ;; external host reference
459459

interpreter/script/js.ml

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -390,30 +390,33 @@ let abs_mask_of = function
390390
| I32T | F32T -> I32 Int32.max_int
391391
| I64T | F64T -> I64 Int64.max_int
392392

393-
let value v t =
394-
match v.it, t with
395-
| Num n, _ -> [Const (n @@ v.at) @@ v.at]
396-
| Vec s, _ -> [VecConst (s @@ v.at) @@ v.at]
397-
| Ref NullRef, (RefT (_, ht)) ->
398-
[ RefNull (Match.bot_of_heaptype [] ht) @@ v.at ]
399-
| Ref (HostRef n), _ ->
400-
[ Const (I32 n @@ v.at) @@ v.at;
401-
Call (hostref_idx @@ v.at) @@ v.at;
393+
let value v at =
394+
match v with
395+
| Num n -> [Const (n @@ at) @@ at]
396+
| Vec s -> [VecConst (s @@ at) @@ at]
397+
| Ref (HostRef n) ->
398+
[ Const (I32 n @@ at) @@ at;
399+
Call (hostref_idx @@ at) @@ at;
402400
]
403-
| Ref (Extern.ExternRef (HostRef n)), _ ->
404-
[ Const (I32 n @@ v.at) @@ v.at;
405-
Call (hostref_idx @@ v.at) @@ v.at;
406-
ExternConvert Externalize @@ v.at;
401+
| Ref (Extern.ExternRef (HostRef n)) ->
402+
[ Const (I32 n @@ at) @@ at;
403+
Call (hostref_idx @@ at) @@ at;
404+
ExternConvert Externalize @@ at;
407405
]
408-
| Ref _, _ -> assert false
406+
| Ref _ -> assert false
407+
408+
let literal lit =
409+
match lit.it with
410+
| ValLit v -> value v lit.at
411+
| NullLit ht -> [RefNull (Match.bot_of_heaptype [] ht) @@ lit.at]
409412

410-
let invoke dt vs ts at =
413+
let invoke dt lits at =
411414
let dummy = RecT [SubT (Final, [], FuncT ([], []))] in
412415
let rts0 = Lib.List32.init subject_type_idx (fun i -> dummy, (dummy, i)) in
413416
let rts, i = statify_deftype rts0 dt in
414417
List.map (fun (_, (rt, _)) -> rt @@ at) (Lib.List32.drop subject_type_idx rts),
415418
ExternFuncT (Idx i),
416-
List.concat (List.map2 value vs ts) @ [Call (subject_idx @@ at) @@ at]
419+
List.concat (List.map literal lits) @ [Call (subject_idx @@ at) @@ at]
417420

418421
let get t at =
419422
[], ExternGlobalT t, [GlobalGet (subject_idx @@ at) @@ at]
@@ -435,6 +438,7 @@ let type_of_vec_pat = function
435438
let type_of_ref_pat = function
436439
| RefPat ref -> type_of_ref ref.it
437440
| RefTypePat ht -> (NoNull, ht)
441+
| NullPat ht -> (Null, ht)
438442

439443
let rec type_of_result res =
440444
match res.it with
@@ -554,6 +558,10 @@ let assert_return ress ts at =
554558
[ RefTest (NoNull, t) @@ at;
555559
Test (I32 I32Op.Eqz) @@ at;
556560
BrIf (0l @@ at) @@ at ]
561+
| RefResult (NullPat _) ->
562+
[ RefIsNull @@ at;
563+
Test (I32 I32Op.Eqz) @@ at;
564+
BrIf (0l @@ at) @@ at ]
557565
| EitherResult ress ->
558566
let idx = Lib.List32.length !locals in
559567
locals := !locals @ [Local t @@ res.at];
@@ -704,12 +712,17 @@ let of_ref r =
704712
| HostRef n | Extern.ExternRef (HostRef n) -> "hostref(" ^ Int32.to_string n ^ ")"
705713
| _ -> assert false
706714

707-
let of_value v =
708-
match v.it with
715+
let of_val v =
716+
match v with
709717
| Num n -> of_num n
710718
| Vec v -> of_vec v
711719
| Ref r -> of_ref r
712720

721+
let of_lit lit =
722+
match lit.it with
723+
| ValLit v -> of_val v
724+
| NullLit _ -> "null"
725+
713726
let of_nan = function
714727
| CanonicalNan -> "\"nan:canonical\""
715728
| ArithmeticNan -> "\"nan:arithmetic\""
@@ -728,6 +741,7 @@ let of_vec_pat = function
728741
let of_ref_pat = function
729742
| RefPat r -> of_ref r.it
730743
| RefTypePat t -> "\"ref." ^ string_of_heaptype t ^ "\""
744+
| NullPat t -> "\"ref.null\""
731745

732746
let rec of_result res =
733747
match res.it with
@@ -753,16 +767,16 @@ let of_wrapper env x_opt name wrap_action wrap_assertion at =
753767

754768
let of_action env act =
755769
match act.it with
756-
| Invoke (x_opt, name, vs) ->
770+
| Invoke (x_opt, name, lits) ->
757771
"call(" ^ of_inst_opt env x_opt ^ ", " ^ of_name name ^ ", " ^
758-
"[" ^ String.concat ", " (List.map of_value vs) ^ "])",
772+
"[" ^ String.concat ", " (List.map of_lit lits) ^ "])",
759773
(match lookup_export env x_opt name act.at with
760774
| ExternFuncT (Def dt) ->
761-
let (ins, out) as ft = functype_of_comptype (expand_deftype dt) in
775+
let (_, ts) as ft = functype_of_comptype (expand_deftype dt) in
762776
if is_js_functype ft then
763777
None
764778
else
765-
Some (of_wrapper env x_opt name (invoke dt vs ins), out)
779+
Some (of_wrapper env x_opt name (invoke dt lits), ts)
766780
| _ -> None
767781
)
768782
| Get (x_opt, name) ->

interpreter/script/runner.ml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ let string_of_ref_pat (p : ref_pat) =
265265
match p with
266266
| RefPat r -> Value.string_of_ref r.it
267267
| RefTypePat t -> Types.string_of_heaptype t
268+
| NullPat t -> "null"
268269

269270
let rec string_of_result r =
270271
match r.it with
@@ -285,6 +286,7 @@ let rec type_of_result r =
285286
| VecResult (VecPat v) -> Types.VecT (Value.type_of_vec v)
286287
| RefResult (RefPat r) -> Types.RefT (Value.type_of_ref r.it)
287288
| RefResult (RefTypePat t) -> Types.(RefT (NoNull, t)) (* assume closed *)
289+
| RefResult (NullPat t) -> Types.(RefT (Null, t))
288290
| EitherResult rs ->
289291
let ts = List.map type_of_result rs in
290292
List.fold_left (fun t1 t2 ->
@@ -357,6 +359,16 @@ let register_instance name inst =
357359

358360
(* Running *)
359361

362+
let value_of_lit lit =
363+
match lit.it with
364+
| ValLit v -> v
365+
| NullLit ht -> Value.(Ref NullRef)
366+
367+
let type_of_lit lit =
368+
match lit.it with
369+
| ValLit v -> Value.type_of_value v
370+
| NullLit ht -> Types.RefT (Types.Null, ht)
371+
360372
let validity = function
361373
| Ok t -> ()
362374
| Error (at, msg) -> Invalid.error at msg
@@ -389,20 +401,20 @@ let run_instantiation m =
389401

390402
let run_action act : Value.t list =
391403
match act.it with
392-
| Invoke (x_opt, name, vs) ->
404+
| Invoke (x_opt, name, lits) ->
393405
trace ("Invoking function \"" ^ Types.string_of_name name ^ "\"...");
394406
let inst = lookup_instance x_opt act.at in
395407
(match Engine.module_export inst name with
396408
| Some (Engine.ExternFunc f) ->
397409
let (ts1, _ts2) =
398410
Types.(functype_of_comptype (expand_deftype (Engine.func_type f))) in
399-
if List.length vs <> List.length ts1 then
411+
if List.length lits <> List.length ts1 then
400412
Script.error act.at "wrong number of arguments";
401-
List.iter2 (fun v t ->
402-
if not (Match.match_valtype [] (Value.type_of_value v.it) t) then
403-
Script.error v.at "wrong type of argument"
404-
) vs ts1;
405-
result (Engine.func_call f (List.map (fun v -> v.it) vs))
413+
List.iter2 (fun lit t ->
414+
if not (Match.match_valtype [] (type_of_lit lit) t) then
415+
Script.error lit.at "wrong type of argument"
416+
) lits ts1;
417+
result (Engine.func_call f (List.map value_of_lit lits))
406418
| Some _ -> Assert.error act.at "export is not a function"
407419
| None -> Assert.error act.at "undefined export"
408420
)
@@ -461,6 +473,7 @@ let assert_ref_pat r p =
461473
| RefTypePat Types.FuncHT, Instance.FuncRef _
462474
| RefTypePat Types.ExnHT, Exn.ExnRef _
463475
| RefTypePat Types.ExternHT, _ -> true
476+
| NullPat _, Value.NullRef -> true
464477
| _ -> false
465478

466479
let rec assert_result v r =

interpreter/script/script.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ type var = string Source.phrase
33
type Value.ref_ += HostRef of int32
44
type num = Value.num Source.phrase
55
type ref_ = Value.ref_ Source.phrase
6-
type literal = Value.t Source.phrase
6+
7+
type literal = literal' Source.phrase
8+
and literal' =
9+
| ValLit of Value.t
10+
| NullLit of Types.heaptype
711

812
type definition = definition' Source.phrase
913
and definition' =
@@ -30,6 +34,7 @@ type vec_pat =
3034
type ref_pat =
3135
| RefPat of ref_
3236
| RefTypePat of Types.heaptype
37+
| NullPat of Types.heaptype
3338

3439
type result = result' Source.phrase
3540
and result' =

interpreter/text/arrange.ml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -771,17 +771,22 @@ let num mode = if mode = `Binary then hex_string_of_num else string_of_num
771771
let vec mode = if mode = `Binary then hex_string_of_vec else string_of_vec
772772

773773
let ref_ = function
774-
| NullRef -> Node ("ref.null", [])
774+
| Value.NullRef -> Node ("ref.null", [])
775775
| Script.HostRef n -> Node ("ref.host " ^ nat32 n, [])
776776
| Extern.ExternRef (Script.HostRef n) -> Node ("ref.extern " ^ nat32 n, [])
777777
| _ -> assert false
778778

779-
let literal mode lit =
780-
match lit.it with
779+
let value mode v =
780+
match v with
781781
| Num n -> Node (constop n ^ " " ^ num mode n, [])
782782
| Vec v -> Node (vconstop v ^ " " ^ vec mode v, [])
783783
| Ref r -> ref_ r
784784

785+
let literal mode lit =
786+
match lit.it with
787+
| ValLit v -> value mode v
788+
| NullLit t -> Node ("ref.null " ^ heaptype t, [])
789+
785790
let definition mode isdef x_opt def =
786791
try
787792
match mode with
@@ -830,7 +835,7 @@ let nanop (n : nanop) =
830835
| _ -> .
831836

832837
let num_pat mode = function
833-
| NumPat n -> literal mode (Value.Num n.it @@ n.at)
838+
| NumPat n -> literal mode (ValLit (Value.Num n.it) @@ n.at)
834839
| NanPat nan -> Node (constop nan.it ^ " " ^ nanop nan, [])
835840

836841
let lane_pat mode pat shape =
@@ -851,6 +856,7 @@ let vec_pat mode = function
851856
let ref_pat = function
852857
| RefPat r -> ref_ r.it
853858
| RefTypePat t -> Node ("ref." ^ heaptype t, [])
859+
| NullPat t -> Node ("ref.null " ^ heaptype t, [])
854860

855861
let rec result mode res =
856862
match res.it with

interpreter/text/parser.mly

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,14 +1500,17 @@ literal_vec :
15001500
| LPAR VEC_CONST VECSHAPE list(num) RPAR { snd (vec $2 $3 $4 $sloc) }
15011501
15021502
literal_ref :
1503-
| LPAR REF_NULL heaptype? RPAR { Value.NullRef }
15041503
| LPAR REF_HOST NAT RPAR { Script.HostRef (nat32 $3 $loc($3)) }
15051504
| LPAR REF_EXTERN NAT RPAR { Extern.ExternRef (Script.HostRef (nat32 $3 $loc($3))) }
15061505
1506+
literal_null :
1507+
| LPAR REF_NULL heaptype RPAR { $3 (empty_context ()) }
1508+
15071509
literal :
1508-
| literal_num { Value.Num $1 @@ $sloc }
1509-
| literal_vec { Value.Vec $1 @@ $sloc }
1510-
| literal_ref { Value.Ref $1 @@ $sloc }
1510+
| literal_num { ValLit (Value.Num $1) @@ $sloc }
1511+
| literal_vec { ValLit (Value.Vec $1) @@ $sloc }
1512+
| literal_ref { ValLit (Value.Ref $1) @@ $sloc }
1513+
| literal_null { NullLit $1 @@ $sloc }
15111514
15121515
numpat :
15131516
| num { fun sh -> vec_lane_lit sh $1.it $1.at }
@@ -1517,6 +1520,8 @@ result :
15171520
| literal_num { NumResult (NumPat ($1 @@ $sloc)) @@ $sloc }
15181521
| LPAR CONST NAN RPAR { NumResult (NanPat (nanop $2 ($3 @@ $loc($3)))) @@ $sloc }
15191522
| literal_ref { RefResult (RefPat ($1 @@ $sloc)) @@ $sloc }
1523+
| LPAR REF_NULL RPAR { RefResult (RefPat (Value.NullRef @@ $sloc)) @@ $sloc }
1524+
| LPAR REF_NULL heaptype RPAR { RefResult (NullPat ($3 (empty_context ()))) @@ $sloc }
15201525
| LPAR REF RPAR { RefResult (RefTypePat AnyHT) @@ $sloc }
15211526
| LPAR REF_EQ RPAR { RefResult (RefTypePat EqHT) @@ $sloc }
15221527
| LPAR REF_I31 RPAR { RefResult (RefTypePat I31HT) @@ $sloc }

spectec/src/backend-interpreter/runner.ml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,16 @@ let err_exit = ref true
128128

129129
(** Main functions **)
130130

131+
let value_of_arg = function
132+
| ValLit v -> v
133+
| NullLit _ -> Value.(Ref NullRef)
134+
131135
let invoke module_name funcname args =
132-
log "[Invoking %s %s...]\n" funcname (Value.string_of_values args);
136+
let values = List.map value_of_arg args in
137+
log "[Invoking %s %s...]\n" funcname (Value.string_of_values values);
133138

134139
let funcaddr = get_export_addr funcname module_name in
135-
Interpreter.invoke [funcaddr; al_of_list al_of_value args]
140+
Interpreter.invoke [funcaddr; al_of_list al_of_value values]
136141

137142

138143
let get_global_value module_name globalname =
@@ -296,10 +301,10 @@ let run_wasm' args module_ =
296301
(* TODO: Only Int32 arguments/results are acceptable *)
297302
match args with
298303
| funcname :: args' ->
299-
let make_value s = Value.Num (I32 (Int32.of_string s)) in
304+
let make_lit s = ValLit (Value.Num (I32 (Int32.of_string s))) in
300305

301306
(* Invoke *)
302-
invoke (Register.get_module_name None) funcname (List.map make_value args')
307+
invoke (Register.get_module_name None) funcname (List.map make_lit args')
303308
(* Print invocation result *)
304309
|> al_to_list al_to_value
305310
|> Value.string_of_values

0 commit comments

Comments
 (0)