Skip to content

Commit 443a81c

Browse files
committed
unified unboxed field getters/setters. This will be useful once we have unboxed integers of different sizes
1 parent a228be1 commit 443a81c

File tree

1 file changed

+50
-150
lines changed

1 file changed

+50
-150
lines changed

backend/cmm_helpers.ml

+50-150
Original file line numberDiff line numberDiff line change
@@ -919,32 +919,29 @@ let complex_im c dbg =
919919

920920
(* Unit *)
921921

922-
let return_unit dbg c = Csequence (c, Cconst_int (1, dbg))
922+
let return_unit dbg c =
923+
match c with
924+
| Csequence (_, Cconst_int (1, _)) as c -> c
925+
| c -> Csequence (c, Cconst_int (1, dbg))
926+
927+
let memory_chunk_width_in_bytes : memory_chunk -> int = function
928+
| Byte_unsigned | Byte_signed -> 1
929+
| Sixteen_unsigned | Sixteen_signed -> 2
930+
| Thirtytwo_unsigned | Thirtytwo_signed -> 4
931+
| Single { reg = Float64 | Float32 } -> 4
932+
| Word_int -> size_int
933+
| Word_val -> size_addr
934+
| Double -> size_float
935+
| Onetwentyeight_unaligned | Onetwentyeight_aligned -> size_vec128
923936

924937
let strided_field_address ptr ~index ~stride dbg =
925938
if index * stride = 0
926939
then ptr
927940
else Cop (Cadda, [ptr; Cconst_int (index * stride, dbg)], dbg)
928941

929942
let field_address ?(memory_chunk = Word_val) ptr n dbg =
930-
if n = 0
931-
then ptr
932-
else
933-
let field_size_in_bytes =
934-
match memory_chunk with
935-
| Byte_unsigned | Byte_signed -> 1
936-
| Sixteen_unsigned | Sixteen_signed -> 2
937-
| Thirtytwo_unsigned | Thirtytwo_signed -> 4
938-
| Single { reg = Float64 | Float32 } ->
939-
assert (size_float = 8);
940-
(* unclear what to do if this is false *)
941-
size_float / 2
942-
| Word_int -> size_int
943-
| Word_val -> size_addr
944-
| Double -> size_float
945-
| Onetwentyeight_unaligned | Onetwentyeight_aligned -> size_vec128
946-
in
947-
Cop (Cadda, [ptr; Cconst_int (n * field_size_in_bytes, dbg)], dbg)
943+
strided_field_address ptr dbg ~index:n
944+
~stride:(memory_chunk_width_in_bytes memory_chunk)
948945

949946
let get_field_gen_given_memory_chunk memory_chunk mutability ptr n dbg =
950947
Cop
@@ -1405,147 +1402,50 @@ let unboxed_int64_or_nativeint_array_set ~has_custom_ops arr ~index ~new_value
14051402
in
14061403
int_array_set arr index new_value dbg)))
14071404

1408-
(* Get the field of a block given a possibly inconstant index *)
1405+
let get_field_unboxed ~dbg memory_chunk mutability block ~index_in_words =
1406+
if Arch.big_endian && memory_chunk_width_in_bytes memory_chunk <> size_addr
1407+
then
1408+
(* CR layouts v5.1: Properly support big-endian. *)
1409+
Misc.fatal_error
1410+
"Unboxed non-word size integer fields are only supported on \
1411+
little-endian architectures";
1412+
(* CR layouts v5.1: We'll need to vary log2_size_addr among other things to
1413+
efficiently pack small integers *)
1414+
let field_address =
1415+
assert (size_float = size_addr);
1416+
array_indexing log2_size_addr block index_in_words dbg
1417+
in
1418+
Cop
1419+
(Cload { memory_chunk; mutability; is_atomic = false }, [field_address], dbg)
14091420

14101421
let get_field_computed imm_or_ptr mutability ~block ~index dbg =
14111422
let memory_chunk =
14121423
match imm_or_ptr with
14131424
| Lambda.Immediate -> Word_int
14141425
| Lambda.Pointer -> Word_val
14151426
in
1416-
let field_address = array_indexing log2_size_addr block index dbg in
1417-
Cop
1418-
(Cload { memory_chunk; mutability; is_atomic = false }, [field_address], dbg)
1419-
1420-
(* Getters for unboxed int fields *)
1421-
1422-
let get_field_unboxed_int32 mutability ~block ~index dbg =
1423-
let memory_chunk = Thirtytwo_signed in
1424-
(* CR layouts v5.1: Properly support big-endian. *)
1425-
if Arch.big_endian
1426-
then
1427-
Misc.fatal_error
1428-
"Unboxed int32 fields only supported on little-endian architectures";
1429-
(* CR layouts v5.1: We'll need to vary log2_size_addr to efficiently pack
1430-
* int32s *)
1431-
let field_address = array_indexing log2_size_addr block index dbg in
1432-
Cop
1433-
(Cload { memory_chunk; mutability; is_atomic = false }, [field_address], dbg)
1434-
1435-
let get_field_unboxed_int64_or_nativeint mutability ~block ~index dbg =
1436-
let memory_chunk = Word_int in
1437-
let field_address = array_indexing log2_size_addr block index dbg in
1438-
Cop
1439-
(Cload { memory_chunk; mutability; is_atomic = false }, [field_address], dbg)
1440-
1441-
(* Setters for unboxed int fields *)
1442-
1443-
let setfield_unboxed_int32 arr ofs newval dbg =
1444-
(* CR layouts v5.1: Properly support big-endian. *)
1445-
if Arch.big_endian
1446-
then
1447-
Misc.fatal_error
1448-
"Unboxed int32 fields only supported on little-endian architectures";
1449-
(* CR layouts v5.1: We will need to vary log2_size_addr when int32 fields are
1450-
efficiently packed. *)
1451-
return_unit dbg
1452-
(Cop
1453-
( Cstore (Thirtytwo_signed, Assignment),
1454-
[array_indexing log2_size_addr arr ofs dbg; newval],
1455-
dbg ))
1456-
1457-
let setfield_unboxed_int64_or_nativeint arr ofs newval dbg =
1458-
return_unit dbg
1459-
(Cop
1460-
( Cstore (Word_int, Assignment),
1461-
[array_indexing log2_size_addr arr ofs dbg; newval],
1462-
dbg ))
1463-
1464-
(* Getters and setters for unboxed float32 fields *)
1465-
1466-
let get_field_unboxed_float32 mutability ~block ~index dbg =
1467-
(* CR layouts v5.1: Properly support big-endian. *)
1468-
if Arch.big_endian
1469-
then
1470-
Misc.fatal_error
1471-
"Unboxed float32 fields only supported on little-endian architectures";
1472-
let memory_chunk = Single { reg = Float32 } in
1473-
(* CR layouts v5.1: We'll need to vary log2_size_addr to efficiently pack
1474-
* float32s *)
1475-
let field_address = array_indexing log2_size_addr block index dbg in
1476-
Cop
1477-
(Cload { memory_chunk; mutability; is_atomic = false }, [field_address], dbg)
1478-
1479-
let setfield_unboxed_float32 arr ofs newval dbg =
1480-
(* CR layouts v5.1: Properly support big-endian. *)
1481-
if Arch.big_endian
1482-
then
1483-
Misc.fatal_error
1484-
"Unboxed float32 fields only supported on little-endian architectures";
1485-
(* CR layouts v5.1: We will need to vary log2_size_addr when float32 fields
1486-
are efficiently packed. *)
1487-
return_unit dbg
1488-
(Cop
1489-
( Cstore (Single { reg = Float32 }, Assignment),
1490-
[array_indexing log2_size_addr arr ofs dbg; newval],
1491-
dbg ))
1492-
1493-
(* Getters and setters for unboxed vec128 fields *)
1494-
1495-
let get_field_unboxed_vec128 mutability ~block ~index_in_words dbg =
1496-
(* CR layouts v5.1: Properly support big-endian. *)
1497-
if Arch.big_endian
1498-
then
1499-
Misc.fatal_error
1500-
"Unboxed vec128 fields only supported on little-endian architectures";
1501-
let memory_chunk = Onetwentyeight_unaligned in
1502-
let field_address = array_indexing log2_size_addr block index_in_words dbg in
1503-
Cop
1504-
(Cload { memory_chunk; mutability; is_atomic = false }, [field_address], dbg)
1505-
1506-
let setfield_unboxed_vec128 arr ~index_in_words newval dbg =
1507-
(* CR layouts v5.1: Properly support big-endian. *)
1508-
if Arch.big_endian
1509-
then
1510-
Misc.fatal_error
1511-
"Unboxed vec128 fields only supported on little-endian architectures";
1512-
let field_address = array_indexing log2_size_addr arr index_in_words dbg in
1513-
return_unit dbg
1514-
(Cop
1515-
( Cstore (Onetwentyeight_unaligned, Assignment),
1516-
[field_address; newval],
1517-
dbg ))
1518-
1519-
let get_field_unboxed ~dbg memory_chunk mutability block ~index_in_words =
1520-
match (memory_chunk : memory_chunk) with
1521-
| Single { reg = Float32 } ->
1522-
get_field_unboxed_float32 mutability ~block ~index:index_in_words dbg
1523-
| Double ->
1524-
unboxed_float_array_ref mutability ~block ~index:index_in_words dbg
1525-
| Onetwentyeight_unaligned | Onetwentyeight_aligned ->
1526-
get_field_unboxed_vec128 mutability ~block ~index_in_words dbg
1527-
| Thirtytwo_signed ->
1528-
get_field_unboxed_int32 mutability ~block ~index:index_in_words dbg
1529-
| Word_int ->
1530-
get_field_unboxed_int64_or_nativeint mutability ~block ~index:index_in_words
1531-
dbg
1532-
| Word_val ->
1533-
Misc.fatal_error "cannot use get_field_unboxed with a heap block"
1534-
| _ -> Misc.fatal_error "get_field_unboxed: unexpected memory chunk"
1427+
get_field_unboxed ~dbg memory_chunk mutability block ~index_in_words:index
15351428

15361429
let set_field_unboxed ~dbg memory_chunk block ~index_in_words newval =
1537-
match (memory_chunk : memory_chunk) with
1538-
| Single { reg = Float32 } ->
1539-
setfield_unboxed_float32 block index_in_words newval dbg
1540-
| Double -> float_array_set block index_in_words newval dbg
1541-
| Onetwentyeight_unaligned | Onetwentyeight_aligned ->
1542-
setfield_unboxed_vec128 block ~index_in_words newval dbg
1543-
| Thirtytwo_signed -> setfield_unboxed_int32 block index_in_words newval dbg
1544-
| Word_int ->
1545-
setfield_unboxed_int64_or_nativeint block index_in_words newval dbg
1430+
match memory_chunk with
15461431
| Word_val ->
1547-
Misc.fatal_error "cannot use set_field_unboxed with a heap block"
1548-
| _ -> Misc.fatal_error "set_field_unboxed : unexpected memory chunk"
1432+
Misc.fatal_error "Attempted to set a value via [setfield_unboxed]"
1433+
| memory_chunk ->
1434+
let size_in_bytes = memory_chunk_width_in_bytes memory_chunk in
1435+
(* CR layouts v5.1: Properly support big-endian. *)
1436+
if Arch.big_endian && size_in_bytes <> size_addr
1437+
then
1438+
Misc.fatal_error
1439+
"Unboxed non-word-size fields are only supported on little-endian \
1440+
architectures";
1441+
(* CR layouts v5.1: We will need to vary log2_size_addr, among other things,
1442+
when small fields are efficiently packed. *)
1443+
let field_address =
1444+
array_indexing log2_size_addr block index_in_words dbg
1445+
in
1446+
let newval = if size_in_bytes = 4 then low_32 dbg newval else newval in
1447+
return_unit dbg
1448+
(Cop (Cstore (memory_chunk, Assignment), [field_address; newval], dbg))
15491449

15501450
(* String length *)
15511451

0 commit comments

Comments
 (0)