Commit 6bc08721 by Javier Miranda Committed by Pierre-Marie de Rodat

[Ada] Fix portability issues in access to subprograms

This patch improves the portability of the code generated by the
compiler for access to subprograms. Written by Richard Kenner.

2019-09-18  Javier Miranda  <miranda@adacore.com>

gcc/ada/

	* exp_ch4.adb (Expand_N_Op_Eq): The frontend assumes that we can
	do a bit-for-bit comparison of two access to protected
	subprogram pointers. However, there are two reasons why we may
	not be able to do that: (1) there may be padding bits for
	alignment before the access to subprogram, and (2) the access to
	subprogram itself may not be compared bit-for- bit because the
	activation record part is undefined: two pointers are equal iff
	the subprogram addresses are equal. This patch fixes it by
	forcing a field-by-field comparison.
	* bindgen.adb (Gen_Adainit): The type No_Param_Proc is defined
	in the library as having Favor_Top_Level, but when we create an
	object of that type in the binder file we don't have that
	pragma, so the types are different. This patch fixes this issue.
	* libgnarl/s-interr.adb, libgnarl/s-interr__hwint.adb,
	libgnarl/s-interr__sigaction.adb, libgnarl/s-interr__vxworks.adb
	(Is_Registered): This routine erroneously assumes that the
	access to protected subprogram is two addresses. We need to
	create the same record that the compiler makes to ensure that
	any padding is the same. Then we have to look at just the first
	word of the access to subprogram. This patch fixes this issue.

From-SVN: r275856
parent 0af16535
2019-09-18 Javier Miranda <miranda@adacore.com>
* exp_ch4.adb (Expand_N_Op_Eq): The frontend assumes that we can
do a bit-for-bit comparison of two access to protected
subprogram pointers. However, there are two reasons why we may
not be able to do that: (1) there may be padding bits for
alignment before the access to subprogram, and (2) the access to
subprogram itself may not be compared bit-for- bit because the
activation record part is undefined: two pointers are equal iff
the subprogram addresses are equal. This patch fixes it by
forcing a field-by-field comparison.
* bindgen.adb (Gen_Adainit): The type No_Param_Proc is defined
in the library as having Favor_Top_Level, but when we create an
object of that type in the binder file we don't have that
pragma, so the types are different. This patch fixes this issue.
* libgnarl/s-interr.adb, libgnarl/s-interr__hwint.adb,
libgnarl/s-interr__sigaction.adb, libgnarl/s-interr__vxworks.adb
(Is_Registered): This routine erroneously assumes that the
access to protected subprogram is two addresses. We need to
create the same record that the compiler makes to ensure that
any padding is the same. Then we have to look at just the first
word of the access to subprogram. This patch fixes this issue.
2019-09-18 Bob Duff <duff@adacore.com> 2019-09-18 Bob Duff <duff@adacore.com>
* exp_ch5.adb (Expand_Assign_Array_Loop_Or_Bitfield): The call * exp_ch5.adb (Expand_Assign_Array_Loop_Or_Bitfield): The call
......
...@@ -524,6 +524,7 @@ package body Bindgen is ...@@ -524,6 +524,7 @@ package body Bindgen is
and then not Configurable_Run_Time_On_Target and then not Configurable_Run_Time_On_Target
then then
WBI (" type No_Param_Proc is access procedure;"); WBI (" type No_Param_Proc is access procedure;");
WBI (" pragma Favor_Top_Level (No_Param_Proc);");
WBI (""); WBI ("");
end if; end if;
......
...@@ -8221,6 +8221,32 @@ package body Exp_Ch4 is ...@@ -8221,6 +8221,32 @@ package body Exp_Ch4 is
Insert_Actions (N, Bodies, Suppress => All_Checks); Insert_Actions (N, Bodies, Suppress => All_Checks);
Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks); Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
end if; end if;
-- If unnesting, handle elementary types whose Equivalent_Types are
-- records because there may be padding or undefined fields.
elsif Unnest_Subprogram_Mode
and then Ekind_In (Typl, E_Class_Wide_Type,
E_Class_Wide_Subtype,
E_Access_Subprogram_Type,
E_Access_Protected_Subprogram_Type,
E_Anonymous_Access_Protected_Subprogram_Type,
E_Access_Subprogram_Type,
E_Exception_Type)
and then Present (Equivalent_Type (Typl))
and then Is_Record_Type (Equivalent_Type (Typl))
then
Typl := Equivalent_Type (Typl);
Remove_Side_Effects (Lhs);
Remove_Side_Effects (Rhs);
Rewrite (N,
Expand_Record_Equality (N, Typl,
Unchecked_Convert_To (Typl, Lhs),
Unchecked_Convert_To (Typl, Rhs),
Bodies));
Insert_Actions (N, Bodies, Suppress => All_Checks);
Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
end if; end if;
-- Test if result is known at compile time -- Test if result is known at compile time
...@@ -9497,10 +9523,21 @@ package body Exp_Ch4 is ...@@ -9497,10 +9523,21 @@ package body Exp_Ch4 is
Typ : constant Entity_Id := Etype (Left_Opnd (N)); Typ : constant Entity_Id := Etype (Left_Opnd (N));
begin begin
-- Case of elementary type with standard operator -- Case of elementary type with standard operator. But if
-- unnesting, handle elementary types whose Equivalent_Types are
-- records because there may be padding or undefined fields.
if Is_Elementary_Type (Typ) if Is_Elementary_Type (Typ)
and then Sloc (Entity (N)) = Standard_Location and then Sloc (Entity (N)) = Standard_Location
and then not (Ekind_In (Typ, E_Class_Wide_Type,
E_Class_Wide_Subtype,
E_Access_Subprogram_Type,
E_Access_Protected_Subprogram_Type,
E_Anonymous_Access_Protected_Subprogram_Type,
E_Access_Subprogram_Type,
E_Exception_Type)
and then Present (Equivalent_Type (Typ))
and then Is_Record_Type (Equivalent_Type (Typ)))
then then
Binary_Op_Validity_Checks (N); Binary_Op_Validity_Checks (N);
......
...@@ -545,9 +545,11 @@ package body System.Interrupts is ...@@ -545,9 +545,11 @@ package body System.Interrupts is
function Is_Registered (Handler : Parameterless_Handler) return Boolean is function Is_Registered (Handler : Parameterless_Handler) return Boolean is
type Acc_Proc is access procedure;
type Fat_Ptr is record type Fat_Ptr is record
Object_Addr : System.Address; Object_Addr : System.Address;
Handler_Addr : System.Address; Handler_Addr : Acc_Proc;
end record; end record;
function To_Fat_Ptr is new Ada.Unchecked_Conversion function To_Fat_Ptr is new Ada.Unchecked_Conversion
...@@ -565,7 +567,7 @@ package body System.Interrupts is ...@@ -565,7 +567,7 @@ package body System.Interrupts is
Ptr := Registered_Handler_Head; Ptr := Registered_Handler_Head;
while Ptr /= null loop while Ptr /= null loop
if Ptr.H = Fat.Handler_Addr then if Ptr.H = Fat.Handler_Addr.all'Address then
return True; return True;
end if; end if;
......
...@@ -561,9 +561,12 @@ package body System.Interrupts is ...@@ -561,9 +561,12 @@ package body System.Interrupts is
------------------- -------------------
function Is_Registered (Handler : Parameterless_Handler) return Boolean is function Is_Registered (Handler : Parameterless_Handler) return Boolean is
type Acc_Proc is access procedure;
type Fat_Ptr is record type Fat_Ptr is record
Object_Addr : System.Address; Object_Addr : System.Address;
Handler_Addr : System.Address; Handler_Addr : Acc_Proc;
end record; end record;
function To_Fat_Ptr is new Ada.Unchecked_Conversion function To_Fat_Ptr is new Ada.Unchecked_Conversion
...@@ -581,7 +584,7 @@ package body System.Interrupts is ...@@ -581,7 +584,7 @@ package body System.Interrupts is
Ptr := Registered_Handler_Head; Ptr := Registered_Handler_Head;
while Ptr /= null loop while Ptr /= null loop
if Ptr.H = Fat.Handler_Addr then if Ptr.H = Fat.Handler_Addr.all'Address then
return True; return True;
end if; end if;
......
...@@ -487,9 +487,11 @@ package body System.Interrupts is ...@@ -487,9 +487,11 @@ package body System.Interrupts is
function Is_Registered (Handler : Parameterless_Handler) return Boolean is function Is_Registered (Handler : Parameterless_Handler) return Boolean is
Ptr : R_Link := Registered_Handlers; Ptr : R_Link := Registered_Handlers;
type Acc_Proc is access procedure;
type Fat_Ptr is record type Fat_Ptr is record
Object_Addr : System.Address; Object_Addr : System.Address;
Handler_Addr : System.Address; Handler_Addr : Acc_Proc;
end record; end record;
function To_Fat_Ptr is new Ada.Unchecked_Conversion function To_Fat_Ptr is new Ada.Unchecked_Conversion
...@@ -505,7 +507,7 @@ package body System.Interrupts is ...@@ -505,7 +507,7 @@ package body System.Interrupts is
Fat := To_Fat_Ptr (Handler); Fat := To_Fat_Ptr (Handler);
while Ptr /= null loop while Ptr /= null loop
if Ptr.H = Fat.Handler_Addr then if Ptr.H = Fat.Handler_Addr.all'Address then
return True; return True;
end if; end if;
......
...@@ -578,9 +578,12 @@ package body System.Interrupts is ...@@ -578,9 +578,12 @@ package body System.Interrupts is
------------------- -------------------
function Is_Registered (Handler : Parameterless_Handler) return Boolean is function Is_Registered (Handler : Parameterless_Handler) return Boolean is
type Acc_Proc is access procedure;
type Fat_Ptr is record type Fat_Ptr is record
Object_Addr : System.Address; Object_Addr : System.Address;
Handler_Addr : System.Address; Handler_Addr : Acc_Proc;
end record; end record;
function To_Fat_Ptr is new Ada.Unchecked_Conversion function To_Fat_Ptr is new Ada.Unchecked_Conversion
...@@ -598,7 +601,7 @@ package body System.Interrupts is ...@@ -598,7 +601,7 @@ package body System.Interrupts is
Ptr := Registered_Handler_Head; Ptr := Registered_Handler_Head;
while Ptr /= null loop while Ptr /= null loop
if Ptr.H = Fat.Handler_Addr then if Ptr.H = Fat.Handler_Addr.all'Address then
return True; return True;
end if; end if;
......
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