@@ -1025,6 +1025,22 @@ let custom_ops_unboxed_int32_odd_array =
1025
1025
Cconst_int (Config. custom_ops_struct_size, Debuginfo. none) ],
1026
1026
Debuginfo. none )
1027
1027
1028
+ (* caml_unboxed_float32_array_ops refers to the first element of an array of two
1029
+ custom ops. The array index indicates the number of (invalid) tailing
1030
+ float32s (0 or 1). *)
1031
+ let custom_ops_unboxed_float32_array =
1032
+ Cconst_symbol
1033
+ (Cmm. global_symbol " caml_unboxed_float32_array_ops" , Debuginfo. none)
1034
+
1035
+ let custom_ops_unboxed_float32_even_array = custom_ops_unboxed_float32_array
1036
+
1037
+ let custom_ops_unboxed_float32_odd_array =
1038
+ Cop
1039
+ ( Caddi ,
1040
+ [ custom_ops_unboxed_float32_array;
1041
+ Cconst_int (Config. custom_ops_struct_size, Debuginfo. none) ],
1042
+ Debuginfo. none )
1043
+
1028
1044
let custom_ops_unboxed_int64_array =
1029
1045
Cconst_symbol
1030
1046
(Cmm. global_symbol " caml_unboxed_int64_array_ops" , Debuginfo. none)
@@ -1033,7 +1049,8 @@ let custom_ops_unboxed_nativeint_array =
1033
1049
Cconst_symbol
1034
1050
(Cmm. global_symbol " caml_unboxed_nativeint_array_ops" , Debuginfo. none)
1035
1051
1036
- let unboxed_int32_array_length arr dbg =
1052
+ let unboxed_packed_array_length arr dbg ~custom_ops_base_symbol
1053
+ ~elements_per_word =
1037
1054
(* Checking custom_ops is needed to determine if the array contains an odd or
1038
1055
even number of elements *)
1039
1056
let res =
@@ -1054,17 +1071,27 @@ let unboxed_int32_array_length arr dbg =
1054
1071
( VP. create custom_ops_index_var,
1055
1072
(* compute index into custom ops array *)
1056
1073
lsr_int
1057
- (sub_int (Cvar custom_ops_var)
1058
- custom_ops_unboxed_int32_array dbg)
1074
+ (sub_int (Cvar custom_ops_var) custom_ops_base_symbol dbg)
1059
1075
(int ~dbg custom_ops_size_log2)
1060
1076
dbg,
1061
1077
(* subtract index from length in int32s *)
1062
1078
sub_int
1063
- (mul_int (Cvar num_words_var) (int ~dbg 2 ) dbg)
1079
+ (mul_int (Cvar num_words_var)
1080
+ (int ~dbg elements_per_word)
1081
+ dbg)
1064
1082
(Cvar custom_ops_index_var) dbg ) ) ))
1065
1083
in
1066
1084
tag_int res dbg
1067
1085
1086
+ let unboxed_int32_array_length =
1087
+ unboxed_packed_array_length
1088
+ ~custom_ops_base_symbol: custom_ops_unboxed_int32_array ~elements_per_word: 2
1089
+
1090
+ let unboxed_float32_array_length =
1091
+ unboxed_packed_array_length
1092
+ ~custom_ops_base_symbol: custom_ops_unboxed_float32_array
1093
+ ~elements_per_word: 2
1094
+
1068
1095
let unboxed_int64_or_nativeint_array_length arr dbg =
1069
1096
let res =
1070
1097
bind " arr" arr (fun arr ->
@@ -1179,24 +1206,31 @@ let sign_extend_32 dbg e =
1179
1206
[Cop (Clsl , [e; Cconst_int (32 , dbg)], dbg); Cconst_int (32 , dbg)],
1180
1207
dbg )
1181
1208
1182
- let unboxed_int32_array_ref arr index dbg =
1209
+ let unboxed_packed_array_ref arr index dbg ~ memory_chunk ~ elements_per_word =
1183
1210
bind " arr" arr (fun arr ->
1184
1211
bind " index" index (fun index ->
1185
1212
let index =
1186
- (* Need to skip the custom_operations field. We add 2 element
1187
- offsets not 1 since the call to [array_indexing], below, is in
1188
- terms of 32-bit words. Then we multiply the offset by 2 to get 4
1189
- since we are manipulating a tagged int. *)
1190
- add_int index (int ~dbg 4 ) dbg
1213
+ (* Need to skip the custom_operations field. We add
1214
+ elements_per_word offsets not 1 since the call to
1215
+ [array_indexing], below, is in terms of elements. Then we
1216
+ multiply the offset by 2 since we are manipulating a tagged
1217
+ int. *)
1218
+ add_int index (int ~dbg (elements_per_word * 2 )) dbg
1191
1219
in
1192
1220
let log2_size_addr = 2 in
1193
- (* N.B. The resulting value will be sign extended by the code
1194
- generated for a [Thirtytwo_signed] load. *)
1195
1221
Cop
1196
- ( mk_load_mut Thirtytwo_signed ,
1222
+ ( mk_load_mut memory_chunk ,
1197
1223
[array_indexing log2_size_addr arr index dbg],
1198
1224
dbg )))
1199
1225
1226
+ let unboxed_int32_array_ref =
1227
+ unboxed_packed_array_ref ~memory_chunk: Thirtytwo_signed ~elements_per_word: 2
1228
+
1229
+ let unboxed_float32_array_ref =
1230
+ unboxed_packed_array_ref
1231
+ ~memory_chunk: (Single { reg = Float32 })
1232
+ ~elements_per_word: 2
1233
+
1200
1234
let unboxed_int64_or_nativeint_array_ref arr index dbg =
1201
1235
bind " arr" arr (fun arr ->
1202
1236
bind " index" index (fun index ->
@@ -1207,20 +1241,29 @@ let unboxed_int64_or_nativeint_array_ref arr index dbg =
1207
1241
in
1208
1242
int_array_ref arr index dbg))
1209
1243
1210
- let unboxed_int32_array_set arr ~index ~new_value dbg =
1244
+ let unboxed_packed_array_set arr ~index ~new_value dbg ~memory_chunk
1245
+ ~elements_per_word =
1211
1246
bind " arr" arr (fun arr ->
1212
1247
bind " index" index (fun index ->
1213
1248
bind " new_value" new_value (fun new_value ->
1214
1249
let index =
1215
- (* See comment in [unboxed_int32_array_ref ]. *)
1216
- add_int index (int ~dbg 4 ) dbg
1250
+ (* See comment in [unboxed_packed_array_ref ]. *)
1251
+ add_int index (int ~dbg (elements_per_word * 2 ) ) dbg
1217
1252
in
1218
1253
let log2_size_addr = 2 in
1219
1254
Cop
1220
- ( Cstore (Thirtytwo_signed , Assignment ),
1255
+ ( Cstore (memory_chunk , Assignment ),
1221
1256
[array_indexing log2_size_addr arr index dbg; new_value],
1222
1257
dbg ))))
1223
1258
1259
+ let unboxed_int32_array_set =
1260
+ unboxed_packed_array_set ~memory_chunk: Thirtytwo_signed ~elements_per_word: 2
1261
+
1262
+ let unboxed_float32_array_set =
1263
+ unboxed_packed_array_set
1264
+ ~memory_chunk: (Single { reg = Float32 })
1265
+ ~elements_per_word: 2
1266
+
1224
1267
let unboxed_int64_or_nativeint_array_set arr ~index ~new_value dbg =
1225
1268
bind " arr" arr (fun arr ->
1226
1269
bind " index" index (fun index ->
@@ -1258,6 +1301,14 @@ let get_field_unboxed_int32 mutability ~block ~index dbg =
1258
1301
Cop
1259
1302
(Cload { memory_chunk; mutability; is_atomic = false }, [field_address], dbg)
1260
1303
1304
+ let get_field_unboxed_float32 mutability ~block ~index dbg =
1305
+ let memory_chunk = Single { reg = Float32 } in
1306
+ (* CR layouts v5.1: We'll need to vary log2_size_addr to efficiently pack
1307
+ * float32s *)
1308
+ let field_address = array_indexing log2_size_addr block index dbg in
1309
+ Cop
1310
+ (Cload { memory_chunk; mutability; is_atomic = false }, [field_address], dbg)
1311
+
1261
1312
let get_field_unboxed_int64_or_nativeint mutability ~block ~index dbg =
1262
1313
let memory_chunk = Word_int in
1263
1314
let field_address = array_indexing log2_size_addr block index dbg in
@@ -1280,6 +1331,15 @@ let setfield_unboxed_int32 arr ofs newval dbg =
1280
1331
[array_indexing log2_size_addr arr ofs dbg; newval],
1281
1332
dbg ))
1282
1333
1334
+ let setfield_unboxed_float32 arr ofs newval dbg =
1335
+ (* CR layouts v5.1: We will need to vary log2_size_addr when float32 fields
1336
+ are efficiently packed. *)
1337
+ return_unit dbg
1338
+ (Cop
1339
+ ( Cstore (Single { reg = Float32 }, Assignment ),
1340
+ [array_indexing log2_size_addr arr ofs dbg; newval],
1341
+ dbg ))
1342
+
1283
1343
let setfield_unboxed_int64_or_nativeint arr ofs newval dbg =
1284
1344
return_unit dbg
1285
1345
(Cop
@@ -3076,9 +3136,7 @@ let arraylength kind arg dbg =
3076
3136
(* Note: we only support 64 bit targets now, so this is ok for
3077
3137
Punboxedfloatarray *)
3078
3138
Cop (Cor , [float_array_length_shifted hdr dbg; Cconst_int (1 , dbg)], dbg)
3079
- | Punboxedfloatarray Pfloat32 ->
3080
- (* CR mslater: (float32) unboxed arrays *)
3081
- assert false
3139
+ | Punboxedfloatarray Pfloat32 -> unboxed_float32_array_length arg dbg
3082
3140
| Punboxedintarray Pint64 | Punboxedintarray Pnativeint ->
3083
3141
unboxed_int64_or_nativeint_array_length arg dbg
3084
3142
| Punboxedintarray Pint32 -> unboxed_int32_array_length arg dbg
@@ -4006,6 +4064,22 @@ let allocate_unboxed_int32_array ~elements (mode : Lambda.alloc_mode) dbg =
4006
4064
in
4007
4065
Cop (Calloc mode, Cconst_natint (header, dbg) :: custom_ops :: payload, dbg)
4008
4066
4067
+ let allocate_unboxed_float32_array ~elements (mode : Lambda.alloc_mode ) dbg =
4068
+ let header =
4069
+ let size = 1 (* custom_ops field *) + ((List. length elements + 1 ) / 2 ) in
4070
+ match mode with
4071
+ | Alloc_heap -> custom_header ~size
4072
+ | Alloc_local -> custom_local_header ~size
4073
+ in
4074
+ let custom_ops =
4075
+ (* For odd-length unboxed float32 arrays there are 32 bits spare at the end
4076
+ of the block, which are never read. *)
4077
+ if List. length elements mod 2 = 0
4078
+ then custom_ops_unboxed_float32_even_array
4079
+ else custom_ops_unboxed_float32_odd_array
4080
+ in
4081
+ Cop (Calloc mode, Cconst_natint (header, dbg) :: custom_ops :: elements, dbg)
4082
+
4009
4083
let allocate_unboxed_int64_or_nativeint_array custom_ops ~elements
4010
4084
(mode : Lambda.alloc_mode ) dbg =
4011
4085
let header =
0 commit comments