home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
gnat-2.06-src.tgz
/
tar.out
/
fsf
/
gnat
/
ada
/
exp_pakd.adb
< prev
next >
Wrap
Text File
|
1996-09-28
|
29KB
|
800 lines
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- E X P _ P A K D --
-- --
-- B o d y --
-- --
-- $Revision: 1.13 $ --
-- --
-- Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 2, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING. If not, write --
-- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
-- --
------------------------------------------------------------------------------
with Atree; use Atree;
with Einfo; use Einfo;
with Exp_Ch4; use Exp_Ch4;
with Exp_Util; use Exp_Util;
with Freeze; use Freeze;
with Nlists; use Nlists;
with Nmake; use Nmake;
with Rtsfind; use Rtsfind;
with Sem; use Sem;
with Sem_Eval; use Sem_Eval;
with Sem_Res; use Sem_Res;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Snames; use Snames;
with Stand; use Stand;
with Tbuild; use Tbuild;
with Ttypes; use Ttypes;
with Uintp; use Uintp;
package body Exp_Pakd is
---------------------------
-- Endian Considerations --
---------------------------
-- As described in the specification, bit numbering in a packed array
-- is consistent with bit numbering in a record representation clause,
-- and hence dependent on the endianness of the machine:
-- For little-endian machines, element zero is at the right hand end
-- (low order end) of a bit field.
-- For big-endian machines, element zero is at the left hand end
-- (high order end) of a bit field.
-- The shifts that are used to right justify a field therefore differ
-- in the two cases. For the little-endian case, we can simply use the
-- bit number (i.e. the element number * element size) as the count for
-- a right shift. For the big-endian case, we have to subtract the shift
-- count from an appropriate constant to use in the right shift. We use
-- rotates instead of shifts (which is necessary in the store case to
-- preserve other fields), and we expect that the backend will be able
-- to change the right rotate into a left rotate, avoiding the subtract,
-- if the architecture provides such an instruction.
-----------------------
-- Local Subprograms --
-----------------------
function Convert_To_PAT_Type (Aexp : Node_Id) return Node_Id;
-- Given an expression of a packed array type, builds a corresponding
-- expression whose type is the implementation type used to represent
-- the packed array. Aexp is analyzed on entry, and on return Aexp
-- is rewritten (using Rewrite_Substitute_Tree) by this expression.
-- The value returned is the modified expression (whose Node_Id is
-- actually the same as Aexp).
procedure Setup_Packed_Array_Reference
(N : Node_Id;
Vsiz : out Uint;
Csiz : out Nat);
-- This procedure performs common processing on the N_Indexed_Component
-- parameter given as N, whose prefix is a reference to a packed array.
-- On return, the indexed component has been modified as follows:
-- The prefix is the object containing the desired bit field. It is
-- of type Unsigned or Long_Long_Unsigned, and is either the entire
-- value, for the small static case, or the proper selected word from
-- the array in the large or dynamic case. This node is analyzed and
-- resolved on return.
--
-- The subscript is a node representing the shift count to be used in
-- the rotate right instruction that positions the field for access.
--
-- The prefix and subscript are analyzed on return. In fact the reason
-- we return these values by rewriting the indexed component is to keep
-- everything properly connected to the tree. The remaining parameters
-- are set as follows on return:
--
-- Vsiz is the data size, either Unsigned'Size for the array or the
-- actual Esize for the static modular type case.
--
-- Csiz is the component size (either 1, 2 or 4)
--
-- Note: in some cases the call to this routine may generate actions
-- (for handling multi-use references and the generation of the packed
-- array type on the fly). Such actions are inserted into the tree
-- directly using Insert_Action.
-------------------------
-- Convert_To_PAT_Type --
-------------------------
-- The PAT is always obtained from the actual subtype
function Convert_To_PAT_Type (Aexp : Entity_Id) return Entity_Id is
Result : constant Entity_Id := Convert_To_Actual_Subtype (Aexp);
Act_ST : constant Entity_Id := Etype (Result);
PAT : Entity_Id;
Decl : Node_Id;
begin
-- OK, we have the actual subtype. If it already has a packed
-- array type precalculated, then we can use this type.
if Present (Packed_Array_Type (Act_ST)) then
PAT := Packed_Array_Type (Act_ST);
-- Otherwise we need to build the packed array type
else
Expand_Packed_Array_Type (Act_ST, PAT, Decl);
Insert_Action (Aexp, Decl);
Insert_Actions (Aexp, Freeze_Entity (PAT, Sloc (Aexp)));
end if;
-- Finally what we return is the result of doing an unchecked
-- conversion from the actual subtype to the packed array type
Rewrite_Substitute_Tree (Aexp,
Unchecked_Convert_To (PAT, Relocate_Node (Aexp)));
Analyze (Aexp);
Resolve (Aexp, PAT);
return Aexp;
end Convert_To_PAT_Type;
------------------------------------
-- Expand_Packed_Boolean_Operator --
------------------------------------
-- This routine expands "a op b" for the packed cases
procedure Expand_Packed_Boolean_Operator (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
L : constant Node_Id := Convert_To_PAT_Type (Left_Opnd (N));
R : constant Node_Id := Convert_To_PAT_Type (Right_Opnd (N));
PAT : constant Entity_Id := Etype (L);
begin
-- For the modular case, we expand a op b into
-- typ!(pat!(a) op pat!(b))
if Is_Modular_Integer_Type (PAT) then
declare
P : Node_Id;
begin
if Nkind (N) = N_Op_And then
P := Make_Op_And (Loc, L, R);
elsif Nkind (N) = N_Op_Or then
P := Make_Op_And (Loc, L, R);
else -- Nkind (N) = N_Op_Xor
P := Make_Op_Xor (Loc, L, R);
end if;
Rewrite_Substitute_Tree (N, Unchecked_Convert_To (Typ, P));
end;
-- For the non-modular case, we use Exp_Ch4.Make_Boolean_Array to build
-- a function that does the necessary loop of operations on the array,
-- and then replace the operation with a call to this function, doing
-- the necessary unchecked conversions, and then replace the logical
-- operation with a call to this function:
-- typ!(func (pat!(a), pat!(b)))
else
declare
Func_Body : constant Node_Id := Make_Boolean_Array_Op (PAT, N);
Func_Name : constant Entity_Id := Defining_Unit_Name
(Specification (Func_Body));
begin
Insert_Action (N, Func_Body);
Rewrite_Substitute_Tree (N,
Unchecked_Convert_To (Typ,
Make_Function_Call (Loc,
Name => New_Reference_To (Func_Name, Loc),
Parameter_Associations => New_List (L, R))));
end;
end if;
Analyze (N);
Resolve (N, Typ);
end Expand_Packed_Boolean_Operator;
------------------------------
-- Expand_Packed_Array_Type --
------------------------------
procedure Expand_Packed_Array_Type
(Typ : Entity_Id;
PAT : out Entity_Id;
Decl : out Node_Id)
is
Loc : constant Source_Ptr := Sloc (Typ);
Base : constant Entity_Id := Base_Type (Typ);
Ctyp : constant Entity_Id := Component_Type (Typ);
Styp : constant Entity_Id := Etype (First_Index (Typ));
Static : constant Boolean := Is_OK_Static_Subtype (Styp);
Lo_Bound : constant Node_Id := Type_Low_Bound (Styp);
Hi_Bound : constant Node_Id := Type_High_Bound (Styp);
Siz : Int := UI_To_Int (Esize (Ctyp));
Len_Bits : Uint;
Bits_U1 : Node_Id;
PAT_High : Node_Id;
Der_Tdef : Node_Id;
Btyp : RE_Id;
Fnode : Node_Id;
Type_Def : Node_Id;
begin
pragma Assert (Ekind (Typ) = E_Array_Subtype);
-- Use 4-bit fields for 3-bit quantities
if Siz = 3 then
Siz := 4;
end if;
-- The name of the packed array type is
-- tttPx
-- where x is 1,2 or 4 for the component size in bits and ttt is
-- the name of the parent packed type.
PAT :=
Make_Defining_Identifier (Loc,
Chars => New_External_Name (Chars (Typ), 'P', Siz));
if Static then
Len_Bits :=
(Expr_Value (Hi_Bound) - Expr_Value (Lo_Bound) + 1) * Siz;
end if;
-- We are now going to build the Packed_Array_Type. For unconstrained
-- packed arrays, the corresponding type is simply:
-- type tttPn is new Raw_Bits
if not Is_Constrained (Typ) then
Der_Tdef :=
Make_Derived_Type_Definition (Loc,
Subtype_Indication =>
New_Occurrence_Of (RTE (RE_Raw_Bits), Loc));
-- If the size is static, and in the range 1 .. Long_Long_Integer'Size
-- (= Long_Long_Unsigned'Size), we use a subtype of a modular type:
-- type tttPn is new btyp
-- range 0 .. 2 ** (Esize (Typ) * Siz) - 1;
-- Here Siz is 1, 2 or 4, as computed above and btyp is either Unsigned
-- or Long_Long_Unsigned, depending on the size.
elsif Static
and then Len_Bits <= Standard_Long_Long_Integer_Size
then
if Len_Bits <= Standard_Integer_Size then
Btyp := RE_Unsigned;
else
Btyp := RE_Long_Long_Unsigned;
end if;
Der_Tdef :=
Make_Derived_Type_Definition (Loc,
Subtype_Indication =>
Make_Subtype_Indication (Loc,
Subtype_Mark => New_Occurrence_Of (RTE (Btyp), Loc),
Constraint =>
Make_Range_Constraint (Loc,
Range_Expression =>
Make_Range (Loc,
Low_Bound => Make_Integer_Literal (Loc, Uint_0),
High_Bound =>
Make_Integer_Literal (Loc,
Intval => 2 ** Len_Bits - 1)))));
-- For all other cases, we build an array type:
-- type tttPn is
-- new System.Raw_Bits (0 .. (Bits + (Usiz - 1)) / Usiz - 1);
-- Usiz is Uns'Size which is the same as Integer'Size, since
-- that is how the type System.Unsigned is defined. Bits is the
-- length of the array in bits.
else
Bits_U1 :=
Make_Op_Add (Loc,
Left_Opnd =>
Make_Op_Multiply (Loc,
Left_Opnd =>
Make_Integer_Literal (Loc, UI_From_Int (Siz)),
Right_Opnd =>
Make_Attribute_Reference (Loc,
Attribute_Name => Name_Range_Length,
Prefix => New_Occurrence_Of (Styp, Loc))),
Right_Opnd =>
Make_Integer_Literal (Loc,
Intval => UI_From_Int (Standard_Integer_Size - 1)));
Set_Paren_Count (Bits_U1, 1);
PAT_High :=
Make_Op_Subtract (Loc,
Left_Opnd =>
Make_Op_Divide (Loc,
Left_Opnd => Bits_U1,
Right_Opnd =>
Make_Integer_Literal (Loc,
Intval => UI_From_Int (Standard_Integer_Size))),
Right_Opnd => Make_Integer_Literal (Loc, Uint_1));
Der_Tdef :=
Make_Derived_Type_Definition (Loc,
Subtype_Indication =>
Make_Subtype_Indication (Loc,
Subtype_Mark =>
New_Occurrence_Of (RTE (RE_Raw_Bits), Loc),
Constraint =>
Make_Index_Or_Discriminant_Constraint (Loc,
Constraints => New_List (
Make_Range (Loc,
Low_Bound =>
Make_Integer_Literal (Loc, Uint_0),
High_Bound => PAT_High)))));
end if;
-- Now we set the full type declaration as the result
Decl :=
Make_Full_Type_Declaration (Loc,
Defining_Identifier => PAT,
Type_Definition => Der_Tdef);
end Expand_Packed_Array_Type;
-------------------------------
-- Expand_Packed_Element_Get --
-------------------------------
procedure Expand_Packed_Element_Get (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Ctyp : constant Entity_Id := Component_Type (Etype (Prefix (N)));
Obj : Node_Id;
Shift : Node_Id;
Cod : List_Id;
Vsiz : Uint;
Csiz : Nat;
begin
Setup_Packed_Array_Reference (N, Vsiz, Csiz);
Shift := Relocate_Node (First (Expressions (N)));
Obj := Prefix (N);
-- We generate a shift right to position the field, followed
-- by a masking operation to extract the bit field, and we
-- finally do a Val operation to convert the result to the
-- required target type.
Rewrite_Substitute_Tree (N,
Make_Attribute_Reference (Loc,
Prefix => New_Reference_To (Ctyp, Loc),
Attribute_Name => Name_Val,
Expressions => New_List (
Make_Op_And (Loc,
Left_Opnd =>
Make_Op_Shift_Right (Loc,
Left_Opnd => Obj,
Right_Opnd => Shift),
Right_Opnd => Make_Integer_Literal (Loc, 2 ** Csiz - 1)))));
Analyze (N);
Resolve (N, Ctyp);
end Expand_Packed_Element_Get;
-------------------------------
-- Expand_Packed_Element_Set --
-------------------------------
procedure Expand_Packed_Element_Set (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Lhs : constant Node_Id := Name (N);
Rhs : constant Node_Id := Expression (N);
Ctyp : constant Entity_Id := Etype (Rhs);
Result : Node_Id;
Obj : Node_Id;
Shift : Node_Id;
Vsiz : Uint;
Csiz : Nat;
Or_Rhs : Node_Id;
begin
Setup_Packed_Array_Reference (Lhs, Vsiz, Csiz);
Shift := Relocate_Node (First (Expressions (Lhs)));
Obj := Prefix (Lhs);
-- The statement to be generated is:
-- Obj := (((Obj >> Shift) and Mask) or Or_Rhs) << Shift)
-- where >> and << are rotate right and left respectively, and
-- Mask is a mask that removes the old bits from the value.
-- The right hand side, Or_Rhs must be of Etype (Obj). A special
-- case arises if what we have now is a Val attribute reference whose
-- expression type is Etype (Obj). This happens for assignments of
-- fields from the same array. In this case we get the required right
-- hand side by simply removing the inner attribute reference.
if Nkind (Rhs) = N_Attribute_Reference
and then Attribute_Name (Rhs) = Name_Val
and then Etype (First (Expressions (Rhs))) = Etype (Obj)
then
Or_Rhs := First (Expressions (Rhs));
-- Otherwise we get the expression to the right type by taking X'Pos
-- of the expression, where X is the component type (i.e. Ctyp).
else
Or_Rhs :=
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (Ctyp, Loc),
Attribute_Name => Name_Pos,
Expressions => New_List (Relocate_Node (Rhs)));
end if;
-- Now do the rewrite
Rewrite_Substitute_Tree (N,
Make_Assignment_Statement (Loc,
Name => Duplicate_Subexpr (Obj, True),
Expression =>
Make_Op_Rotate_Left (Loc,
Left_Opnd =>
Make_Op_Or (Loc,
Left_Opnd =>
Make_Op_And (Loc,
Left_Opnd =>
Make_Op_Rotate_Right (Loc,
Left_Opnd => Duplicate_Subexpr (Obj, True),
Right_Opnd => Duplicate_Subexpr (Shift)),
Right_Opnd =>
Make_Integer_Literal (Loc,
Intval => (2 ** Vsiz - 1) - (2 ** Csiz - 1))),
Right_Opnd => Or_Rhs),
Right_Opnd => Duplicate_Subexpr (Shift))));
Analyze (N);
end Expand_Packed_Element_Set;
-----------------------
-- Expand_Packed_Not --
-----------------------
-- Handles expansion of not on packed array types
procedure Expand_Packed_Not (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
Opnd : constant Node_Id := Convert_To_PAT_Type (Right_Opnd (N));
PAT : constant Entity_Id := Etype (Opnd);
A : Entity_Id;
B : Entity_Id;
J : Entity_Id;
A_J : Node_Id;
B_J : Node_Id;
Func_Name : Entity_Id;
Func_Body : Node_Id;
Loop_Statement : Node_Id;
Result : Node_Id;
Type_Of_B : Node_Id;
begin
-- For the case where the packed array type is a modular type,
-- not A expands simply into:
-- typ!(PAT!(A) xor mask)
-- where PAT is the packed array type, and mask is a mask of all
-- one bits of length equal to the size of this packed type.
if not Is_Array_Type (PAT) then
Rewrite_Substitute_Tree (N,
Unchecked_Convert_To (Typ,
Make_Op_Xor (Loc,
Left_Opnd => Opnd,
Right_Opnd =>
Make_Integer_Literal (Loc,
Intval => 2 ** Esize (PAT) - 1))));
-- For the array case, we build and insert into the tree the following
-- function definition
-- function Nnnn (A : PAT) is
-- B : PAT;
-- begin
-- for J in A'range loop
-- B (J) := not A (J);
-- end loop;
-- return B;
-- end Nnnn;
-- We then replace the not operation with a call to this function.
-- The call does the necessary unchecked conversions to and from PAT
-- Note: above is wrong, does not do the right thing with the last
-- word, which may be only partially filled. ???
else
A := Make_Defining_Identifier (Loc, Name_uA);
B := Make_Defining_Identifier (Loc, Name_uB);
J := Make_Defining_Identifier (Loc, Name_uJ);
A_J :=
Make_Indexed_Component (Loc,
Prefix => New_Reference_To (A, Loc),
Expressions => New_List (New_Reference_To (J, Loc)));
B_J :=
Make_Indexed_Component (Loc,
Prefix => New_Reference_To (B, Loc),
Expressions => New_List (New_Reference_To (J, Loc)));
Loop_Statement :=
Make_Loop_Statement (Loc,
Identifier => Empty,
Iteration_Scheme =>
Make_Iteration_Scheme (Loc,
Loop_Parameter_Specification =>
Make_Loop_Parameter_Specification (Loc,
Defining_Identifier => J,
Discrete_Subtype_Definition =>
Make_Attribute_Reference (Loc,
Prefix => Make_Identifier (Loc, Chars (A)),
Attribute_Name => Name_Range))),
Statements => New_List (
Make_Assignment_Statement (Loc,
Name => B_J,
Expression => Make_Op_Not (Loc, A_J))));
Func_Name :=
Make_Defining_Identifier (Loc, New_Internal_Name ('N'));
Insert_Action (N,
Make_Subprogram_Body (Loc,
Specification =>
Make_Function_Specification (Loc,
Defining_Unit_Name => Func_Name,
Parameter_Specifications => New_List (
Make_Parameter_Specification (Loc,
Defining_Identifier => A,
Parameter_Type => New_Reference_To (PAT, Loc))),
Subtype_Mark => New_Reference_To (PAT, Loc)),
Declarations => New_List (
Make_Object_Declaration (Loc,
Defining_Identifier => B,
Object_Definition => New_Reference_To (PAT, Loc))),
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
Statements => New_List (
Loop_Statement,
Make_Return_Statement (Loc,
Expression =>
Make_Identifier (Loc, Chars (B)))))));
-- Now we replace the node with a call to this function:
-- typ!(func (pat!(n)))
Rewrite_Substitute_Tree (N,
Unchecked_Convert_To (Typ,
Make_Function_Call (Loc,
Name => New_Reference_To (Func_Name, Loc),
Parameter_Associations => New_List (Relocate_Node (Opnd)))));
end if;
Analyze (N);
Resolve (N, Typ);
end Expand_Packed_Not;
----------------------------------
-- Setup_Packed_Array_Reference --
----------------------------------
procedure Setup_Packed_Array_Reference
(N : Node_Id;
Vsiz : out Uint;
Csiz : out Nat)
is
Loc : constant Source_Ptr := Sloc (N);
Atyp : constant Entity_Id := Etype (Prefix (N));
Ctyp : constant Entity_Id := Component_Type (Atyp);
Styp : constant Entity_Id := Etype (First_Index (Atyp));
Sub : constant Node_Id := First (Expressions (N));
Arr : constant Node_Id := Convert_To_PAT_Type (Prefix (N));
PAT : constant Entity_Id := Etype (Arr);
Otyp : Entity_Id;
Subscr : Node_Id;
begin
Csiz := UI_To_Int (Esize (Ctyp));
if Csiz = 4 then
Csiz := 3;
end if;
if Is_Array_Type (PAT) then
Vsiz := Esize (Component_Type (PAT));
Otyp := Component_Type (PAT);
else
Vsiz := Esize (PAT);
Otyp := PAT;
end if;
-- Get expression for the subscript value. First, if Do_Range_Check
-- is set on the subscript, then we must do a range check against the
-- original bounds (not the bounds of the packed array type). We do
-- this by introducing a subtype conversion.
if Do_Range_Check (Sub)
and then Etype (Sub) /= Styp
then
Rewrite_Substitute_Tree (Sub, Convert_To (Styp, Sub));
end if;
-- Next, we want the subscript to be of type Integer, and zero based.
-- If it is of an integer type now, we just subtract:
-- Integer (subscript) - Integer (Styp'First)
if Is_Integer_Type (Styp) then
Rewrite_Substitute_Tree (Sub,
Make_Op_Subtract (Loc,
Left_Opnd => Convert_To (Standard_Integer, Sub),
Right_Opnd =>
Convert_To (Standard_Integer,
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (Styp, Loc),
Attribute_Name => Name_First))));
-- For the enumeration case, we have to use 'Pos to get the value
-- to work with before subtracting the lower bound.
-- Integer (Styp'Pos (Sub)) - Integer (Styp'Pos (Styp'First));
else
pragma Assert (Is_Enumeration_Type (Styp));
Rewrite_Substitute_Tree (Sub,
Make_Op_Subtract (Loc,
Left_Opnd => Convert_To (Standard_Integer,
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (Styp, Loc),
Attribute_Name => Name_Pos,
Expressions => New_List (Relocate_Node (Sub)))),
Right_Opnd =>
Convert_To (Standard_Integer,
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (Styp, Loc),
Attribute_Name => Name_Pos,
Expressions => New_List (
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (Styp, Loc),
Attribute_Name => Name_First))))));
end if;
-- If the component size is 2 or 4, then the subscript must be
-- multiplied by the component size to get the shift count.
if Csiz /= 1 then
Rewrite_Substitute_Tree (Sub,
Make_Op_Multiply (Loc,
Left_Opnd => Make_Integer_Literal (Loc, UI_From_Int (Csiz)),
Right_Opnd => Relocate_Node (Sub)));
end if;
-- Now we have the shift count within the entire value. In the
-- following code, we may be doing a Duplicate_Subexpr on the value
-- which means that it must be analyzed.
Analyze (Sub);
Resolve (Sub, Standard_Integer);
-- If we have the array case, then this shift count must be broken
-- down into a word subscript, and a shift within the word.
if Is_Array_Type (PAT) then
-- The shift count within the word is
-- shift mod Unsigned'Size
Rewrite_Substitute_Tree (Sub,
Make_Op_Mod (Loc,
Left_Opnd => Relocate_Node (Sub),
Right_Opnd => Make_Integer_Literal (Loc, Vsiz)));
-- The subscript to be used on the PAT array is
-- shift / Unsigned'Size
Rewrite_Substitute_Tree (Arr,
Make_Indexed_Component (Loc,
Prefix => Relocate_Node (Arr),
Expressions => New_List (
Make_Op_Divide (Loc,
Left_Opnd => Duplicate_Subexpr (Left_Opnd (Sub)),
Right_Opnd => Make_Integer_Literal (Loc, Vsiz)))));
-- For the non-array case, the word shift count is already
-- set, and all we need is the unchecked conversion of the
-- array to the PAT type.
else
Rewrite_Substitute_Tree (Arr, Unchecked_Convert_To (PAT, Arr));
end if;
-- The one remaining step is to modify the shift count for the
-- big-endian case. Consider the following example in a word
-- of 32 bits
-- xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx bits of word
-- vvvv vvvvvvvv vvvvvvvv bits of value
-- 9988 77665544 33221100 little-endian numbering
-- 0011 22334455 66778899 big-endian numbering
-- Here we have the case of 2-bit fields, with an array of ten such
-- elements stored in a 20-bit field, loaded as a 32-bit word.
-- For the little-endian case, we already have the proper rotate
-- count set, e.g. for element 2, the shift count is 2*2 = 4.
-- For the big endian case, we have to adjust the shift count,
-- computing it as N - shift, where N is the number of bits in
-- the value, and shift is the shift count so far computed.
if Bytes_Big_Endian then
Rewrite_Substitute_Tree (Sub,
Make_Op_Subtract (Loc,
Left_Opnd => Make_Integer_Literal (Loc, Vsiz),
Right_Opnd => Relocate_Node (Sub)));
end if;
-- We return both the Object and the Shift count in analyzed form.
-- Note that the N_Indexed_Component node is destroyed, but that's
-- fine, because we are going to rewrite it anyway.
Analyze (Arr);
Resolve (Arr, Otyp);
Analyze (Sub);
Resolve (Sub, Standard_Integer);
end Setup_Packed_Array_Reference;
end Exp_Pakd;