@@ -38,6 +38,71 @@ module Generate (Target : Wa_target_sig.S) = struct
3838 ; debug : Parse_bytecode.Debug .t
3939 }
4040
41+ type repr =
42+ | Value
43+ | Float
44+ | Int32
45+ | Nativeint
46+ | Int64
47+
48+ let repr_type r =
49+ match r with
50+ | Value -> Value. value
51+ | Float -> F64
52+ | Int32 -> I32
53+ | Nativeint -> I32
54+ | Int64 -> I64
55+
56+ let specialized_func_type (params , result ) =
57+ { W. params = List. map ~f: repr_type params; result = [ repr_type result ] }
58+
59+ let box_value r e =
60+ match r with
61+ | Value -> e
62+ | Float -> Memory. box_float e
63+ | Int32 -> Memory. box_int32 e
64+ | Nativeint -> Memory. box_nativeint e
65+ | Int64 -> Memory. box_int64 e
66+
67+ let unbox_value r e =
68+ match r with
69+ | Value -> e
70+ | Float -> Memory. unbox_float e
71+ | Int32 -> Memory. unbox_int32 e
72+ | Nativeint -> Memory. unbox_nativeint e
73+ | Int64 -> Memory. unbox_int64 e
74+
75+ let specialized_primitives =
76+ let h = Hashtbl. create 18 in
77+ List. iter
78+ ~f: (fun (nm , typ ) -> Hashtbl. add h nm typ)
79+ [ " caml_int32_bswap" , ([ Int32 ], Int32 )
80+ ; " caml_nativeint_bswap" , ([ Nativeint ], Nativeint )
81+ ; " caml_int64_bswap" , ([ Int64 ], Int64 )
82+ ; " caml_int32_compare" , ([ Int32 ; Int32 ], Value )
83+ ; " caml_nativeint_compare" , ([ Nativeint ; Nativeint ], Value )
84+ ; " caml_int64_compare" , ([ Int64 ; Int64 ], Value )
85+ ; " caml_string_get32" , ([ Value ; Value ], Int32 )
86+ ; " caml_string_get64" , ([ Value ; Value ], Int64 )
87+ ; " caml_bytes_get32" , ([ Value ; Value ], Int32 )
88+ ; " caml_bytes_get64" , ([ Value ; Value ], Int64 )
89+ ; " caml_bytes_set32" , ([ Value ; Value ; Int32 ], Value )
90+ ; " caml_bytes_set64" , ([ Value ; Value ; Int64 ], Value )
91+ ; " caml_lxm_next" , ([ Value ], Int64 )
92+ ; " caml_ba_uint8_get32" , ([ Value ; Value ], Int32 )
93+ ; " caml_ba_uint8_get64" , ([ Value ; Value ], Int64 )
94+ ; " caml_ba_uint8_set32" , ([ Value ; Value ; Int32 ], Value )
95+ ; " caml_ba_uint8_set64" , ([ Value ; Value ; Int64 ], Value )
96+ ; " caml_nextafter_float" , ([ Float ; Float ], Float )
97+ ; " caml_classify_float" , ([ Float ], Value )
98+ ; " caml_ldexp_float" , ([ Float ; Value ], Float )
99+ ; " caml_signbit_float" , ([ Float ], Value )
100+ ; " caml_erf_float" , ([ Float ], Float )
101+ ; " caml_erfc_float" , ([ Float ], Float )
102+ ; " caml_float_compare" , ([ Float ; Float ], Value )
103+ ];
104+ h
105+
41106 let func_type n =
42107 { W. params = List. init ~len: n ~f: (fun _ -> Value. value); result = [ Value. value ] }
43108
@@ -386,6 +451,10 @@ module Generate (Target : Wa_target_sig.S) = struct
386451 int32_shift_op (Shr U ) i j
387452 | Extern "caml_int32_to_int" , [ i ] -> Value. val_int (Memory. unbox_int32 i)
388453 | Extern "caml_int32_of_int" , [ i ] -> Memory. box_int32 (Value. int_val i)
454+ | Extern "caml_nativeint_of_int32" , [ i ] ->
455+ Memory. box_nativeint (Memory. unbox_int32 i)
456+ | Extern "caml_nativeint_to_int32" , [ i ] ->
457+ Memory. box_int32 (Memory. unbox_nativeint i)
389458 | Extern "caml_int64_bits_of_float" , [ f ] ->
390459 let * f = Memory. unbox_float f in
391460 Memory. box_int64 (return (W. UnOp (I64 ReinterpretF , f)))
@@ -565,18 +634,30 @@ module Generate (Target : Wa_target_sig.S) = struct
565634 ~init: (return [] )
566635 in
567636 Memory. allocate ~tag: 0 l
568- | Extern name , l ->
637+ | Extern name , l -> (
569638 let name = Primitive. resolve name in
570- (* ZZZ Different calling convention when large number of parameters *)
571- let * f = register_import ~name (Fun (func_type (List. length l))) in
572- let rec loop acc l =
573- match l with
574- | [] -> return (W. Call (f, List. rev acc))
575- | x :: r ->
576- let * x = x in
577- loop (x :: acc) r
578- in
579- loop [] l
639+ try
640+ let typ = Hashtbl. find specialized_primitives name in
641+ let * f = register_import ~name (Fun (specialized_func_type typ)) in
642+ let rec loop acc arg_typ l =
643+ match arg_typ, l with
644+ | [] , [] -> box_value (snd typ) (return (W. Call (f, List. rev acc)))
645+ | repr :: rem , x :: r ->
646+ let * x = unbox_value repr x in
647+ loop (x :: acc) rem r
648+ | [] , _ :: _ | _ :: _ , [] -> assert false
649+ in
650+ loop [] (fst typ) l
651+ with Not_found ->
652+ let * f = register_import ~name (Fun (func_type (List. length l))) in
653+ let rec loop acc l =
654+ match l with
655+ | [] -> return (W. Call (f, List. rev acc))
656+ | x :: r ->
657+ let * x = x in
658+ loop (x :: acc) r
659+ in
660+ loop [] l)
580661 | Not , [ x ] -> Value. not x
581662 | Lt , [ x; y ] -> Value. lt x y
582663 | Le , [ x; y ] -> Value. le x y
0 commit comments