This patch improves on the code generated for an assignment to a component of
a bit-packed array, when lhs and rhs have a different representation.
Executing the following :
gcc -c -gnatG p1.adb | grep -c '\$system__pack_40'
must yield:
1
---
package Conf is
type UINT32_T is mod 2**32;
for UINT32_T'SIZE use 32;
type UINT4_T is mod 2**4;
for UINT4_T'SIZE use 4;
-- record type
type REC_T is record
SIZE : UINT32_T;
V1, V2 : Uint4_T;
end record;
-- packed record type
type REC_pack_T is new REC_T;
for REC_pack_T use record
SIZE at 0 range 0 .. 31; -- 32 bits
V1 at 0 range 32 .. 35; -- 4 bits
V2 at 0 range 36 .. 39; -- 4 bits
end record;
for REC_pack_T'Size use 40;
-- packed arrays of each record type
subtype ARRAY_INDEX_T is Integer range 1 .. 10;
type PARR_R_T is array (ARRAY_INDEX_T) of REC_T;
pragma Pack (PARR_R_T);
type PARR_PR_T is array(ARRAY_INDEX_T) of REC_PACK_T;
pragma Pack (PARR_PR_T);
-- data
Csz : constant Uint32_T := 0;
Cv1 : constant Uint4_T := 0;
Cv2 : constant Uint4_T := 3;
A_R : PARR_R_T := (others => (SIZE => Csz, V1 => Cv1, V2 => Cv2));
--
procedure Assert (Cond : Boolean);
PR : REC_PACK_T;
A_PR : PARR_PR_T;
INDEX : constant := 8;
end;
---
with Conf; use Conf;
procedure P1 is
begin
PR := REC_PACK_T(A_R (INDEX));
A_PR (INDEX) := PR;
end;
Tested on x86_64-pc-linux-gnu, committed on trunk
2011-08-29 Ed Schonberg <[email protected]>
* exp_ch5.adb (Expand_N_Assignment_Statement): if the left-hand side is
an indexed component of a packed array whose element type is a record
with a representation clause different from that of the right-hand
side, generate a temporary to minimuze the number of bit-field
operations generated.
Index: exp_ch5.adb
===================================================================
--- exp_ch5.adb (revision 178177)
+++ exp_ch5.adb (working copy)
@@ -1890,11 +1890,42 @@
if Nkind (Lhs) = N_Indexed_Component
and then Is_Bit_Packed_Array (Etype (Prefix (Lhs)))
- and then not Crep
then
- Expand_Bit_Packed_Element_Set (N);
- return;
+ if not Crep then
+ Expand_Bit_Packed_Element_Set (N);
+ return;
+ else
+ -- Generate the following, to force component-by-component
+ -- assignments in an efficient way. Otherwise each component
+ -- will require a temporary and two bit-field manipulations.
+
+ -- T1 : Elmt_Type;
+ -- T1 := RhS;
+ -- Lhs := T1;
+
+ declare
+ Tnn : constant Entity_Id := Make_Temporary (Loc, 'T');
+ Stats : List_Id;
+
+ begin
+ Stats := New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Tnn,
+ Object_Definition => New_Occurrence_Of (Etype (Lhs), Loc)),
+ Make_Assignment_Statement (Loc,
+ Name => New_Occurrence_Of (Tnn, Loc),
+ Expression => Relocate_Node (Rhs)),
+ Make_Assignment_Statement (Loc,
+ Name => Relocate_Node (Lhs),
+ Expression => New_Occurrence_Of (Tnn, Loc)));
+
+ Insert_Actions (N, Stats);
+ Rewrite (N, Make_Null_Statement (Loc));
+ Analyze (N);
+ end;
+ end if;
+
-- Build-in-place function call case. Note that we're not yet doing
-- build-in-place for user-written assignment statements (the assignment
-- here came from an aggregate.)