Skip to content

Commit d1c8d85

Browse files
authored
Peek and poke (ocaml-flambda#3309)
1 parent f8caad4 commit d1c8d85

24 files changed

+423
-109
lines changed

bytecomp/bytegen.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ let preserve_tailcall_for_prim = function
199199
| Patomic_exchange | Patomic_compare_exchange
200200
| Patomic_cas | Patomic_fetch_add | Patomic_load _
201201
| Pdls_get | Preinterpret_tagged_int63_as_unboxed_int64
202-
| Preinterpret_unboxed_int64_as_tagged_int63 | Ppoll ->
202+
| Preinterpret_unboxed_int64_as_tagged_int63 | Ppoll | Ppeek _ | Ppoke _ ->
203203
false
204204

205205
(* Add a Kpop N instruction in front of a continuation *)
@@ -737,6 +737,8 @@ let comp_primitive stack_info p sz args =
737737
| Punbox_float _ | Pbox_float (_, _) | Punbox_int _ | Pbox_int _
738738
->
739739
fatal_error "Bytegen.comp_primitive"
740+
| Ppeek _ | Ppoke _ ->
741+
fatal_error "Bytegen.comp_primitive: Ppeek/Ppoke not supported in bytecode"
740742

741743
let is_immed n = immed_min <= n && n <= immed_max
742744

lambda/lambda.ml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,8 @@ type primitive =
334334
| Parray_to_iarray
335335
| Parray_of_iarray
336336
| Pget_header of locality_mode
337+
| Ppeek of peek_or_poke
338+
| Ppoke of peek_or_poke
337339
(* Fetching domain-local state *)
338340
| Pdls_get
339341
(* Poll for runtime actions *)
@@ -490,6 +492,14 @@ and boxed_integer = Primitive.boxed_integer =
490492
and boxed_vector = Primitive.boxed_vector =
491493
| Boxed_vec128
492494

495+
and peek_or_poke =
496+
| Ppp_tagged_immediate
497+
| Ppp_unboxed_float32
498+
| Ppp_unboxed_float
499+
| Ppp_unboxed_int32
500+
| Ppp_unboxed_int64
501+
| Ppp_unboxed_nativeint
502+
493503
and bigarray_kind =
494504
Pbigarray_unknown
495505
| Pbigarray_float16
@@ -1941,7 +1951,8 @@ let primitive_may_allocate : primitive -> locality_mode option = function
19411951
| Patomic_fetch_add
19421952
| Pdls_get
19431953
| Preinterpret_unboxed_int64_as_tagged_int63
1944-
| Parray_element_size_in_bytes _ -> None
1954+
| Parray_element_size_in_bytes _
1955+
| Ppeek _ | Ppoke _ -> None
19451956
| Preinterpret_tagged_int63_as_unboxed_int64 ->
19461957
if !Clflags.native_code then None
19471958
else
@@ -2107,7 +2118,7 @@ let primitive_can_raise prim =
21072118
| Prunstack | Pperform | Presume | Preperform -> true (* XXX! *)
21082119
| Pdls_get | Ppoll | Preinterpret_tagged_int63_as_unboxed_int64
21092120
| Preinterpret_unboxed_int64_as_tagged_int63
2110-
| Parray_element_size_in_bytes _ ->
2121+
| Parray_element_size_in_bytes _ | Ppeek _ | Ppoke _ ->
21112122
false
21122123

21132124
let constant_layout: constant -> layout = function
@@ -2342,6 +2353,16 @@ let primitive_result_layout (p : primitive) =
23422353
| Ppoll -> layout_unit
23432354
| Preinterpret_tagged_int63_as_unboxed_int64 -> layout_unboxed_int64
23442355
| Preinterpret_unboxed_int64_as_tagged_int63 -> layout_int
2356+
| Ppeek layout -> (
2357+
match layout with
2358+
| Ppp_tagged_immediate -> layout_int
2359+
| Ppp_unboxed_float32 -> layout_unboxed_float Unboxed_float32
2360+
| Ppp_unboxed_float -> layout_unboxed_float Unboxed_float64
2361+
| Ppp_unboxed_int32 -> layout_unboxed_int32
2362+
| Ppp_unboxed_int64 -> layout_unboxed_int64
2363+
| Ppp_unboxed_nativeint -> layout_unboxed_nativeint
2364+
)
2365+
| Ppoke _ -> layout_unit
23452366

23462367
let compute_expr_layout free_vars_kind lam =
23472368
let rec compute_expr_layout kinds = function

lambda/lambda.mli

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,8 @@ type primitive =
343343
| Parray_of_iarray (* Unsafely reinterpret an immutable array as a mutable
344344
one; O(1) *)
345345
| Pget_header of locality_mode
346+
| Ppeek of peek_or_poke
347+
| Ppoke of peek_or_poke
346348
(* Get the header of a block. This primitive is invalid if provided with an
347349
immediate value.
348350
Note: The GC color bits in the header are not reliable except for checking
@@ -524,6 +526,14 @@ and boxed_integer = Primitive.boxed_integer =
524526
and boxed_vector = Primitive.boxed_vector =
525527
| Boxed_vec128
526528

529+
and peek_or_poke =
530+
| Ppp_tagged_immediate
531+
| Ppp_unboxed_float32
532+
| Ppp_unboxed_float
533+
| Ppp_unboxed_int32
534+
| Ppp_unboxed_int64
535+
| Ppp_unboxed_nativeint
536+
527537
and bigarray_kind =
528538
Pbigarray_unknown
529539
| Pbigarray_float16

lambda/printlambda.ml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,15 @@ let field_read_semantics ppf sem =
478478
| Reads_agree -> ()
479479
| Reads_vary -> fprintf ppf "_mut"
480480

481+
let peek_or_poke ppf (pp : peek_or_poke) =
482+
match pp with
483+
| Ppp_tagged_immediate -> fprintf ppf "tagged_immediate"
484+
| Ppp_unboxed_float32 -> fprintf ppf "unboxed_float32"
485+
| Ppp_unboxed_float -> fprintf ppf "unboxed_float"
486+
| Ppp_unboxed_int32 -> fprintf ppf "unboxed_int32"
487+
| Ppp_unboxed_int64 -> fprintf ppf "unboxed_int64"
488+
| Ppp_unboxed_nativeint -> fprintf ppf "unboxed_nativeint"
489+
481490
let primitive ppf = function
482491
| Pbytes_to_string -> fprintf ppf "bytes_to_string"
483492
| Pbytes_of_string -> fprintf ppf "bytes_of_string"
@@ -930,6 +939,12 @@ let primitive ppf = function
930939
fprintf ppf "reinterpret_tagged_int63_as_unboxed_int64"
931940
| Preinterpret_unboxed_int64_as_tagged_int63 ->
932941
fprintf ppf "reinterpret_unboxed_int64_as_tagged_int63"
942+
| Ppeek layout ->
943+
fprintf ppf "(peek@ %a)"
944+
peek_or_poke layout
945+
| Ppoke layout ->
946+
fprintf ppf "(poke@ %a)"
947+
peek_or_poke layout
933948

934949
let name_of_primitive = function
935950
| Pbytes_of_string -> "Pbytes_of_string"
@@ -1107,6 +1122,8 @@ let name_of_primitive = function
11071122
"Preinterpret_tagged_int63_as_unboxed_int64"
11081123
| Preinterpret_unboxed_int64_as_tagged_int63 ->
11091124
"Preinterpret_unboxed_int64_as_tagged_int63"
1125+
| Ppeek _ -> "Ppeek"
1126+
| Ppoke _ -> "Ppoke"
11101127

11111128
let zero_alloc_attribute ppf check =
11121129
match check with

lambda/tmc.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,7 @@ let rec choice ctx t =
974974
| Pint_as_pointer _
975975
| Psequand | Psequor
976976
| Ppoll
977+
| Ppeek _ | Ppoke _
977978
->
978979
let primargs = traverse_list ctx primargs in
979980
Choice.lambda (Lprim (prim, primargs, loc))

lambda/translprim.ml

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ module String = Misc.Stdlib.String
2828
type error =
2929
| Unknown_builtin_primitive of string
3030
| Wrong_arity_builtin_primitive of string
31+
| Wrong_layout_for_peek_or_poke of string
3132
| Invalid_floatarray_glb
3233
| Product_iarrays_unsupported
3334
| Invalid_array_kind_for_uninitialized_makearray_dynamic
@@ -123,6 +124,10 @@ type prim =
123124
| Identity
124125
| Apply of Lambda.region_close * Lambda.layout
125126
| Revapply of Lambda.region_close * Lambda.layout
127+
| Peek of Lambda.peek_or_poke option
128+
| Poke of Lambda.peek_or_poke option
129+
(* For [Peek] and [Poke] the [option] is [None] until the primitive
130+
specialization code (below) has been run. *)
126131
| Unsupported of Lambda.primitive
127132

128133
let units_with_used_primitives = Hashtbl.create 7
@@ -916,6 +921,8 @@ let lookup_primitive loc ~poly_mode ~poly_sort pos p =
916921
Primitive(Preinterpret_tagged_int63_as_unboxed_int64, 1)
917922
| "%reinterpret_unboxed_int64_as_tagged_int63" ->
918923
Primitive(Preinterpret_unboxed_int64_as_tagged_int63, 1)
924+
| "%peek" -> Peek None
925+
| "%poke" -> Poke None
919926
| s when String.length s > 0 && s.[0] = '%' ->
920927
(match String.Map.find_opt s indexing_primitives with
921928
| Some prim -> prim ~mode
@@ -1185,6 +1192,27 @@ let glb_array_set_type loc t1 t2 =
11851192
(* Pfloatarray is a minimum *)
11861193
| Pfloatarray_set, Pfloatarray -> Pfloatarray_set
11871194

1195+
let peek_or_poke_layout_from_type ~prim_name error_loc env ty
1196+
: Lambda.peek_or_poke option =
1197+
match Ctype.type_sort ~why:Peek_or_poke ~fixed:true env ty with
1198+
| Error _ -> None
1199+
| Ok sort ->
1200+
let sort = Jkind.Sort.default_to_value_and_get sort in
1201+
let layout = Typeopt.layout env error_loc sort ty in
1202+
match layout with
1203+
| Punboxed_float Unboxed_float32 -> Some Ppp_unboxed_float32
1204+
| Punboxed_float Unboxed_float64 -> Some Ppp_unboxed_float
1205+
| Punboxed_int Unboxed_int32 -> Some Ppp_unboxed_int32
1206+
| Punboxed_int Unboxed_int64 -> Some Ppp_unboxed_int64
1207+
| Punboxed_int Unboxed_nativeint -> Some Ppp_unboxed_nativeint
1208+
| Pvalue { raw_kind = Pintval ; _ } -> Some Ppp_tagged_immediate
1209+
| Ptop
1210+
| Pvalue _
1211+
| Punboxed_vector _
1212+
| Punboxed_product _
1213+
| Pbottom ->
1214+
raise (Error (error_loc, Wrong_layout_for_peek_or_poke prim_name))
1215+
11881216
(* Specialize a primitive from available type information. *)
11891217
(* CR layouts v7: This function had a loc argument added just to support the void
11901218
check error message. Take it out when we remove that. *)
@@ -1367,6 +1395,25 @@ let specialize_primitive env loc ty ~has_constant_constructor prim =
13671395
end else begin
13681396
None
13691397
end
1398+
| Peek _, _ -> (
1399+
match is_function_type env ty with
1400+
| None -> None
1401+
| Some (_p1, result_ty) ->
1402+
match
1403+
peek_or_poke_layout_from_type ~prim_name:"peek"
1404+
(to_location loc) env result_ty
1405+
with
1406+
| None -> None
1407+
| Some contents_layout -> Some (Peek (Some contents_layout))
1408+
)
1409+
| Poke _, _ptr_ty :: new_value_ty :: _ -> (
1410+
match
1411+
peek_or_poke_layout_from_type ~prim_name:"poke"
1412+
(to_location loc) env new_value_ty
1413+
with
1414+
| None -> None
1415+
| Some contents_layout -> Some (Poke (Some contents_layout))
1416+
)
13701417
| _ -> None
13711418

13721419
let caml_equal =
@@ -1613,6 +1660,12 @@ let lambda_of_prim prim_name prim loc args arg_exps =
16131660
ap_region_close = pos;
16141661
ap_mode = alloc_heap;
16151662
}
1663+
| Peek None, _ | Poke None, _ ->
1664+
raise(Error(to_location loc, Wrong_layout_for_peek_or_poke prim_name))
1665+
| Peek (Some layout), [ptr] ->
1666+
Lprim (Ppeek layout, [ptr], loc)
1667+
| Poke (Some layout), [ptr; new_value] ->
1668+
Lprim (Ppoke layout, [ptr; new_value], loc)
16161669
| Unsupported prim, _ ->
16171670
let exn =
16181671
transl_extension_path loc (Lazy.force Env.initial)
@@ -1631,7 +1684,7 @@ let lambda_of_prim prim_name prim loc args arg_exps =
16311684
| (Raise _ | Raise_with_backtrace
16321685
| Lazy_force _ | Loc _ | Primitive _ | Sys_argv | Comparison _
16331686
| Send _ | Send_self _ | Send_cache _ | Frame_pointers | Identity
1634-
| Apply _ | Revapply _), _ ->
1687+
| Apply _ | Revapply _ | Peek _ | Poke _), _ ->
16351688
raise(Error(to_location loc, Wrong_arity_builtin_primitive prim_name))
16361689

16371690
let check_primitive_arity loc p =
@@ -1663,8 +1716,8 @@ let check_primitive_arity loc p =
16631716
| Send _ | Send_self _ -> p.prim_arity = 2
16641717
| Send_cache _ -> p.prim_arity = 4
16651718
| Frame_pointers -> p.prim_arity = 0
1666-
| Identity -> p.prim_arity = 1
1667-
| Apply _ | Revapply _ -> p.prim_arity = 2
1719+
| Identity | Peek _ -> p.prim_arity = 1
1720+
| Apply _ | Revapply _ | Poke _ -> p.prim_arity = 2
16681721
| Unsupported _ -> true
16691722
in
16701723
if not ok then raise(Error(loc, Wrong_arity_builtin_primitive p.prim_name))
@@ -1850,7 +1903,7 @@ let lambda_primitive_needs_event_after = function
18501903
| Pintofbint _ | Pctconst _ | Pbswap16 | Pint_as_pointer _ | Popaque _
18511904
| Pdls_get
18521905
| Pobj_magic _ | Punbox_float _ | Punbox_int _ | Punbox_vector _
1853-
| Preinterpret_unboxed_int64_as_tagged_int63
1906+
| Preinterpret_unboxed_int64_as_tagged_int63 | Ppeek _ | Ppoke _
18541907
(* These don't allocate in bytecode; they're just identity functions: *)
18551908
| Pbox_float (_, _) | Pbox_int _ | Pbox_vector (_, _)
18561909
-> false
@@ -1864,7 +1917,7 @@ let primitive_needs_event_after = function
18641917
| Lazy_force _ | Send _ | Send_self _ | Send_cache _
18651918
| Apply _ | Revapply _ -> true
18661919
| Raise _ | Raise_with_backtrace | Loc _ | Frame_pointers | Identity
1867-
| Unsupported _ -> false
1920+
| Peek _ | Poke _ | Unsupported _ -> false
18681921

18691922
let transl_primitive_application loc p env ty ~poly_mode ~poly_sort
18701923
path exp args arg_exps pos =
@@ -1908,6 +1961,8 @@ let report_error ppf = function
19081961
| Wrong_arity_builtin_primitive prim_name ->
19091962
fprintf ppf "Wrong arity for builtin primitive %a"
19101963
Style.inline_code prim_name
1964+
| Wrong_layout_for_peek_or_poke prim_name ->
1965+
fprintf ppf "Unsupported layout for the %s primitive" prim_name
19111966
| Invalid_floatarray_glb ->
19121967
fprintf ppf
19131968
"@[Floatarray primitives can't be used on arrays containing@ \

lambda/translprim.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ val sort_of_native_repr :
6262
type error =
6363
| Unknown_builtin_primitive of string
6464
| Wrong_arity_builtin_primitive of string
65+
| Wrong_layout_for_peek_or_poke of string
6566
| Invalid_floatarray_glb
6667
| Product_iarrays_unsupported
6768
| Invalid_array_kind_for_uninitialized_makearray_dynamic

lambda/value_rec_compiler.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,9 @@ let compute_static_size lam =
350350
| Patomic_cas
351351
| Patomic_fetch_add
352352
| Popaque _
353-
| Pdls_get ->
353+
| Pdls_get
354+
| Ppeek _
355+
| Ppoke _ ->
354356
dynamic_size lam
355357

356358
(* Primitives specific to flambda-backend *)

middle_end/flambda2/from_lambda/closure_conversion.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,7 @@ let close_primitive acc env ~let_bound_ids_with_kinds named
10491049
| Patomic_exchange | Patomic_compare_exchange | Patomic_cas
10501050
| Patomic_fetch_add | Pdls_get | Ppoll | Patomic_load _
10511051
| Preinterpret_tagged_int63_as_unboxed_int64
1052-
| Preinterpret_unboxed_int64_as_tagged_int63 ->
1052+
| Preinterpret_unboxed_int64_as_tagged_int63 | Ppeek _ | Ppoke _ ->
10531053
(* Inconsistent with outer match *)
10541054
assert false
10551055
in

middle_end/flambda2/from_lambda/lambda_to_flambda_primitives.ml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ let standard_int_or_float_of_unboxed_integer (ubint : L.unboxed_integer) :
100100
let standard_int_or_float_of_boxed_integer bint =
101101
standard_int_or_float_of_unboxed_integer (Primitive.unboxed_integer bint)
102102

103+
let standard_int_or_float_of_peek_or_poke (layout : L.peek_or_poke) :
104+
K.Standard_int_or_float.t =
105+
match layout with
106+
| Ppp_tagged_immediate -> Tagged_immediate
107+
| Ppp_unboxed_float32 -> Naked_float32
108+
| Ppp_unboxed_float -> Naked_float
109+
| Ppp_unboxed_int32 -> Naked_int32
110+
| Ppp_unboxed_int64 -> Naked_int64
111+
| Ppp_unboxed_nativeint -> Naked_nativeint
112+
103113
let convert_block_access_field_kind i_or_p : P.Block_access_field_kind.t =
104114
match i_or_p with L.Immediate -> Immediate | L.Pointer -> Any_value
105115

@@ -2396,6 +2406,12 @@ let convert_lprim ~big_endian (prim : L.primitive) (args : Simple.t list list)
23962406
"Preinterpret_tagged_int63_as_unboxed_int64 can only be used on 64-bit \
23972407
targets";
23982408
[Unary (Reinterpret_64_bit_word Tagged_int63_as_unboxed_int64, i)]
2409+
| Ppeek layout, [[ptr]] ->
2410+
let kind = standard_int_or_float_of_peek_or_poke layout in
2411+
[Unary (Peek kind, ptr)]
2412+
| Ppoke layout, [[ptr]; [new_value]] ->
2413+
let kind = standard_int_or_float_of_peek_or_poke layout in
2414+
[Binary (Poke kind, ptr, new_value)]
23992415
| ( ( Pdivbint { is_safe = Unsafe; size = _; mode = _ }
24002416
| Pmodbint { is_safe = Unsafe; size = _; mode = _ }
24012417
| Psetglobal _ | Praise _ | Pccall _ ),
@@ -2428,7 +2444,7 @@ let convert_lprim ~big_endian (prim : L.primitive) (args : Simple.t list list)
24282444
| Pufloatfield _ | Patomic_load _ | Pmixedfield _
24292445
| Preinterpret_unboxed_int64_as_tagged_int63
24302446
| Preinterpret_tagged_int63_as_unboxed_int64
2431-
| Parray_element_size_in_bytes _ ),
2447+
| Parray_element_size_in_bytes _ | Ppeek _ ),
24322448
([] | _ :: _ :: _ | [([] | _ :: _ :: _)]) ) ->
24332449
Misc.fatal_errorf
24342450
"Closure_conversion.convert_primitive: Wrong arity for unary primitive \
@@ -2471,7 +2487,7 @@ let convert_lprim ~big_endian (prim : L.primitive) (args : Simple.t list list)
24712487
_,
24722488
_ )
24732489
| Pcompare_ints | Pcompare_floats _ | Pcompare_bints _ | Patomic_exchange
2474-
| Patomic_fetch_add ),
2490+
| Patomic_fetch_add | Ppoke _ ),
24752491
( []
24762492
| [_]
24772493
| _ :: _ :: _ :: _

0 commit comments

Comments
 (0)