@@ -52,38 +52,127 @@ let bint_shift bi prim arg1 arg2 =
52
52
(Binary (Int_shift (C. standard_int_of_boxed_integer bi, prim),
53
53
unbox_bint bi arg1, untag_int arg2))
54
54
55
- let string_or_bytes_access_validity_condition str kind index : H.expr_primitive =
55
+ (* offset to substract to a string length depending
56
+ on the size of the read/write *)
57
+ let length_offset_of_size size =
58
+ let offset =
59
+ match (size : Flambda_primitive.string_accessor_width ) with
60
+ | Eight -> 0
61
+ | Sixteen -> 1
62
+ | Thirty_two -> 3
63
+ | Sixty_four -> 7
64
+ in
65
+ Immediate. int (Targetint.OCaml. of_int offset)
66
+
67
+ (* equivalent to the one in `cmm_helpers.ml` *)
68
+ let max_or_zero size_int x =
69
+ let register_bitsize_minus_one =
70
+ H. Simple (Simple. const (Naked_immediate (
71
+ Immediate. int (Targetint.OCaml. of_int (size_int * 8 - 1 )))))
72
+ in
73
+ let sign =
74
+ H. Prim (Binary (Int_shift (Naked_nativeint , Asr ),
75
+ x, register_bitsize_minus_one)) in
76
+ let minus_one =
77
+ H. Simple (Simple. const (Naked_nativeint (Targetint. of_int (- 1 ))))
78
+ in
79
+ let sign_negation =
80
+ H. Prim (Binary (Int_arith (Naked_nativeint , Xor ),
81
+ sign, minus_one)) in
82
+ let ret =
83
+ H. Prim (Binary (Int_arith (Naked_nativeint , And ),
84
+ sign_negation, x)) in
85
+ ret
86
+
87
+ (* actual (strict) upper bound for an index in a string read/write *)
88
+ let actual_max_length size_int size length =
89
+ if size = (Eight : Flambda_primitive.string_accessor_width ) then
90
+ length (* micro-optimization *)
91
+ else begin
92
+ let offset = length_offset_of_size size in
93
+ let reduced_length =
94
+ H. Prim (Binary (Int_arith (Naked_immediate , Sub ),
95
+ length, Simple (Simple. const (Naked_immediate offset))))
96
+ in
97
+ let reduced_length_nativeint =
98
+ H. Prim (Unary (Num_conv { src = Naked_immediate ; dst = Naked_nativeint },
99
+ reduced_length))
100
+ in
101
+ let nativeint_res = max_or_zero size_int reduced_length_nativeint in
102
+ H. Prim (Unary (Num_conv { src = Naked_nativeint ; dst = Naked_immediate },
103
+ nativeint_res))
104
+ end
105
+
106
+ let string_or_bytes_access_validity_condition
107
+ size_int str kind size index : H.expr_primitive =
56
108
Binary (Int_comp (I. Naked_immediate , Unsigned , Lt ),
57
109
untag_int index,
58
- (Prim (Unary (String_length kind, str))))
110
+ actual_max_length size_int size (Prim (Unary (String_length kind, str))))
59
111
60
- let string_or_bytes_ref kind arg1 arg2 dbg : H.expr_primitive =
112
+ let string_or_bytes_ref size_int kind arg1 arg2 dbg : H.expr_primitive =
61
113
Checked {
62
114
primitive =
63
115
tag_int (Binary (String_or_bigstring_load (kind, Eight ), arg1, arg2));
64
116
validity_conditions = [
65
- string_or_bytes_access_validity_condition arg1 String arg2;
117
+ string_or_bytes_access_validity_condition size_int arg1 String Eight arg2;
66
118
];
67
119
failure = Index_out_of_bounds ;
68
120
dbg;
69
121
}
70
122
71
- let bigstring_access_validity_condition bstr index : H.expr_primitive =
123
+ let bigstring_access_validity_condition size_int bstr size index : H.expr_primitive =
72
124
Binary (Int_comp (I. Naked_immediate , Unsigned , Lt ),
73
125
untag_int index,
74
- (Prim (Unary (Bigarray_length { dimension = 1 ; }, bstr))))
126
+ actual_max_length size_int size
127
+ (Prim (Unary (Bigarray_length { dimension = 1 ; }, bstr))))
75
128
76
129
(* CR mshinwell: Same problems as previous function *)
77
- let bigstring_ref size arg1 arg2 dbg : H.expr_primitive =
130
+ let bigstring_ref size_int size arg1 arg2 dbg : H.expr_primitive =
131
+ let wrap =
132
+ match (size : Flambda_primitive.string_accessor_width ) with
133
+ | Eight | Sixteen -> tag_int
134
+ | Thirty_two -> box_bint Pint32
135
+ | Sixty_four -> box_bint Pint64
136
+ in
78
137
Checked {
79
- primitive = Binary (String_or_bigstring_load (Bigstring , size), arg1, arg2);
138
+ primitive =
139
+ wrap (Binary (String_or_bigstring_load (Bigstring , size), arg1, arg2));
80
140
validity_conditions = [
81
- bigstring_access_validity_condition arg1 arg2;
141
+ bigstring_access_validity_condition size_int arg1 size arg2;
82
142
];
83
143
failure = Index_out_of_bounds ;
84
144
dbg;
85
145
}
86
146
147
+ let boxable_number_of_naked_number_kind k : K.Boxable_number.t =
148
+ match (k : K.Naked_number_kind.t ) with
149
+ | Naked_immediate -> Untagged_immediate
150
+ | Naked_float -> Naked_float
151
+ | Naked_int32 -> Naked_int32
152
+ | Naked_int64 -> Naked_int64
153
+ | Naked_nativeint -> Naked_nativeint
154
+
155
+ let bigarray_wrap_of_kind kind =
156
+ match P. element_kind_of_bigarray_kind kind with
157
+ | Value -> Fun. id
158
+ | Fabricated -> assert false
159
+ | Naked_number k ->
160
+ let bi = boxable_number_of_naked_number_kind k in
161
+ (fun arg -> H. Unary (Box_number bi, Prim arg))
162
+
163
+ let bigarray_unwrap_of_kind kind =
164
+ match P. element_kind_of_bigarray_kind kind with
165
+ | Value -> Fun. id
166
+ | Fabricated -> assert false
167
+ | Naked_number k ->
168
+ let bi = boxable_number_of_naked_number_kind k in
169
+ (fun arg -> H. Prim (Unary (Unbox_number bi, arg)))
170
+
171
+ let bigarray_map_last f l =
172
+ match List. rev l with
173
+ | [] -> assert false
174
+ | h :: r -> List. rev (f h :: r)
175
+
87
176
let convert_lprim ~backend (prim : L.primitive ) (args : Simple.t list )
88
177
(dbg : Debuginfo.t ) : H.expr_primitive =
89
178
let args = List. map (fun arg : H. simple_or_prim -> Simple arg) args in
@@ -215,9 +304,11 @@ let convert_lprim ~backend (prim : L.primitive) (args : Simple.t list)
215
304
| Pbytesrefu , [arg1; arg2] ->
216
305
tag_int (Binary (String_or_bigstring_load (Bytes , Eight ), arg1, arg2))
217
306
| Pbytesrefs , [arg1; arg2] ->
218
- string_or_bytes_ref Bytes arg1 arg2 dbg
307
+ let module B = (val backend : Flambda2_backend_intf .S ) in
308
+ string_or_bytes_ref B .size_int Bytes arg1 arg2 dbg
219
309
| Pstringrefs , [arg1; arg2 ] ->
220
- string_or_bytes_ref String arg1 arg2 dbg
310
+ let module B = (val backend : Flambda2_backend_intf .S ) in
311
+ string_or_bytes_ref B .size_int String arg1 arg2 dbg
221
312
| Pstring_load_16 true (* unsafe *) , [arg1; arg2 ]
222
313
| Pbytes_load_16 true (* unsafe *) , [arg1; arg2 ] ->
223
314
tag_int (Binary (String_or_bigstring_load (String , Sixteen ), arg1 , arg2 ))
@@ -232,72 +323,78 @@ let convert_lprim ~backend (prim : L.primitive) (args : Simple.t list)
232
323
Prim (Binary (String_or_bigstring_load (String , Sixty_four ),
233
324
arg1 , arg2 )))
234
325
| Pstring_load_16 false , [str; index ] ->
326
+ let module B = (val backend : Flambda2_backend_intf .S ) in
235
327
Checked {
236
328
primitive =
237
329
tag_int
238
330
(Binary (String_or_bigstring_load (String , Sixteen ), str, index));
239
331
validity_conditions = [
240
- string_or_bytes_access_validity_condition str String index;
332
+ string_or_bytes_access_validity_condition B. size_int str String Sixteen index;
241
333
];
242
334
failure = Index_out_of_bounds ;
243
335
dbg;
244
336
}
245
337
| Pstring_load_32 false , [str; index ] ->
338
+ let module B = (val backend : Flambda2_backend_intf .S ) in
246
339
Checked {
247
340
primitive =
248
341
Unary (Box_number Naked_int32 ,
249
342
Prim (Binary (String_or_bigstring_load (String , Thirty_two ),
250
343
str, index)));
251
344
validity_conditions = [
252
- string_or_bytes_access_validity_condition str String index;
345
+ string_or_bytes_access_validity_condition B. size_int str String Thirty_two index;
253
346
];
254
347
failure = Index_out_of_bounds ;
255
348
dbg;
256
349
}
257
350
| Pstring_load_64 false , [str; index ] ->
351
+ let module B = (val backend : Flambda2_backend_intf .S ) in
258
352
Checked {
259
353
primitive =
260
354
Unary (Box_number Naked_int64 ,
261
355
Prim (Binary (String_or_bigstring_load (String , Sixty_four ),
262
356
str, index)));
263
357
validity_conditions = [
264
- string_or_bytes_access_validity_condition str String index;
358
+ string_or_bytes_access_validity_condition B. size_int str String Sixty_four index;
265
359
];
266
360
failure = Index_out_of_bounds ;
267
361
dbg;
268
362
}
269
363
(* CR mshinwell: factor out *)
270
364
| Pbytes_load_16 false , [bytes; index ] ->
365
+ let module B = (val backend : Flambda2_backend_intf .S ) in
271
366
Checked {
272
367
primitive =
273
368
tag_int
274
369
(Binary (String_or_bigstring_load (Bytes , Sixteen ), bytes, index));
275
370
validity_conditions = [
276
- string_or_bytes_access_validity_condition bytes Bytes index;
371
+ string_or_bytes_access_validity_condition B. size_int bytes Bytes Sixteen index;
277
372
];
278
373
failure = Index_out_of_bounds ;
279
374
dbg;
280
375
}
281
376
| Pbytes_load_32 false , [bytes; index ] ->
377
+ let module B = (val backend : Flambda2_backend_intf .S ) in
282
378
Checked {
283
379
primitive =
284
380
Unary (Box_number Naked_int32 ,
285
381
Prim (Binary (String_or_bigstring_load (Bytes , Thirty_two ),
286
382
bytes, index)));
287
383
validity_conditions = [
288
- string_or_bytes_access_validity_condition bytes Bytes index;
384
+ string_or_bytes_access_validity_condition B. size_int bytes Bytes Thirty_two index;
289
385
];
290
386
failure = Index_out_of_bounds ;
291
387
dbg;
292
388
}
293
389
| Pbytes_load_64 false , [bytes; index ] ->
390
+ let module B = (val backend : Flambda2_backend_intf .S ) in
294
391
Checked {
295
392
primitive =
296
393
Unary (Box_number Naked_int64 ,
297
394
Prim (Binary (String_or_bigstring_load (Bytes , Sixty_four ),
298
395
bytes, index)));
299
396
validity_conditions = [
300
- string_or_bytes_access_validity_condition bytes Bytes index;
397
+ string_or_bytes_access_validity_condition B. size_int bytes Bytes Sixty_four index;
301
398
];
302
399
failure = Index_out_of_bounds ;
303
400
dbg;
@@ -313,34 +410,37 @@ let convert_lprim ~backend (prim : L.primitive) (args : Simple.t list)
313
410
Ternary (Bytes_or_bigstring_set (Bytes , Sixty_four ),
314
411
bytes , index , Prim (Unary (Unbox_number Naked_int64 , new_value )))
315
412
| Pbytes_set_16 false , [bytes; index ; new_value ] ->
413
+ let module B = (val backend : Flambda2_backend_intf .S ) in
316
414
Checked {
317
415
primitive =
318
416
Ternary (Bytes_or_bigstring_set (Bytes , Sixteen ),
319
417
bytes, index, untag_int new_value);
320
418
validity_conditions = [
321
- string_or_bytes_access_validity_condition bytes Bytes index;
419
+ string_or_bytes_access_validity_condition B. size_int bytes Bytes Sixteen index;
322
420
];
323
421
failure = Index_out_of_bounds ;
324
422
dbg;
325
423
}
326
424
| Pbytes_set_32 false , [bytes; index ; new_value ] ->
425
+ let module B = (val backend : Flambda2_backend_intf .S ) in
327
426
Checked {
328
427
primitive =
329
428
Ternary (Bytes_or_bigstring_set (Bytes , Thirty_two ),
330
429
bytes, index, Prim (Unary (Unbox_number Naked_int32 , new_value)));
331
430
validity_conditions = [
332
- string_or_bytes_access_validity_condition bytes Bytes index;
431
+ string_or_bytes_access_validity_condition B. size_int bytes Bytes Thirty_two index;
333
432
];
334
433
failure = Index_out_of_bounds ;
335
434
dbg;
336
435
}
337
436
| Pbytes_set_64 false , [bytes; index ; new_value ] ->
437
+ let module B = (val backend : Flambda2_backend_intf .S ) in
338
438
Checked {
339
439
primitive =
340
440
Ternary (Bytes_or_bigstring_set (Bytes , Sixty_four ),
341
441
bytes, index, Prim (Unary (Unbox_number Naked_int64 , new_value)));
342
442
validity_conditions = [
343
- string_or_bytes_access_validity_condition bytes Bytes index;
443
+ string_or_bytes_access_validity_condition B. size_int bytes Bytes Sixty_four index;
344
444
];
345
445
failure = Index_out_of_bounds ;
346
446
dbg;
@@ -631,12 +731,13 @@ let convert_lprim ~backend (prim : L.primitive) (args : Simple.t list)
631
731
Ternary (Bytes_or_bigstring_set (Bytes , Eight ), bytes, index,
632
732
untag_int new_value)
633
733
| Pbytessets , [bytes; index; new_value] ->
734
+ let module B = (val backend : Flambda2_backend_intf .S ) in
634
735
Checked {
635
736
primitive =
636
737
Ternary (Bytes_or_bigstring_set (Bytes , Eight ),
637
738
bytes, index, untag_int new_value);
638
739
validity_conditions = [
639
- string_or_bytes_access_validity_condition bytes Bytes index;
740
+ string_or_bytes_access_validity_condition B. size_int bytes Bytes Eight index;
640
741
];
641
742
failure = Index_out_of_bounds ;
642
743
dbg;
@@ -694,64 +795,73 @@ let convert_lprim ~backend (prim : L.primitive) (args : Simple.t list)
694
795
let is_safe : P.is_safe = if unsafe then Unsafe else Safe in
695
796
let kind = C. convert_bigarray_kind kind in
696
797
let layout = C. convert_bigarray_layout layout in
697
- Variadic (Bigarray_load (is_safe, num_dimensions, kind, layout), args)
798
+ let wrap = bigarray_wrap_of_kind kind in
799
+ wrap (Variadic (Bigarray_load (is_safe, num_dimensions, kind, layout), args))
698
800
| Pbigarrayset (unsafe , num_dimensions , kind , layout ), args ->
699
801
let is_safe : P.is_safe = if unsafe then Unsafe else Safe in
700
802
let kind = C. convert_bigarray_kind kind in
701
803
let layout = C. convert_bigarray_layout layout in
702
- Variadic (Bigarray_set (is_safe, num_dimensions, kind, layout), args)
804
+ let unwrap = bigarray_unwrap_of_kind kind in
805
+ let new_args = bigarray_map_last unwrap args in
806
+ Variadic (Bigarray_set (is_safe, num_dimensions, kind, layout), new_args)
703
807
| Pbigarraydim dimension , [arg] ->
704
808
tag_int (Unary (Bigarray_length { dimension; }, arg))
705
809
| Pbigstring_load_16 true , [arg1; arg2] ->
706
810
Binary (String_or_bigstring_load (Bigstring , Sixteen ), arg1, arg2)
707
811
| Pbigstring_load_16 false , [arg1; arg2] ->
708
- bigstring_ref Sixteen arg1 arg2 dbg
812
+ let module B = (val backend : Flambda2_backend_intf .S ) in
813
+ bigstring_ref B .size_int Sixteen arg1 arg2 dbg
709
814
| Pbigstring_load_32 true , [arg1; arg2 ] ->
710
815
Binary (String_or_bigstring_load (Bigstring , Thirty_two ), arg1 , arg2 )
711
816
| Pbigstring_load_32 false , [arg1; arg2 ] ->
712
- bigstring_ref Thirty_two arg1 arg2 dbg
817
+ let module B = (val backend : Flambda2_backend_intf .S ) in
818
+ bigstring_ref B .size_int Thirty_two arg1 arg2 dbg
713
819
| Pbigstring_load_64 true , [arg1; arg2 ] ->
714
820
Binary (String_or_bigstring_load (Bigstring , Sixty_four ), arg1 , arg2 )
715
821
| Pbigstring_load_64 false , [arg1; arg2 ] ->
716
- bigstring_ref Sixty_four arg1 arg2 dbg
822
+ let module B = (val backend : Flambda2_backend_intf .S ) in
823
+ bigstring_ref B .size_int Sixty_four arg1 arg2 dbg
717
824
| Pbigstring_set_16 true , [bigstring; index ; new_value ] ->
718
825
Ternary (Bytes_or_bigstring_set (Bigstring , Sixteen ),
719
- bigstring, index, new_value)
826
+ bigstring , index , untag_int new_value )
720
827
| Pbigstring_set_32 true , [bigstring; index ; new_value ] ->
721
828
Ternary (Bytes_or_bigstring_set (Bigstring , Thirty_two ),
722
- bigstring, index, new_value)
829
+ bigstring , index , Prim ( Unary ( Unbox_number Naked_int32 , new_value )) )
723
830
| Pbigstring_set_64 true , [bigstring; index ; new_value ] ->
724
831
Ternary (Bytes_or_bigstring_set (Bigstring , Sixty_four ),
725
- bigstring, index, new_value)
832
+ bigstring , index , Prim ( Unary ( Unbox_number Naked_int64 , new_value )) )
726
833
| Pbigstring_set_16 false , [bigstring; index ; new_value ] ->
834
+ let module B = (val backend : Flambda2_backend_intf .S ) in
727
835
Checked {
728
836
primitive =
729
837
Ternary (Bytes_or_bigstring_set (Bigstring , Sixteen ),
730
- bigstring, index, new_value);
838
+ bigstring, index, untag_int new_value);
731
839
validity_conditions = [
732
- bigstring_access_validity_condition bigstring index;
840
+ bigstring_access_validity_condition B. size_int bigstring Sixteen index;
733
841
];
734
842
failure = Index_out_of_bounds ;
735
843
dbg;
736
844
}
737
845
| Pbigstring_set_32 false , [bigstring; index ; new_value ] ->
846
+ let module B = (val backend : Flambda2_backend_intf .S ) in
738
847
Checked {
739
848
primitive =
740
849
Ternary (Bytes_or_bigstring_set (Bigstring , Thirty_two ),
741
- bigstring, index, new_value);
850
+ bigstring, index, Prim ( Unary ( Unbox_number Naked_int32 , new_value)) );
742
851
validity_conditions = [
743
- bigstring_access_validity_condition bigstring index;
852
+ bigstring_access_validity_condition B. size_int bigstring Thirty_two index;
744
853
];
745
854
failure = Index_out_of_bounds ;
746
855
dbg;
747
856
}
748
857
| Pbigstring_set_64 false , [bigstring; index ; new_value ] ->
858
+ let module B = (val backend : Flambda2_backend_intf .S ) in
749
859
Checked {
750
860
primitive =
751
861
Ternary (Bytes_or_bigstring_set (Bigstring , Sixty_four ),
752
- bigstring, index, new_value);
862
+ bigstring, index, Prim ( Unary ( Unbox_number Naked_int64 , new_value)) );
753
863
validity_conditions = [
754
- bigstring_access_validity_condition bigstring index;
864
+ bigstring_access_validity_condition B. size_int bigstring Sixty_four index;
755
865
];
756
866
failure = Index_out_of_bounds ;
757
867
dbg;
0 commit comments