Commit abdeafa6 by Bob Duff Committed by Pierre-Marie de Rodat

[Ada] Add the System.Bitfield_Utils runtime unit

2019-08-21  Bob Duff  <duff@adacore.com>

gcc/ada/

	* Makefile.rtl (GNATRTL_NONTASKING_OBJS): Add s-bitutil.o and
	s-biutin.o.
	* exp_ch5.adb (Expand_Assign_Array_Bitfield): New function to
	generate a call to Copy_Bitfield. This is disabled for now.
	(Expand_Assign_Array_Loop_Or_Bitfield): New function to decide
	whether to call Expand_Assign_Array_Bitfield.
	(Expand_Assign_Array): Call Expand_Assign_Array_Loop_Or_Bitfield
	instead of Expand_Assign_Array_Loop.
	* libgnat/s-bitfie.ads, libgnat/s-bituti.adb,
	libgnat/s-bituti.ads: New units.
	* rtsfind.ads: Add enum literals for accessing Copy_Bitfield.

From-SVN: r274785
parent a1fda1e8
2019-08-21 Bob Duff <duff@adacore.com>
* Makefile.rtl (GNATRTL_NONTASKING_OBJS): Add s-bitutil.o and
s-biutin.o.
* exp_ch5.adb (Expand_Assign_Array_Bitfield): New function to
generate a call to Copy_Bitfield. This is disabled for now.
(Expand_Assign_Array_Loop_Or_Bitfield): New function to decide
whether to call Expand_Assign_Array_Bitfield.
(Expand_Assign_Array): Call Expand_Assign_Array_Loop_Or_Bitfield
instead of Expand_Assign_Array_Loop.
* libgnat/s-bitfie.ads, libgnat/s-bituti.adb,
libgnat/s-bituti.ads: New units.
* rtsfind.ads: Add enum literals for accessing Copy_Bitfield.
2019-08-21 Piotr Trojanek <trojanek@adacore.com> 2019-08-21 Piotr Trojanek <trojanek@adacore.com>
* bindo-graphs.ads (Iterate_Edges_To_Successors): Fix typo in * bindo-graphs.ads (Iterate_Edges_To_Successors): Fix typo in
......
...@@ -502,7 +502,9 @@ GNATRTL_NONTASKING_OBJS= \ ...@@ -502,7 +502,9 @@ GNATRTL_NONTASKING_OBJS= \
s-atopri$(objext) \ s-atopri$(objext) \
s-auxdec$(objext) \ s-auxdec$(objext) \
s-bignum$(objext) \ s-bignum$(objext) \
s-bitfie$(objext) \
s-bitops$(objext) \ s-bitops$(objext) \
s-bituti$(objext) \
s-boarop$(objext) \ s-boarop$(objext) \
s-boustr$(objext) \ s-boustr$(objext) \
s-bytswa$(objext) \ s-bytswa$(objext) \
......
...@@ -114,6 +114,28 @@ package body Exp_Ch5 is ...@@ -114,6 +114,28 @@ package body Exp_Ch5 is
-- Auxiliary declarations are inserted before node N using the standard -- Auxiliary declarations are inserted before node N using the standard
-- Insert_Actions mechanism. -- Insert_Actions mechanism.
function Expand_Assign_Array_Bitfield
(N : Node_Id;
Larray : Entity_Id;
Rarray : Entity_Id;
L_Type : Entity_Id;
R_Type : Entity_Id;
Rev : Boolean) return Node_Id;
-- Alternative to Expand_Assign_Array_Loop for packed bitfields. Generates
-- a call to the System.Bitfields.Copy_Bitfield, which is more efficient
-- than copying component-by-component.
function Expand_Assign_Array_Loop_Or_Bitfield
(N : Node_Id;
Larray : Entity_Id;
Rarray : Entity_Id;
L_Type : Entity_Id;
R_Type : Entity_Id;
Ndim : Pos;
Rev : Boolean) return Node_Id;
-- Calls either Expand_Assign_Array_Loop or Expand_Assign_Array_Bitfield as
-- appropriate.
procedure Expand_Assign_Record (N : Node_Id); procedure Expand_Assign_Record (N : Node_Id);
-- N is an assignment of an untagged record value. This routine handles -- N is an assignment of an untagged record value. This routine handles
-- the case where the assignment must be made component by component, -- the case where the assignment must be made component by component,
...@@ -314,6 +336,10 @@ package body Exp_Ch5 is ...@@ -314,6 +336,10 @@ package body Exp_Ch5 is
Crep : constant Boolean := Change_Of_Representation (N); Crep : constant Boolean := Change_Of_Representation (N);
pragma Assert
(Crep
or else Is_Bit_Packed_Array (L_Type) = Is_Bit_Packed_Array (R_Type));
Larray : Node_Id; Larray : Node_Id;
Rarray : Node_Id; Rarray : Node_Id;
...@@ -939,7 +965,7 @@ package body Exp_Ch5 is ...@@ -939,7 +965,7 @@ package body Exp_Ch5 is
else else
Rewrite (N, Rewrite (N,
Expand_Assign_Array_Loop Expand_Assign_Array_Loop_Or_Bitfield
(N, Larray, Rarray, L_Type, R_Type, Ndim, (N, Larray, Rarray, L_Type, R_Type, Ndim,
Rev => not Forwards_OK (N))); Rev => not Forwards_OK (N)));
end if; end if;
...@@ -1092,12 +1118,12 @@ package body Exp_Ch5 is ...@@ -1092,12 +1118,12 @@ package body Exp_Ch5 is
Condition => Condition, Condition => Condition,
Then_Statements => New_List ( Then_Statements => New_List (
Expand_Assign_Array_Loop Expand_Assign_Array_Loop_Or_Bitfield
(N, Larray, Rarray, L_Type, R_Type, Ndim, (N, Larray, Rarray, L_Type, R_Type, Ndim,
Rev => False)), Rev => False)),
Else_Statements => New_List ( Else_Statements => New_List (
Expand_Assign_Array_Loop Expand_Assign_Array_Loop_Or_Bitfield
(N, Larray, Rarray, L_Type, R_Type, Ndim, (N, Larray, Rarray, L_Type, R_Type, Ndim,
Rev => True)))); Rev => True))));
end if; end if;
...@@ -1320,6 +1346,134 @@ package body Exp_Ch5 is ...@@ -1320,6 +1346,134 @@ package body Exp_Ch5 is
return Assign; return Assign;
end Expand_Assign_Array_Loop; end Expand_Assign_Array_Loop;
----------------------------------
-- Expand_Assign_Array_Bitfield --
----------------------------------
function Expand_Assign_Array_Bitfield
(N : Node_Id;
Larray : Entity_Id;
Rarray : Entity_Id;
L_Type : Entity_Id;
R_Type : Entity_Id;
Rev : Boolean) return Node_Id
is
pragma Assert (not Rev);
-- Reverse copying is not yet supported by Copy_Bitfield.
pragma Assert (not Change_Of_Representation (N));
-- This won't work, for example, to copy a packed array to an unpacked
-- array.
Loc : constant Source_Ptr := Sloc (N);
L_Index_Typ : constant Node_Id := Etype (First_Index (L_Type));
R_Index_Typ : constant Node_Id := Etype (First_Index (R_Type));
Left_Lo : constant Node_Id := Type_Low_Bound (L_Index_Typ);
Right_Lo : constant Node_Id := Type_Low_Bound (R_Index_Typ);
L_Addr : constant Node_Id :=
Make_Attribute_Reference (Loc,
Prefix =>
Make_Indexed_Component (Loc,
Prefix =>
Duplicate_Subexpr (Larray, True),
Expressions => New_List (New_Copy_Tree (Left_Lo))),
Attribute_Name => Name_Address);
L_Bit : constant Node_Id :=
Make_Attribute_Reference (Loc,
Prefix =>
Make_Indexed_Component (Loc,
Prefix =>
Duplicate_Subexpr (Larray, True),
Expressions => New_List (New_Copy_Tree (Left_Lo))),
Attribute_Name => Name_Bit);
R_Addr : constant Node_Id :=
Make_Attribute_Reference (Loc,
Prefix =>
Make_Indexed_Component (Loc,
Prefix =>
Duplicate_Subexpr (Rarray, True),
Expressions => New_List (New_Copy_Tree (Right_Lo))),
Attribute_Name => Name_Address);
R_Bit : constant Node_Id :=
Make_Attribute_Reference (Loc,
Prefix =>
Make_Indexed_Component (Loc,
Prefix =>
Duplicate_Subexpr (Rarray, True),
Expressions => New_List (New_Copy_Tree (Right_Lo))),
Attribute_Name => Name_Bit);
-- Compute the Size of the bitfield. ???We can't use Size here, because
-- it doesn't work properly for slices of packed arrays, so we compute
-- the L'Size as L'Length*L'Component_Size.
--
-- Note that the length check has already been done, so we can use the
-- size of either L or R.
Size : constant Node_Id :=
Make_Op_Multiply (Loc,
Make_Attribute_Reference (Loc,
Prefix =>
Duplicate_Subexpr (Name (N), True),
Attribute_Name => Name_Length),
Make_Attribute_Reference (Loc,
Prefix =>
Duplicate_Subexpr (Name (N), True),
Attribute_Name => Name_Component_Size));
begin
return Make_Procedure_Call_Statement (Loc,
Name => New_Occurrence_Of (RTE (RE_Copy_Bitfield), Loc),
Parameter_Associations => New_List (
R_Addr, R_Bit, L_Addr, L_Bit, Size));
end Expand_Assign_Array_Bitfield;
------------------------------------------
-- Expand_Assign_Array_Loop_Or_Bitfield --
------------------------------------------
function Expand_Assign_Array_Loop_Or_Bitfield
(N : Node_Id;
Larray : Entity_Id;
Rarray : Entity_Id;
L_Type : Entity_Id;
R_Type : Entity_Id;
Ndim : Pos;
Rev : Boolean) return Node_Id
is
Slices : constant Boolean :=
Nkind (Name (N)) = N_Slice or else Nkind (Expression (N)) = N_Slice;
begin
-- Determine whether Copy_Bitfield is appropriate (will work, and will
-- be more efficient than component-by-component copy). Copy_Bitfield
-- doesn't work for reversed storage orders. It is efficient only for
-- slices of bit-packed arrays.
-- Note that Expand_Assign_Array_Bitfield is disabled for now
if False -- ???
and then Is_Bit_Packed_Array (L_Type)
and then Is_Bit_Packed_Array (R_Type)
and then RTE_Available (RE_Copy_Bitfield)
and then not Reverse_Storage_Order (L_Type)
and then not Reverse_Storage_Order (R_Type)
and then Ndim = 1
and then not Rev
and then Slices
then
return Expand_Assign_Array_Bitfield
(N, Larray, Rarray, L_Type, R_Type, Rev);
else
return Expand_Assign_Array_Loop
(N, Larray, Rarray, L_Type, R_Type, Ndim, Rev);
end if;
end Expand_Assign_Array_Loop_Or_Bitfield;
-------------------------- --------------------------
-- Expand_Assign_Record -- -- Expand_Assign_Record --
-------------------------- --------------------------
......
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- S Y S T E M . B I T F I E L D _ U T I L S --
-- --
-- S p e c --
-- --
-- Copyright (C) 2019, Free Software Foundation, Inc. --
-- --
-- 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 3, 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. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
with System.Bitfield_Utils;
package System.Bitfields is
-- Instances of the generic package in System.Bitfield_Utils. So far
-- we have just one, which defaults to the natural endianness of the
-- machine. We might someday want to support Scalar_Storage_Order.
Val_Bytes : constant := 4;
Val_Bits : constant := Val_Bytes * System.Storage_Unit;
type Val_2 is mod 2**(Val_Bits * 2) with Alignment => Val_Bytes;
pragma Provide_Shift_Operators (Val_2);
type Val is mod 2**Val_Bits with Alignment => Val_Bytes;
package Utils is new System.Bitfield_Utils.G (Val, Val_2);
procedure Copy_Bitfield
(Src_Address : Address;
Src_Offset : Utils.Bit_Offset_In_Byte;
Dest_Address : Address;
Dest_Offset : Utils.Bit_Offset_In_Byte;
Size : Utils.Bit_Size)
renames Utils.Copy_Bitfield;
end System.Bitfields;
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- S Y S T E M . B I T F I E L D _ U T I L S --
-- --
-- S p e c --
-- --
-- Copyright (C) 2019, Free Software Foundation, Inc. --
-- --
-- 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 3, 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. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
package System.Bitfield_Utils is
-- This package provides a procedure for copying arbitrarily large and
-- arbitrarily bit-aligned bit fields.
-- Type Val is used to represent small bit fields. Val_2 represents a
-- contiguous pair of Vals. Val_2'Alignment is half of its size in bytes,
-- which is likely not the natural alignment. This is done to ensure that
-- any bit field that fits in a Val can fit in an aligned Val_2, starting
-- somewhere in the first half, and possibly crossing over into the second
-- half. This allows us to isolate a Val value by shifting and masking the
-- Val_2.
--
-- Val can be 8, 16, or 32 bits; larger values are more efficient. It can't
-- be 64 bits, because we need Val_2 to be a double-wide shiftable type,
-- and 128 bits is not supported. Instantiating with an 8-bit Val is useful
-- for testing and debugging; 32 bits should be used for production.
--
-- We use modular types here, not because we want modular arithmetic, but
-- so we can do shifting and masking. The actual for Val_2 should have
-- pragma Provide_Shift_Operators, so that the Shift_Left and Shift_Right
-- intrinsics can be passed in. It is impossible to put that pragma on a
-- generic formal, or on a type derived from a generic formal, so they have
-- to be passed in.
--
-- Endian indicates whether we're on little-endian or big-endian machine.
pragma Elaborate_Body;
Little : constant Bit_Order := Low_Order_First;
Big : constant Bit_Order := High_Order_First;
generic
type Val is mod <>;
type Val_2 is mod <>;
with function Shift_Left
(Value : Val_2;
Amount : Natural) return Val_2 is <>;
with function Shift_Right
(Value : Val_2;
Amount : Natural) return Val_2 is <>;
Endian : Bit_Order := Default_Bit_Order;
package G is
-- Assert that Val has one of the allowed sizes, and that Val_2 is twice
-- that.
pragma Assert (Val'Size in 8 | 16 | 32);
pragma Assert (Val_2'Size = Val'Size * 2);
-- Assert that both are aligned the same, to the size in bytes of Val
-- (not Val_2).
pragma Assert (Val'Alignment = Val'Size / Storage_Unit);
pragma Assert (Val_2'Alignment = Val'Alignment);
type Val_Array is array (Positive range <>) of Val;
-- It might make more sense to have:
-- subtype Val is Val_2 range 0 .. 2**Val'Size - 1;
-- But then GNAT gets the component size of Val_Array wrong.
pragma Assert (Val_Array'Alignment = Val'Alignment);
pragma Assert (Val_Array'Component_Size = Val'Size);
subtype Bit_Size is Natural; -- Size in bits of a bit field
subtype Small_Size is Bit_Size range 0 .. Val'Size;
-- Size of a small one
subtype Bit_Offset is Small_Size range 0 .. Val'Size - 1;
-- Starting offset
subtype Bit_Offset_In_Byte is Bit_Offset range 0 .. Storage_Unit - 1;
procedure Copy_Bitfield
(Src_Address : Address;
Src_Offset : Bit_Offset_In_Byte;
Dest_Address : Address;
Dest_Offset : Bit_Offset_In_Byte;
Size : Bit_Size);
-- An Address and a Bit_Offset together form a "bit address". This
-- copies the source bit field to the destination. Size is the size in
-- bits of the bit field. The bit fields can be arbitrarily large, but
-- the starting offsets must be within the first byte that the Addresses
-- point to. The Address values need not be aligned.
--
-- For example, a slice assignment of a packed bit field:
--
-- D (D_First .. D_Last) := S (S_First .. S_Last);
--
-- can be implemented using:
--
-- Copy_Bitfield
-- (S (S_First)'Address, S (S_First)'Bit,
-- D (D_First)'Address, D (D_First)'Bit,
-- Size);
end G;
end System.Bitfield_Utils;
...@@ -220,6 +220,7 @@ package Rtsfind is ...@@ -220,6 +220,7 @@ package Rtsfind is
System_Atomic_Primitives, System_Atomic_Primitives,
System_Aux_DEC, System_Aux_DEC,
System_Bignums, System_Bignums,
System_Bitfields,
System_Bit_Ops, System_Bit_Ops,
System_Boolean_Array_Operations, System_Boolean_Array_Operations,
System_Byte_Swapping, System_Byte_Swapping,
...@@ -809,6 +810,8 @@ package Rtsfind is ...@@ -809,6 +810,8 @@ package Rtsfind is
RE_To_Bignum, -- System.Bignums RE_To_Bignum, -- System.Bignums
RE_From_Bignum, -- System.Bignums RE_From_Bignum, -- System.Bignums
RE_Copy_Bitfield, -- System.Bitfields
RE_Bit_And, -- System.Bit_Ops RE_Bit_And, -- System.Bit_Ops
RE_Bit_Eq, -- System.Bit_Ops RE_Bit_Eq, -- System.Bit_Ops
RE_Bit_Not, -- System.Bit_Ops RE_Bit_Not, -- System.Bit_Ops
...@@ -2051,6 +2054,8 @@ package Rtsfind is ...@@ -2051,6 +2054,8 @@ package Rtsfind is
RE_To_Bignum => System_Bignums, RE_To_Bignum => System_Bignums,
RE_From_Bignum => System_Bignums, RE_From_Bignum => System_Bignums,
RE_Copy_Bitfield => System_Bitfields,
RE_Bit_And => System_Bit_Ops, RE_Bit_And => System_Bit_Ops,
RE_Bit_Eq => System_Bit_Ops, RE_Bit_Eq => System_Bit_Ops,
RE_Bit_Not => System_Bit_Ops, RE_Bit_Not => System_Bit_Ops,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment