aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Charlet <charlet@gcc.gnu.org>2012-04-02 11:47:18 +0200
committerArnaud Charlet <charlet@gcc.gnu.org>2012-04-02 11:47:18 +0200
commit36504e5f465b19d444187bcee11a26e1842d277c (patch)
tree893cbf6d87b25d83e94a3593cf5409f73678e794
parent804670f120cd78a0304b630e7e53b1e13c9f5bfb (diff)
downloadgcc-36504e5f465b19d444187bcee11a26e1842d277c.zip
gcc-36504e5f465b19d444187bcee11a26e1842d277c.tar.gz
gcc-36504e5f465b19d444187bcee11a26e1842d277c.tar.bz2
[multiple changes]
2012-04-02 Yannick Moy <moy@adacore.com> * osint.adb, osint.ads (Add_Default_Search_Dirs): Add library search dirs in file specified with option -gnateO. 2012-04-02 Robert Dewar <dewar@adacore.com> * sem_ch5.adb, exp_util.adb, sem_util.adb, exp_ch4.adb: Minor reformatting. 2012-04-02 Olivier Hainque <hainque@adacore.com> * g-sse.ads: Add x86-solaris and x86_64-darwin to the set of platforms where the use of this spec is supported. Add current year to the copyright notice. * gcc-interfaces/Makefile.in: Add g-sse.o and g-ssvety.o to EXTRA_GNATRTL_NONTASKING_OBJS on x86 32/64 targets that support it and where they were missing (x86-solaris, x86-freebsd, x86_64-freebsd, and x86-darwin). 2012-04-02 Gary Dismukes <dismukes@adacore.com> * bindgen.adb (Gen_Ada_Init): When compiling for the AAMP small library, where we no longer suppress the Standard_Library, generate an empty body rather than the usual generation of assignments to imported globals, since those aren't present in the small library. 2012-04-02 Ed Schonberg <schonberg@adacore.com> * sinfo.ads: Minor documentation fix. 2012-04-02 Hristian Kirtchev <kirtchev@adacore.com> * sem_res.adb (Resolve_Conditional_Expression): Add local variables Else_Typ and Then_Typ. Add missing type conversions to the "then" and "else" expressions when their respective types are scalar. 2012-04-02 Vincent Pucci <pucci@adacore.com> * exp_ch9.adb: Reordering of the local subprograms. New Table for the lock free implementation that maps each protected subprograms with the protected component it references. (Allow_Lock_Free_Implementation): New routine. Check if the protected body enables the lock free implementation. (Build_Lock_Free_Protected_Subprogram_Body): New routine. (Build_Lock_Free_Unprotected_Subprogram_Body): New routine. (Comp_Of): New routine. * Makefile.rtl: Add s-atopri.o * debug.adb: New compiler debug flag -gnatd9 for lock free implementation. * rtsfind.ads: RE_Atomic_Compare_Exchange_8, RE_Atomic_Compare_Exchange_16, RE_Atomic_Compare_Exchange_32, RE_Atomic_Compare_Exchange_64, RE_Atomic_Load_8, RE_Atomic_Load_16, RE_Atomic_Load_32, RE_Atomic_Load_64, RE_Uint8, RE_Uint16, RE_Uint32, RE_Uint64 added. * s-atropi.ads: New file. Defines atomic primitives used by the lock free implementation. From-SVN: r186076
-rw-r--r--gcc/ada/ChangeLog59
-rw-r--r--gcc/ada/Makefile.rtl1
-rw-r--r--gcc/ada/bindgen.adb10
-rw-r--r--gcc/ada/debug.adb5
-rw-r--r--gcc/ada/exp_ch4.adb7
-rw-r--r--gcc/ada/exp_ch9.adb1221
-rw-r--r--gcc/ada/exp_util.adb5
-rw-r--r--gcc/ada/g-sse.ads4
-rw-r--r--gcc/ada/gcc-interface/Makefile.in12
-rw-r--r--gcc/ada/osint.adb11
-rw-r--r--gcc/ada/osint.ads5
-rw-r--r--gcc/ada/rtsfind.ads27
-rw-r--r--gcc/ada/s-atopri.ads120
-rw-r--r--gcc/ada/sem_ch5.adb3
-rw-r--r--gcc/ada/sem_res.adb29
-rw-r--r--gcc/ada/sem_util.adb11
-rw-r--r--gcc/ada/sinfo.ads2
17 files changed, 1327 insertions, 205 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 73da545..26f77b8 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,62 @@
+2012-04-02 Yannick Moy <moy@adacore.com>
+
+ * osint.adb, osint.ads (Add_Default_Search_Dirs): Add library
+ search dirs in file specified with option -gnateO.
+
+2012-04-02 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch5.adb, exp_util.adb, sem_util.adb, exp_ch4.adb: Minor
+ reformatting.
+
+2012-04-02 Olivier Hainque <hainque@adacore.com>
+
+ * g-sse.ads: Add x86-solaris and x86_64-darwin to the set of
+ platforms where the use of this spec is supported. Add current
+ year to the copyright notice.
+ * gcc-interfaces/Makefile.in: Add g-sse.o and g-ssvety.o to
+ EXTRA_GNATRTL_NONTASKING_OBJS on x86 32/64 targets that support
+ it and where they were missing (x86-solaris, x86-freebsd,
+ x86_64-freebsd, and x86-darwin).
+
+2012-04-02 Gary Dismukes <dismukes@adacore.com>
+
+ * bindgen.adb (Gen_Ada_Init): When compiling for the AAMP small
+ library, where we no longer suppress the Standard_Library,
+ generate an empty body rather than the usual generation of
+ assignments to imported globals, since those aren't present in
+ the small library.
+
+2012-04-02 Ed Schonberg <schonberg@adacore.com>
+
+ * sinfo.ads: Minor documentation fix.
+
+2012-04-02 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_res.adb (Resolve_Conditional_Expression): Add local variables
+ Else_Typ and Then_Typ. Add missing type conversions to the "then" and
+ "else" expressions when their respective types are scalar.
+
+2012-04-02 Vincent Pucci <pucci@adacore.com>
+
+ * exp_ch9.adb: Reordering of the local subprograms. New Table
+ for the lock free implementation that maps each protected
+ subprograms with the protected component it references.
+ (Allow_Lock_Free_Implementation): New routine. Check if
+ the protected body enables the lock free implementation.
+ (Build_Lock_Free_Protected_Subprogram_Body): New routine.
+ (Build_Lock_Free_Unprotected_Subprogram_Body): New routine.
+ (Comp_Of): New routine.
+ * Makefile.rtl: Add s-atopri.o
+ * debug.adb: New compiler debug flag -gnatd9 for lock free
+ implementation.
+ * rtsfind.ads: RE_Atomic_Compare_Exchange_8,
+ RE_Atomic_Compare_Exchange_16, RE_Atomic_Compare_Exchange_32,
+ RE_Atomic_Compare_Exchange_64, RE_Atomic_Load_8,
+ RE_Atomic_Load_16, RE_Atomic_Load_32, RE_Atomic_Load_64, RE_Uint8,
+ RE_Uint16, RE_Uint32, RE_Uint64 added.
+ * s-atropi.ads: New file. Defines atomic primitives used
+ by the lock free implementation.
+
2012-04-02 Emmanuel Briot <briot@adacore.com>
* g-expect.adb (Expect_Internal): Fix leak of the input file descriptor.
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 7169658..d3212b2 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -479,6 +479,7 @@ GNATRTL_NONTASKING_OBJS= \
s-assert$(objext) \
s-atacco$(objext) \
s-atocou$(objext) \
+ s-atopri$(objext) \
s-auxdec$(objext) \
s-bitops$(objext) \
s-boarop$(objext) \
diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb
index a4b7d39..c44a648 100644
--- a/gcc/ada/bindgen.adb
+++ b/gcc/ada/bindgen.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2012, 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- --
@@ -511,6 +511,14 @@ package body Bindgen is
if CodePeer_Mode then
WBI (" begin");
+ -- When compiling for the AAMP small library, where the standard library
+ -- is no longer suppressed, we still want to exclude the setting of the
+ -- various imported globals, which aren't present for that library.
+
+ elsif AAMP_On_Target and then Configurable_Run_Time_On_Target then
+ WBI (" begin");
+ WBI (" null;");
+
-- If the standard library is suppressed, then the only global variables
-- that might be needed (by the Ravenscar profile) are the priority and
-- the processor for the environment task.
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index bb3e485..cbcdf0c 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -153,7 +153,7 @@ package body Debug is
-- d6 Default access unconstrained to thin pointers
-- d7 Do not output version & file time stamp in -gnatv or -gnatl mode
-- d8 Force opposite endianness in packed stuff
- -- d9
+ -- d9 Allow lock free implementation
-- Debug flags for binder (GNATBIND)
@@ -710,6 +710,9 @@ package body Debug is
-- opposite endianness from the actual correct value. Useful in
-- testing out code generation from the packed routines.
+ -- d9 This allows lock free implementation for protected objects
+ -- (see Exp_Ch9).
+
------------------------------------------
-- Documentation for Binder Debug Flags --
------------------------------------------
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index d08e375..02a733c 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -7832,9 +7832,7 @@ package body Exp_Ch4 is
begin
-- Do validity check if validity checking operands
- if Validity_Checks_On
- and then Validity_Check_Operands
- then
+ if Validity_Checks_On and then Validity_Check_Operands then
Ensure_Valid (Operand);
end if;
@@ -7866,7 +7864,7 @@ package body Exp_Ch4 is
-- end if;
-- end loop;
- -- Conversely, an existentially quantified expression:
+ -- Similarly, an existentially quantified expression:
-- for some X in range => Cond
@@ -7957,7 +7955,6 @@ package body Exp_Ch4 is
Make_Expression_With_Actions (Loc,
Expression => New_Occurrence_Of (Flag, Loc),
Actions => Actions));
-
Analyze_And_Resolve (N, Standard_Boolean);
end Expand_N_Quantified_Expression;
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index a827284..212ed30 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -25,6 +25,7 @@
with Atree; use Atree;
with Checks; use Checks;
+with Debug; use Debug;
with Einfo; use Einfo;
with Elists; use Elists;
with Errout; use Errout;
@@ -60,6 +61,7 @@ with Sinfo; use Sinfo;
with Snames; use Snames;
with Stand; use Stand;
with Stringt; use Stringt;
+with Table;
with Targparm; use Targparm;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
@@ -75,6 +77,34 @@ package body Exp_Ch9 is
Entry_Family_Bound : constant Int := 2**16;
+ ------------------------------
+ -- Lock Free Data Structure --
+ ------------------------------
+
+ -- A data structure used for the Lock Free (LF) implementation of protected
+ -- objects. Since a protected subprogram can only access a single protected
+ -- component in the LF implementation, this structure stores each protected
+ -- subprogram and its accessed protected component when the protected
+ -- object allows the LF implementation.
+
+ type Lock_Free_Sub_Type is record
+ Sub_Body : Node_Id;
+ Comp_Id : Entity_Id;
+ end record;
+
+ subtype Subprogram_Id is Nat;
+
+ -- The following table used for the Lock Free implementation of protected
+ -- objects maps Lock_Free_Sub_Type to Subprogram_Id.
+
+ package LF_Sub_Table is new Table.Table (
+ Table_Component_Type => Lock_Free_Sub_Type,
+ Table_Index_Type => Subprogram_Id,
+ Table_Low_Bound => 1,
+ Table_Initial => 5,
+ Table_Increment => 5,
+ Table_Name => "LF_Sub_Table");
+
-----------------------
-- Local Subprograms --
-----------------------
@@ -109,6 +139,10 @@ package body Exp_Ch9 is
-- Decls is the list of declarations to be enhanced.
-- Ent is the entity for the original entry body.
+ function Allow_Lock_Free_Implementation (N : Node_Id) return Boolean;
+ -- Given a protected body N, return True if N permits a lock free
+ -- implementation.
+
function Build_Accept_Body (Astat : Node_Id) return Node_Id;
-- Transform accept statement into a block with added exception handler.
-- Used both for simple accept statements and for accept alternatives in
@@ -144,6 +178,32 @@ package body Exp_Ch9 is
-- of the range of each entry family. A single array with that size is
-- allocated for each concurrent object of the type.
+ function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id;
+ -- Build the function that translates the entry index in the call
+ -- (which depends on the size of entry families) into an index into the
+ -- Entry_Bodies_Array, to determine the body and barrier function used
+ -- in a protected entry call. A pointer to this function appears in every
+ -- protected object.
+
+ function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id;
+ -- Build subprogram declaration for previous one
+
+ function Build_Lock_Free_Protected_Subprogram_Body
+ (N : Node_Id;
+ Pid : Node_Id;
+ N_Op_Spec : Node_Id) return Node_Id;
+ -- This function is used to construct the lock free version of a protected
+ -- subprogram when the protected type denoted by Pid allows the lock free
+ -- implementation. It only contains a call to the unprotected version of
+ -- the subprogram body.
+
+ function Build_Lock_Free_Unprotected_Subprogram_Body
+ (N : Node_Id;
+ Pid : Node_Id) return Node_Id;
+ -- This function is used to construct the lock free version of an
+ -- unprotected subprogram when the protected type denoted by Pid allows the
+ -- lock free implementation.
+
function Build_Parameter_Block
(Loc : Source_Ptr;
Actuals : List_Id;
@@ -169,49 +229,6 @@ package body Exp_Ch9 is
-- and Decl is the enclosing synchronized type declaration at whose
-- freeze point the generated body is analyzed.
- function Build_Renamed_Formal_Declaration
- (New_F : Entity_Id;
- Formal : Entity_Id;
- Comp : Entity_Id;
- Renamed_Formal : Node_Id) return Node_Id;
- -- Create a renaming declaration for a formal, within a protected entry
- -- body or an accept body. The renamed object is a component of the
- -- parameter block that is a parameter in the entry call.
-
- -- In Ada 2012, if the formal is an incomplete tagged type, the renaming
- -- does not dereference the corresponding component to prevent an illegal
- -- use of the incomplete type (AI05-0151).
-
- procedure Build_Wrapper_Bodies
- (Loc : Source_Ptr;
- Typ : Entity_Id;
- N : Node_Id);
- -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
- -- record of a concurrent type. N is the insertion node where all bodies
- -- will be placed. This routine builds the bodies of the subprograms which
- -- serve as an indirection mechanism to overriding primitives of concurrent
- -- types, entries and protected procedures. Any new body is analyzed.
-
- procedure Build_Wrapper_Specs
- (Loc : Source_Ptr;
- Typ : Entity_Id;
- N : in out Node_Id);
- -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
- -- record of a concurrent type. N is the insertion node where all specs
- -- will be placed. This routine builds the specs of the subprograms which
- -- serve as an indirection mechanism to overriding primitives of concurrent
- -- types, entries and protected procedures. Any new spec is analyzed.
-
- function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id;
- -- Build the function that translates the entry index in the call
- -- (which depends on the size of entry families) into an index into the
- -- Entry_Bodies_Array, to determine the body and barrier function used
- -- in a protected entry call. A pointer to this function appears in every
- -- protected object.
-
- function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id;
- -- Build subprogram declaration for previous one
-
function Build_Protected_Entry
(N : Node_Id;
Ent : Entity_Id;
@@ -252,6 +269,19 @@ package body Exp_Ch9 is
-- a cleanup handler that unlocks the object in all cases.
-- (see Exp_Ch7.Expand_Cleanup_Actions).
+ function Build_Renamed_Formal_Declaration
+ (New_F : Entity_Id;
+ Formal : Entity_Id;
+ Comp : Entity_Id;
+ Renamed_Formal : Node_Id) return Node_Id;
+ -- Create a renaming declaration for a formal, within a protected entry
+ -- body or an accept body. The renamed object is a component of the
+ -- parameter block that is a parameter in the entry call.
+ --
+ -- In Ada 2012, if the formal is an incomplete tagged type, the renaming
+ -- does not dereference the corresponding component to prevent an illegal
+ -- use of the incomplete type (AI05-0151).
+
function Build_Selected_Name
(Prefix : Entity_Id;
Selector : Entity_Id;
@@ -291,6 +321,26 @@ package body Exp_Ch9 is
-- subprogram that is called from all protected operations on the same
-- object, including the protected version of the same subprogram.
+ procedure Build_Wrapper_Bodies
+ (Loc : Source_Ptr;
+ Typ : Entity_Id;
+ N : Node_Id);
+ -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
+ -- record of a concurrent type. N is the insertion node where all bodies
+ -- will be placed. This routine builds the bodies of the subprograms which
+ -- serve as an indirection mechanism to overriding primitives of concurrent
+ -- types, entries and protected procedures. Any new body is analyzed.
+
+ procedure Build_Wrapper_Specs
+ (Loc : Source_Ptr;
+ Typ : Entity_Id;
+ N : in out Node_Id);
+ -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
+ -- record of a concurrent type. N is the insertion node where all specs
+ -- will be placed. This routine builds the specs of the subprograms which
+ -- serve as an indirection mechanism to overriding primitives of concurrent
+ -- types, entries and protected procedures. Any new spec is analyzed.
+
procedure Collect_Entry_Families
(Loc : Source_Ptr;
Cdecls : List_Id;
@@ -299,6 +349,10 @@ package body Exp_Ch9 is
-- For each entry family in a concurrent type, create an anonymous array
-- type of the right size, and add a component to the corresponding_record.
+ function Comp_Of (Sub_Body : Node_Id) return Entity_Id;
+ -- For the lock free implementation, return the protected component entity
+ -- referenced in Sub_Body using LF_Sub_Table.
+
function Concurrent_Object
(Spec_Id : Entity_Id;
Conc_Typ : Entity_Id) return Entity_Id;
@@ -322,6 +376,26 @@ package body Exp_Ch9 is
-- step of the expansion must to be done after private data has been moved
-- to its final resting scope to ensure proper visibility of debug objects.
+ procedure Extract_Dispatching_Call
+ (N : Node_Id;
+ Call_Ent : out Entity_Id;
+ Object : out Entity_Id;
+ Actuals : out List_Id;
+ Formals : out List_Id);
+ -- Given a dispatching call, extract the entity of the name of the call,
+ -- its actual dispatching object, its actual parameters and the formal
+ -- parameters of the overridden interface-level version. If the type of
+ -- the dispatching object is an access type then an explicit dereference
+ -- is returned in Object.
+
+ procedure Extract_Entry
+ (N : Node_Id;
+ Concval : out Node_Id;
+ Ename : out Node_Id;
+ Index : out Node_Id);
+ -- Given an entry call, returns the associated concurrent object,
+ -- the entry name, and the entry family index.
+
function Family_Offset
(Loc : Source_Ptr;
Hi : Node_Id;
@@ -358,26 +432,6 @@ package body Exp_Ch9 is
-- the scope of Context_Id and Context_Decls is the declarative list of
-- Context.
- procedure Extract_Dispatching_Call
- (N : Node_Id;
- Call_Ent : out Entity_Id;
- Object : out Entity_Id;
- Actuals : out List_Id;
- Formals : out List_Id);
- -- Given a dispatching call, extract the entity of the name of the call,
- -- its actual dispatching object, its actual parameters and the formal
- -- parameters of the overridden interface-level version. If the type of
- -- the dispatching object is an access type then an explicit dereference
- -- is returned in Object.
-
- procedure Extract_Entry
- (N : Node_Id;
- Concval : out Node_Id;
- Ename : out Node_Id;
- Index : out Node_Id);
- -- Given an entry call, returns the associated concurrent object,
- -- the entry name, and the entry family index.
-
function Find_Task_Or_Protected_Pragma
(T : Node_Id;
P : Name_Id) return Node_Id;
@@ -393,6 +447,9 @@ package body Exp_Ch9 is
-- Task_Body_Procedure of Spec_Id. The returned entity denotes formal
-- parameter _E.
+ function Is_Exception_Safe (Subprogram : Node_Id) return Boolean;
+ -- Tell whether a given subprogram cannot raise an exception
+
function Is_Potentially_Large_Family
(Base_Index : Entity_Id;
Conctyp : Entity_Id;
@@ -762,6 +819,263 @@ package body Exp_Ch9 is
Prepend_To (Decls, Decl);
end Add_Object_Pointer;
+ ------------------------------------
+ -- Allow_Lock_Free_Implementation --
+ ------------------------------------
+
+ -- Here are the restrictions for the Lock Free implementation
+
+ -- Implementation Restrictions on protected declaration
+
+ -- There must be only protected scalar components (at least one)
+
+ -- Component types must support an atomic compare_exchange primitive
+ -- (size equals to 1, 2, 4 or 8 bytes).
+
+ -- No entries
+
+ -- Implementation Restrictions on protected operations
+
+ -- Cannot refer to non-constant outside of the scope of the protected
+ -- operation.
+
+ -- Can only access a single protected component: all protected
+ -- component names appearing in a scope (including nested scopes)
+ -- must statically denote the same protected component.
+
+ -- Fundamental Restrictions on protected operations
+
+ -- No loop and procedure call statements
+
+ -- Any function call and attribute reference must be static
+
+ function Allow_Lock_Free_Implementation (N : Node_Id) return Boolean is
+ Decls : constant List_Id := Declarations (N);
+ Spec : constant Entity_Id := Corresponding_Spec (N);
+ Pro_Def : constant Node_Id := Protected_Definition (Parent (Spec));
+ Pri_Decls : constant List_Id := Private_Declarations (Pro_Def);
+ Vis_Decls : constant List_Id := Visible_Declarations (Pro_Def);
+
+ Comp_Id : Entity_Id;
+ Comp_Size : Int;
+ Comp_Type : Entity_Id;
+ No_Component : Boolean := True;
+ N_Decl : Node_Id;
+
+ function Permit_Lock_Free (Sub_Body : Node_Id) return Boolean;
+ -- Return True if the protected subprogram body Sub_Body doesn't
+ -- prevent the lock free code expansion, i.e. Sub_Body meets all the
+ -- restrictions listed below that allow the lock free implementation.
+ --
+ -- Can only access a single protected component
+ --
+ -- No loop and procedure call statements
+
+ -- Any function call and attribute reference must be static
+
+ -- Cannot refer to non-constant outside of the scope of the protected
+ -- subprogram.
+
+ ----------------------
+ -- Permit_Lock_Free --
+ ----------------------
+
+ function Permit_Lock_Free (Sub_Body : Node_Id) return Boolean is
+ Sub_Id : constant Entity_Id := Corresponding_Spec (Sub_Body);
+ Comp_Id : Entity_Id := Empty;
+ LF_Sub : Lock_Free_Sub_Type;
+
+ function Check_Node (N : Node_Id) return Traverse_Result;
+ -- Check the node N meet the lock free restrictions
+
+ function Check_All_Nodes is new Traverse_Func (Check_Node);
+
+ ----------------
+ -- Check_Node --
+ ----------------
+
+ function Check_Node (N : Node_Id) return Traverse_Result is
+ Comp_Decl : Node_Id;
+ Id : Entity_Id;
+
+ begin
+ case Nkind (N) is
+
+ -- Function call or attribute reference case
+
+ when N_Function_Call | N_Attribute_Reference =>
+
+ -- Any function call and attribute reference must be static
+
+ if not Is_Static_Expression (N) then
+ return Abandon;
+ end if;
+
+ -- Loop and procedure call statement case
+
+ when N_Procedure_Call_Statement | N_Loop_Statement =>
+ -- No loop and procedure call statements
+ return Abandon;
+
+ -- Identifier case
+
+ when N_Identifier =>
+ if Present (Entity (N)) then
+ Id := Entity (N);
+
+ -- Cannot refer to non-constant entities outside of the
+ -- scope of the protected subprogram.
+
+ if Ekind (Id) in Assignable_Kind
+ and then Sloc (Scope (Id)) > No_Location
+ and then not Scope_Within_Or_Same (Scope (Id), Sub_Id)
+ and then not Scope_Within_Or_Same (Scope (Id),
+ Protected_Body_Subprogram (Sub_Id))
+ then
+ return Abandon;
+ end if;
+
+ -- Can only access a single protected component
+
+ if Ekind_In (Id, E_Constant, E_Variable)
+ and then Present (Prival_Link (Id))
+ then
+ Comp_Decl := Parent (Prival_Link (Id));
+
+ if Nkind (Comp_Decl) = N_Component_Declaration
+ and then Is_List_Member (Comp_Decl)
+ and then List_Containing (Comp_Decl) = Pri_Decls
+ then
+ -- Check if another protected component has already
+ -- been accessed by the subprogram body.
+
+ if Present (Comp_Id)
+ and then Comp_Id /= Prival_Link (Id)
+ then
+ return Abandon;
+
+ elsif not Present (Comp_Id) then
+ Comp_Id := Prival_Link (Id);
+ end if;
+ end if;
+ end if;
+ end if;
+
+ -- Ok for all other nodes
+
+ when others => return OK;
+ end case;
+
+ return OK;
+ end Check_Node;
+
+ -- Start of processing for Permit_Lock_Free
+
+ begin
+ if Check_All_Nodes (Sub_Body) = OK then
+
+ -- Fill LF_Sub with Sub_Body and its corresponding protected
+ -- component entity and then store LF_Sub in the lock free
+ -- subprogram table LF_Sub_Table.
+
+ LF_Sub.Sub_Body := Sub_Body;
+ LF_Sub.Comp_Id := Comp_Id;
+ LF_Sub_Table.Append (LF_Sub);
+ return True;
+
+ else
+ return False;
+ end if;
+ end Permit_Lock_Free;
+
+ -- Start of processing for Allow_Lock_Free_Implementation
+
+ begin
+ -- Debug switch -gnatd9 enables Lock Free implementation
+
+ if not Debug_Flag_9 then
+ return False;
+ end if;
+
+ -- Look for any entries declared in the visible part of the protected
+ -- declaration.
+
+ N_Decl := First (Vis_Decls);
+ while Present (N_Decl) loop
+ if Nkind (N_Decl) = N_Entry_Declaration then
+ return False;
+ end if;
+
+ N_Decl := Next (N_Decl);
+ end loop;
+
+ -- Look for any entry, plus look for any scalar component declared in
+ -- the private part of the protected declaration.
+
+ N_Decl := First (Pri_Decls);
+ while Present (N_Decl) loop
+
+ -- Check at least one scalar component is declared
+
+ if Nkind (N_Decl) = N_Component_Declaration then
+ if No_Component then
+ No_Component := False;
+ end if;
+
+ Comp_Id := Defining_Identifier (N_Decl);
+ Comp_Type := Etype (Comp_Id);
+
+ -- Verify the component is a scalar
+
+ if not Is_Scalar_Type (Comp_Type) then
+ return False;
+ end if;
+
+ Comp_Size := UI_To_Int (Esize (Base_Type (Comp_Type)));
+
+ -- Check the size of the component is 8, 16, 32 or 64 bits
+
+ case Comp_Size is
+ when 8 | 16 | 32 | 64 =>
+ null;
+ when others =>
+ return False;
+ end case;
+
+ -- Check there is no entry declared in the private part.
+
+ else
+ if Nkind (N_Decl) = N_Entry_Declaration then
+ return False;
+ end if;
+ end if;
+
+ N_Decl := Next (N_Decl);
+ end loop;
+
+ -- One scalar component must be present
+
+ if No_Component then
+ return False;
+ end if;
+
+ -- Ensure all protected subprograms meet the restrictions that allow the
+ -- lock free implementation.
+
+ N_Decl := First (Decls);
+ while Present (N_Decl) loop
+ if Nkind (N_Decl) = N_Subprogram_Body
+ and then not Permit_Lock_Free (N_Decl)
+ then
+ return False;
+ end if;
+
+ Next (N_Decl);
+ end loop;
+
+ return True;
+ end Allow_Lock_Free_Implementation;
+
-----------------------
-- Build_Accept_Body --
-----------------------
@@ -2720,18 +3034,16 @@ package body Exp_Ch9 is
if No (If_St) then
If_St :=
Make_Implicit_If_Statement (Typ,
- Condition => Cond,
+ Condition => Cond,
Then_Statements => Stats,
- Elsif_Parts => New_List);
-
+ Elsif_Parts => New_List);
Ret := If_St;
else
- Append (
+ Append_To (Elsif_Parts (If_St),
Make_Elsif_Part (Loc,
Condition => Cond,
- Then_Statements => Stats),
- Elsif_Parts (If_St));
+ Then_Statements => Stats));
end if;
end Add_If_Clause;
@@ -2788,7 +3100,7 @@ package body Exp_Ch9 is
else
-- Suppose entries e1, e2, ... have size l1, l2, ... we generate
-- the following:
- --
+
-- if E <= l1 then return 1;
-- elsif E <= l1 + l2 then return 2;
-- ...
@@ -2834,8 +3146,8 @@ package body Exp_Ch9 is
return
Make_Subprogram_Body (Loc,
- Specification => Spec,
- Declarations => Decls,
+ Specification => Spec,
+ Declarations => Decls,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
Statements => New_List (Ret)));
@@ -2856,21 +3168,543 @@ package body Exp_Ch9 is
begin
return
Make_Function_Specification (Loc,
- Defining_Unit_Name => Id,
+ Defining_Unit_Name => Id,
Parameter_Specifications => New_List (
Make_Parameter_Specification (Loc,
Defining_Identifier => Parm1,
- Parameter_Type =>
+ Parameter_Type =>
New_Reference_To (RTE (RE_Address), Loc)),
Make_Parameter_Specification (Loc,
Defining_Identifier => Parm2,
- Parameter_Type =>
+ Parameter_Type =>
New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))),
- Result_Definition => New_Occurrence_Of (
+
+ Result_Definition => New_Occurrence_Of (
RTE (RE_Protected_Entry_Index), Loc));
end Build_Find_Body_Index_Spec;
+ -----------------------------------------------
+ -- Build_Lock_Free_Protected_Subprogram_Body --
+ -----------------------------------------------
+
+ function Build_Lock_Free_Protected_Subprogram_Body
+ (N : Node_Id;
+ Pid : Node_Id;
+ N_Op_Spec : Node_Id) return Node_Id
+ is
+ Loc : constant Source_Ptr := Sloc (N);
+ Op_Spec : Node_Id;
+ P_Op_Spec : Node_Id;
+ Uactuals : List_Id;
+ Pformal : Node_Id;
+ Unprot_Call : Node_Id;
+ R : Node_Id;
+ Return_Stmt : Node_Id := Empty; -- init to avoid gcc 3 warning
+ Exc_Safe : Boolean;
+
+ begin
+ Op_Spec := Specification (N);
+ Exc_Safe := Is_Exception_Safe (N);
+
+ P_Op_Spec :=
+ Build_Protected_Sub_Specification (N, Pid, Protected_Mode);
+
+ -- Build a list of the formal parameters of the protected version of
+ -- the subprogram to use as the actual parameters of the unprotected
+ -- version.
+
+ Uactuals := New_List;
+ Pformal := First (Parameter_Specifications (P_Op_Spec));
+ while Present (Pformal) loop
+ Append_To (Uactuals,
+ Make_Identifier (Loc, Chars (Defining_Identifier (Pformal))));
+ Next (Pformal);
+ end loop;
+
+ -- Make a call to the unprotected version of the subprogram built above
+ -- for use by the protected version built below.
+
+ if Nkind (Op_Spec) = N_Function_Specification then
+ if Exc_Safe then
+ R := Make_Temporary (Loc, 'R');
+ Unprot_Call :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => R,
+ Constant_Present => True,
+ Object_Definition => New_Copy (Result_Definition (N_Op_Spec)),
+ Expression =>
+ Make_Function_Call (Loc,
+ Name => Make_Identifier (Loc,
+ Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
+ Parameter_Associations => Uactuals));
+
+ Return_Stmt :=
+ Make_Simple_Return_Statement (Loc,
+ Expression => New_Reference_To (R, Loc));
+
+ else
+ Unprot_Call := Make_Simple_Return_Statement (Loc,
+ Expression => Make_Function_Call (Loc,
+ Name =>
+ Make_Identifier (Loc,
+ Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
+ Parameter_Associations => Uactuals));
+ end if;
+
+ else
+ Unprot_Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ Make_Identifier (Loc, Chars (Defining_Unit_Name (N_Op_Spec))),
+ Parameter_Associations => Uactuals);
+ end if;
+
+ if Nkind (Op_Spec) = N_Function_Specification
+ and then Exc_Safe
+ then
+ Unprot_Call :=
+ Make_Block_Statement (Loc,
+ Declarations => New_List (Unprot_Call),
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Return_Stmt)));
+ end if;
+
+ return
+ Make_Subprogram_Body (Loc,
+ Declarations => Empty_List,
+ Specification => P_Op_Spec,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Unprot_Call)));
+ end Build_Lock_Free_Protected_Subprogram_Body;
+
+ -------------------------------------------------
+ -- Build_Lock_Free_Unprotected_Subprogram_Body --
+ -------------------------------------------------
+
+ function Build_Lock_Free_Unprotected_Subprogram_Body
+ (N : Node_Id;
+ Pid : Node_Id) return Node_Id
+ is
+ Decls : constant List_Id := Declarations (N);
+ Is_Procedure : constant Boolean :=
+ Ekind (Corresponding_Spec (N)) = E_Procedure;
+ Loc : constant Source_Ptr := Sloc (N);
+
+ function Ren_Comp_Id (Decls : List_Id) return Entity_Id;
+ -- Given the list of delaration Decls, return the renamed entity
+ -- of the protected component accessed by the subprogram body.
+
+ -----------------
+ -- Ren_Comp_Id --
+ -----------------
+
+ function Ren_Comp_Id (Decls : List_Id) return Entity_Id is
+ N_Decl : Node_Id;
+ Pri_Link : Node_Id;
+
+ begin
+ N_Decl := First (Decls);
+ while Present (N_Decl) loop
+
+ -- Look for a renaming declaration
+
+ if Nkind (N_Decl) = N_Object_Renaming_Declaration then
+ Pri_Link := Prival_Link (Defining_Identifier (N_Decl));
+
+ -- Compare the renamed entity and the accessed component entity
+ -- in the LF_Sub_Table.
+
+ if Present (Pri_Link) and then Pri_Link = Comp_Of (N) then
+ return Defining_Identifier (N_Decl);
+ end if;
+ end if;
+
+ Next (N_Decl);
+ end loop;
+
+ return Empty;
+ end Ren_Comp_Id;
+
+ Obj_Id : constant Entity_Id := Ren_Comp_Id (Decls);
+ At_Comp_Id : Entity_Id;
+ At_Load_Id : Entity_Id;
+ Copy_Id : Entity_Id;
+ Exit_Stmt : Node_Id;
+ Label : Node_Id := Empty;
+ Label_Id : Entity_Id;
+ New_Body : Node_Id;
+ New_Decls : List_Id;
+ New_Stmts : List_Id;
+ Obj_Typ : Entity_Id;
+ Old_Id : Entity_Id;
+ Typ_Size : Int;
+ Unsigned_Id : Entity_Id;
+
+ function Make_If (Stmt : Node_Id) return Node_Id;
+ -- Given the statement Stmt, return an if statement with Stmt at the end
+ -- of the list of statements.
+
+ procedure Process_Stmts (Stmts : List_Id);
+ -- Wrap each return and raise statements in Stmts into an if statement
+ -- generated by Make_If. Replace all references to the protected object
+ -- Obj by a reference to its copy Obj_Copy.
+
+ -------------
+ -- Make_If --
+ -------------
+
+ function Make_If (Stmt : Node_Id) return Node_Id is
+ begin
+ -- Generate (for Typ_Size = 32):
+
+ -- if System.Atomic_Primitives.Atomic_Compare_Exchange_32
+ -- (Obj'Address,
+ -- Interfaces.Unsigned_32! (Obj_Old),
+ -- Interfaces.Unsigned_32! (Obj_Copy));
+ -- then
+ -- < Stmt >
+ -- else
+ -- goto L0;
+ -- end if;
+
+ -- Check whether a label has already been created
+
+ if not Present (Label) then
+
+ -- Create a label which will point just after the last
+ -- statement of the loop statement generated in step 3.
+
+ -- Generate:
+
+ -- L0 : Label;
+
+ Label_Id :=
+ Make_Identifier (Loc, New_External_Name ('L', 0));
+
+ Set_Entity (Label_Id,
+ Make_Defining_Identifier (Loc, Chars (Label_Id)));
+ Label := Make_Label (Loc, Label_Id);
+
+ Append_To (Decls,
+ Make_Implicit_Label_Declaration (Loc,
+ Defining_Identifier => Entity (Label_Id),
+ Label_Construct => Label));
+ end if;
+
+ return
+ Make_If_Statement (Loc,
+ Condition =>
+ Make_Function_Call (Loc,
+ Name => New_Reference_To (At_Comp_Id, Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Obj_Id, Loc),
+ Attribute_Name => Name_Address),
+ Unchecked_Convert_To (Unsigned_Id,
+ New_Reference_To (Old_Id, Loc)),
+ Unchecked_Convert_To (Unsigned_Id,
+ New_Reference_To (Copy_Id, Loc)))),
+
+ Then_Statements => New_List (
+ Relocate_Node (Stmt)),
+
+ Else_Statements => New_List (
+ Make_Goto_Statement (Loc,
+ Name => New_Reference_To (Entity (Label_Id), Loc))));
+ end Make_If;
+
+ -------------------
+ -- Process_Stmts --
+ -------------------
+
+ procedure Process_Stmts (Stmts : List_Id) is
+ Stmt : Node_Id;
+
+ function Check_Node (N : Node_Id) return Traverse_Result;
+ -- Recognize a return and raise statement and wrap it into an if
+ -- statement. Replace all references to the protected object by
+ -- a reference to its copy. Reset all Analyzed flags in order to
+ -- reanalyze statments inside the new unprotected subprogram body.
+
+ procedure Process_Nodes is
+ new Traverse_Proc (Check_Node);
+
+ ----------------
+ -- Check_Node --
+ ----------------
+
+ function Check_Node (N : Node_Id) return Traverse_Result is
+ begin
+ -- In case of a procedure, wrap each return and raise statements
+ -- inside an if statement created by Make_If.
+
+ if Is_Procedure
+ and then Nkind_In (N, N_Simple_Return_Statement,
+ N_Extended_Return_Statement,
+ N_Raise_Statement)
+ and then
+ (Nkind (N) /= N_Simple_Return_Statement
+ or else N /= Last (Stmts))
+ then
+ Rewrite (N, Make_If (N));
+ return Skip;
+
+ -- Replace all references to the protected object by a reference
+ -- to the new copy.
+
+ elsif Nkind (N) = N_Identifier
+ and then Present (Entity (N))
+ and then Entity (N) = Obj_Id
+ then
+ Rewrite (N, Make_Identifier (Loc, Chars (Copy_Id)));
+ return Skip;
+ end if;
+
+ -- We mark the node as unanalyzed in order to reanalyze it inside
+ -- the unprotected subprogram body.
+
+ Set_Analyzed (N, False);
+
+ return OK;
+ end Check_Node;
+
+ -- Start of processing for Process_Stmts
+
+ begin
+ -- Process_Nodes for each statement in Stmts
+
+ Stmt := First (Stmts);
+ while Present (Stmt) loop
+ Process_Nodes (Stmt);
+ Next (Stmt);
+ end loop;
+ end Process_Stmts;
+
+ -- Start of processing for Build_Lock_Free_Unprotected_Subprogram_Body
+
+ begin
+ New_Stmts := New_Copy_List (Statements (Handled_Statement_Sequence (N)));
+
+ -- Do the transformation only if the subprogram accesses a protected
+ -- component.
+
+ if not Present (Obj_Id) then
+ goto Continue;
+ end if;
+
+ Copy_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_External_Name (Chars (Obj_Id), Suffix => "_copy"));
+
+ Obj_Typ := Etype (Obj_Id);
+ Typ_Size := UI_To_Int (Esize (Base_Type (Obj_Typ)));
+
+ Process_Stmts (New_Stmts);
+
+ -- Procedure case
+
+ if Is_Procedure then
+ case Typ_Size is
+ when 8 =>
+ At_Comp_Id := RTE (RE_Atomic_Compare_Exchange_8);
+ At_Load_Id := RTE (RE_Atomic_Load_8);
+ Unsigned_Id := RTE (RE_Uint8);
+
+ when 16 =>
+ At_Comp_Id := RTE (RE_Atomic_Compare_Exchange_16);
+ At_Load_Id := RTE (RE_Atomic_Load_16);
+ Unsigned_Id := RTE (RE_Uint16);
+
+ when 32 =>
+ At_Comp_Id := RTE (RE_Atomic_Compare_Exchange_32);
+ At_Load_Id := RTE (RE_Atomic_Load_32);
+ Unsigned_Id := RTE (RE_Uint32);
+
+ when 64 =>
+ At_Comp_Id := RTE (RE_Atomic_Compare_Exchange_64);
+ At_Load_Id := RTE (RE_Atomic_Load_64);
+ Unsigned_Id := RTE (RE_Uint64);
+ when others => null;
+ end case;
+
+ -- Generate (e.g. for Typ_Size = 32):
+
+ -- begin
+ -- loop
+ -- declare
+ -- Obj_Old : constant Obj_Typ :=
+ -- Obj_Typ!
+ -- (System.Atomic_Primitives.Atomic_Load_32
+ -- (Obj'Address));
+ -- Obj_Copy : Obj_Typ := Obj_Old;
+ -- begin
+ -- < New_Stmts >
+ -- exit when
+ -- System.Atomic_Primitives.Atomic_Compare_Exchange_32
+ -- (Obj'Address,
+ -- Interfaces.Unsigned_32! (Obj_Old),
+ -- Interfaces.Unsigned_32! (Obj_Copy));
+ -- end;
+ -- end loop;
+ -- end;
+
+ -- Step 1: Define a copy and save the old value of the protected
+ -- object. The copy replaces all the references to the object present
+ -- in the body of the procedure.
+
+ -- Generate:
+
+ -- Obj_Old : constant Obj_Typ :=
+ -- Obj_Typ!
+ -- (System.Atomic_Primitives.Atomic_Load_32
+ -- (Obj'Address));
+ -- Obj_Copy : Obj_Typ := Obj_Old;
+
+ Old_Id := Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Obj_Id), Suffix => "_old"));
+
+ New_Decls := New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Old_Id,
+ Constant_Present => True,
+ Object_Definition => New_Reference_To (Obj_Typ, Loc),
+ Expression => Unchecked_Convert_To (Obj_Typ,
+ Make_Function_Call (Loc,
+ Name => New_Reference_To (At_Load_Id, Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Obj_Id, Loc),
+ Attribute_Name => Name_Address))))),
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Copy_Id,
+ Object_Definition => New_Reference_To (Obj_Typ, Loc),
+ Expression => New_Reference_To (Old_Id, Loc)));
+
+ -- Step 2: Create an exit statement of the loop statement generated
+ -- in step 3.
+
+ -- Generate (for Typ_Size = 32):
+
+ -- exit when System.Atomic_Primitives.Atomic_Compare_Exchange_32
+ -- (Obj'Address,
+ -- Interfaces.Unsigned_32! (Obj_Old),
+ -- Interfaces.Unsigned_32! (Obj_Copy));
+
+ Exit_Stmt :=
+ Make_Exit_Statement (Loc,
+ Condition =>
+ Make_Function_Call (Loc,
+ Name => New_Reference_To (At_Comp_Id, Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Obj_Id, Loc),
+ Attribute_Name => Name_Address),
+ Unchecked_Convert_To (Unsigned_Id,
+ New_Reference_To (Old_Id, Loc)),
+ Unchecked_Convert_To (Unsigned_Id,
+ New_Reference_To (Copy_Id, Loc)))));
+
+ -- Check the last statement is a return statement
+
+ if Nkind (Last (New_Stmts)) = N_Simple_Return_Statement then
+ Rewrite (Last (New_Stmts), Exit_Stmt);
+ else
+ Append_To (New_Stmts, Exit_Stmt);
+ end if;
+
+ -- Step 3: Create the loop statement which encloses a block
+ -- declaration that contains all the statements of the original
+ -- procedure body.
+
+ -- Generate:
+
+ -- loop
+ -- declare
+ -- < New_Decls >
+ -- begin
+ -- < New_Stmts >
+ -- end;
+ -- end loop;
+
+ New_Stmts := New_List (
+ Make_Loop_Statement (Loc,
+ Statements => New_List (
+ Make_Block_Statement (Loc,
+ Declarations => New_Decls,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_Stmts))),
+ End_Label => Empty));
+
+ -- Append the label to the statements of the loop when needed
+
+ if Present (Label) then
+ Append_To (Statements (First (New_Stmts)), Label);
+ end if;
+
+ -- Function case
+
+ else
+ case Typ_Size is
+ when 8 =>
+ At_Load_Id := RTE (RE_Atomic_Load_8);
+ when 16 =>
+ At_Load_Id := RTE (RE_Atomic_Load_16);
+ when 32 =>
+ At_Load_Id := RTE (RE_Atomic_Load_32);
+ when 64 =>
+ At_Load_Id := RTE (RE_Atomic_Load_64);
+ when others => null;
+ end case;
+
+ -- Define a copy of the protected object which replaces all the
+ -- references to the object present in the body of the function.
+
+ -- Generate:
+
+ -- Obj_Copy : constant Obj_Typ :=
+ -- Obj_Typ!
+ -- (System.Atomic_Primitives.Atomic_Load_32
+ -- (Obj'Address));
+
+ Append_To (Decls,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Copy_Id,
+ Constant_Present => True,
+ Object_Definition => New_Reference_To (Obj_Typ, Loc),
+ Expression => Unchecked_Convert_To (Obj_Typ,
+ Make_Function_Call (Loc,
+ Name => New_Reference_To (At_Load_Id, Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Obj_Id, Loc),
+ Attribute_Name => Name_Address))))));
+ end if;
+
+ << Continue >>
+
+ -- Add renamings for the Protection object, discriminals, privals and
+ -- the entry index constant for use by debugger.
+
+ Debug_Private_Data_Declarations (Decls);
+
+ -- Make an unprotected version of the subprogram for use within the same
+ -- object, with new name and extra parameter representing the object.
+
+ New_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Build_Protected_Sub_Specification (N, Pid, Unprotected_Mode),
+ Declarations => Decls,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_Stmts));
+ return New_Body;
+ end Build_Lock_Free_Unprotected_Subprogram_Body;
+
-------------------------
-- Build_Master_Entity --
-------------------------
@@ -3442,102 +4276,6 @@ package body Exp_Ch9 is
Exc_Safe : Boolean;
Lock_Kind : RE_Id;
- function Is_Exception_Safe (Subprogram : Node_Id) return Boolean;
- -- Tell whether a given subprogram cannot raise an exception
-
- -----------------------
- -- Is_Exception_Safe --
- -----------------------
-
- function Is_Exception_Safe (Subprogram : Node_Id) return Boolean is
-
- function Has_Side_Effect (N : Node_Id) return Boolean;
- -- Return True whenever encountering a subprogram call or raise
- -- statement of any kind in the sequence of statements
-
- ---------------------
- -- Has_Side_Effect --
- ---------------------
-
- -- What is this doing buried two levels down in exp_ch9. It seems
- -- like a generally useful function, and indeed there may be code
- -- duplication going on here ???
-
- function Has_Side_Effect (N : Node_Id) return Boolean is
- Stmt : Node_Id;
- Expr : Node_Id;
-
- function Is_Call_Or_Raise (N : Node_Id) return Boolean;
- -- Indicate whether N is a subprogram call or a raise statement
-
- ----------------------
- -- Is_Call_Or_Raise --
- ----------------------
-
- function Is_Call_Or_Raise (N : Node_Id) return Boolean is
- begin
- return Nkind_In (N, N_Procedure_Call_Statement,
- N_Function_Call,
- N_Raise_Statement,
- N_Raise_Constraint_Error,
- N_Raise_Program_Error,
- N_Raise_Storage_Error);
- end Is_Call_Or_Raise;
-
- -- Start of processing for Has_Side_Effect
-
- begin
- Stmt := N;
- while Present (Stmt) loop
- if Is_Call_Or_Raise (Stmt) then
- return True;
- end if;
-
- -- An object declaration can also contain a function call
- -- or a raise statement
-
- if Nkind (Stmt) = N_Object_Declaration then
- Expr := Expression (Stmt);
-
- if Present (Expr) and then Is_Call_Or_Raise (Expr) then
- return True;
- end if;
- end if;
-
- Next (Stmt);
- end loop;
-
- return False;
- end Has_Side_Effect;
-
- -- Start of processing for Is_Exception_Safe
-
- begin
- -- If the checks handled by the back end are not disabled, we cannot
- -- ensure that no exception will be raised.
-
- if not Access_Checks_Suppressed (Empty)
- or else not Discriminant_Checks_Suppressed (Empty)
- or else not Range_Checks_Suppressed (Empty)
- or else not Index_Checks_Suppressed (Empty)
- or else Opt.Stack_Checking_Enabled
- then
- return False;
- end if;
-
- if Has_Side_Effect (First (Declarations (Subprogram)))
- or else
- Has_Side_Effect (
- First (Statements (Handled_Statement_Sequence (Subprogram))))
- then
- return False;
- else
- return True;
- end if;
- end Is_Exception_Safe;
-
- -- Start of processing for Build_Protected_Subprogram_Body
-
begin
Op_Spec := Specification (N);
Exc_Safe := Is_Exception_Safe (N);
@@ -4698,6 +5436,21 @@ package body Exp_Ch9 is
end loop;
end Collect_Entry_Families;
+ -------------
+ -- Comp_Of --
+ -------------
+
+ function Comp_Of (Sub_Body : Node_Id) return Entity_Id is
+ begin
+ for Sub_Id in 1 .. LF_Sub_Table.Last loop
+ if Sub_Body = LF_Sub_Table.Table (Sub_Id).Sub_Body then
+ return LF_Sub_Table.Table (Sub_Id).Comp_Id;
+ end if;
+ end loop;
+
+ return Empty;
+ end Comp_Of;
+
-----------------------
-- Concurrent_Object --
-----------------------
@@ -7715,6 +8468,9 @@ package body Exp_Ch9 is
Loc : constant Source_Ptr := Sloc (N);
Pid : constant Entity_Id := Corresponding_Spec (N);
+ Lock_Free_On : constant Boolean := Allow_Lock_Free_Implementation (N);
+ -- This flag indicates whether the lock free implementation is active
+
Current_Node : Node_Id;
Disp_Op_Body : Node_Id;
New_Op_Body : Node_Id;
@@ -7843,8 +8599,14 @@ package body Exp_Ch9 is
if not Is_Eliminated (Defining_Entity (Op_Body))
and then not Is_Eliminated (Corresponding_Spec (Op_Body))
then
- New_Op_Body :=
- Build_Unprotected_Subprogram_Body (Op_Body, Pid);
+ if Lock_Free_On then
+ New_Op_Body :=
+ Build_Lock_Free_Unprotected_Subprogram_Body
+ (Op_Body, Pid);
+ else
+ New_Op_Body :=
+ Build_Unprotected_Subprogram_Body (Op_Body, Pid);
+ end if;
Insert_After (Current_Node, New_Op_Body);
Current_Node := New_Op_Body;
@@ -7854,6 +8616,7 @@ package body Exp_Ch9 is
-- appear that this is needed only if this is a visible
-- operation of the type, or if it is an interrupt handler,
-- and this was the strategy used previously in GNAT.
+
-- However, the operation may be exported through a 'Access
-- to an external caller. This is the common idiom in code
-- that uses the Ada 2005 Timing_Events package. As a result
@@ -7863,9 +8626,15 @@ package body Exp_Ch9 is
-- declaration in the protected body itself.
if Present (Corresponding_Spec (Op_Body)) then
- New_Op_Body :=
- Build_Protected_Subprogram_Body (
- Op_Body, Pid, Specification (New_Op_Body));
+ if Lock_Free_On then
+ New_Op_Body :=
+ Build_Lock_Free_Protected_Subprogram_Body
+ (Op_Body, Pid, Specification (New_Op_Body));
+ else
+ New_Op_Body :=
+ Build_Protected_Subprogram_Body
+ (Op_Body, Pid, Specification (New_Op_Body));
+ end if;
Insert_After (Current_Node, New_Op_Body);
Analyze (New_Op_Body);
@@ -12688,6 +13457,97 @@ package body Exp_Ch9 is
end if;
end Install_Private_Data_Declarations;
+ -----------------------
+ -- Is_Exception_Safe --
+ -----------------------
+
+ function Is_Exception_Safe (Subprogram : Node_Id) return Boolean is
+
+ function Has_Side_Effect (N : Node_Id) return Boolean;
+ -- Return True whenever encountering a subprogram call or raise
+ -- statement of any kind in the sequence of statements
+
+ ---------------------
+ -- Has_Side_Effect --
+ ---------------------
+
+ -- What is this doing buried two levels down in exp_ch9. It seems like a
+ -- generally useful function, and indeed there may be code duplication
+ -- going on here ???
+
+ function Has_Side_Effect (N : Node_Id) return Boolean is
+ Stmt : Node_Id;
+ Expr : Node_Id;
+
+ function Is_Call_Or_Raise (N : Node_Id) return Boolean;
+ -- Indicate whether N is a subprogram call or a raise statement
+
+ ----------------------
+ -- Is_Call_Or_Raise --
+ ----------------------
+
+ function Is_Call_Or_Raise (N : Node_Id) return Boolean is
+ begin
+ return Nkind_In (N, N_Procedure_Call_Statement,
+ N_Function_Call,
+ N_Raise_Statement,
+ N_Raise_Constraint_Error,
+ N_Raise_Program_Error,
+ N_Raise_Storage_Error);
+ end Is_Call_Or_Raise;
+
+ -- Start of processing for Has_Side_Effect
+
+ begin
+ Stmt := N;
+ while Present (Stmt) loop
+ if Is_Call_Or_Raise (Stmt) then
+ return True;
+ end if;
+
+ -- An object declaration can also contain a function call or a
+ -- raise statement.
+
+ if Nkind (Stmt) = N_Object_Declaration then
+ Expr := Expression (Stmt);
+
+ if Present (Expr) and then Is_Call_Or_Raise (Expr) then
+ return True;
+ end if;
+ end if;
+
+ Next (Stmt);
+ end loop;
+
+ return False;
+ end Has_Side_Effect;
+
+ -- Start of processing for Is_Exception_Safe
+
+ begin
+ -- If the checks handled by the back end are not disabled, we cannot
+ -- ensure that no exception will be raised.
+
+ if not Access_Checks_Suppressed (Empty)
+ or else not Discriminant_Checks_Suppressed (Empty)
+ or else not Range_Checks_Suppressed (Empty)
+ or else not Index_Checks_Suppressed (Empty)
+ or else Opt.Stack_Checking_Enabled
+ then
+ return False;
+ end if;
+
+ if Has_Side_Effect (First (Declarations (Subprogram)))
+ or else
+ Has_Side_Effect
+ (First (Statements (Handled_Statement_Sequence (Subprogram))))
+ then
+ return False;
+ else
+ return True;
+ end if;
+ end Is_Exception_Safe;
+
---------------------------------
-- Is_Potentially_Large_Family --
---------------------------------
@@ -12702,11 +13562,12 @@ package body Exp_Ch9 is
return Scope (Base_Index) = Standard_Standard
and then Base_Index = Base_Type (Standard_Integer)
and then Has_Discriminants (Conctyp)
- and then Present
- (Discriminant_Default_Value (First_Discriminant (Conctyp)))
+ and then
+ Present (Discriminant_Default_Value (First_Discriminant (Conctyp)))
and then
(Denotes_Discriminant (Lo, True)
- or else Denotes_Discriminant (Hi, True));
+ or else
+ Denotes_Discriminant (Hi, True));
end Is_Potentially_Large_Family;
-------------------------------------
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index b43bd16..ae5470f 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -3948,8 +3948,7 @@ package body Exp_Util is
(Obj_Id : Entity_Id) return Boolean
is
function Is_Controlled_Function_Call (N : Node_Id) return Boolean;
- -- Determine whether a particular node denotes a controlled function
- -- call.
+ -- Determine if particular node denotes a controlled function call
function Is_Displace_Call (N : Node_Id) return Boolean;
-- Determine whether a particular node is a call to Ada.Tags.Displace.
@@ -4065,7 +4064,7 @@ package body Exp_Util is
and then Is_Displace_Call (Renamed_Object (Obj_Id))
and then
(Is_Controlled_Function_Call (Expression (Orig_Decl))
- or else Is_Source_Object (Expression (Orig_Decl)));
+ or else Is_Source_Object (Expression (Orig_Decl)));
end Is_Displacement_Of_Object_Or_Function_Result;
------------------------------
diff --git a/gcc/ada/g-sse.ads b/gcc/ada/g-sse.ads
index 706516b9..60d3577 100644
--- a/gcc/ada/g-sse.ads
+++ b/gcc/ada/g-sse.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2009, Free Software Foundation, Inc. --
+-- Copyright (C) 2009-2012, 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- --
@@ -40,6 +40,8 @@
-- GNU/Linux x86 and x86_64
-- Windows XP/Vista x86 and x86_64
+-- Solaris x86
+-- Darwin x86_64
-- This unit exposes vector _component_ types together with general comments
-- on the binding contents.
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 9991405..5c4acda 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -1083,6 +1083,8 @@ ifeq ($(strip $(filter-out %86 %x86_64 solaris2%,$(arch) $(osys))),)
TOOLS_TARGET_PAIRS=mlib-tgt-specific.adb<mlib-tgt-specific-solaris.adb
+ EXTRA_GNATRTL_NONTASKING_OBJS=g-sse.o g-ssvety.o
+
EH_MECHANISM=-gcc
THREADSLIB = -lposix4 -lthread
MISCLIB = -lposix4 -lnsl -lsocket
@@ -1175,6 +1177,8 @@ ifeq ($(strip $(filter-out %86 kfreebsd%,$(arch) $(osys))),)
mlib-tgt-specific.adb<mlib-tgt-specific-linux.adb \
indepsw.adb<indepsw-gnu.adb
+ EXTRA_GNATRTL_NONTASKING_OBJS=g-sse.o g-ssvety.o
+
EH_MECHANISM=-gcc
THREADSLIB = -lpthread
GNATLIB_SHARED = gnatlib-shared-dual
@@ -1231,6 +1235,8 @@ ifeq ($(strip $(filter-out %86 freebsd%,$(arch) $(osys))),)
mlib-tgt-specific.adb<mlib-tgt-specific-linux.adb
GNATLIB_SHARED = gnatlib-shared-dual
+ EXTRA_GNATRTL_NONTASKING_OBJS=g-sse.o g-ssvety.o
+
EH_MECHANISM=-gcc
THREADSLIB= -lpthread
GMEM_LIB = gmemlib
@@ -1259,6 +1265,8 @@ ifeq ($(strip $(filter-out %86_64 freebsd%,$(arch) $(osys))),)
mlib-tgt-specific.adb<mlib-tgt-specific-linux.adb
GNATLIB_SHARED = gnatlib-shared-dual
+ EXTRA_GNATRTL_NONTASKING_OBJS=g-sse.o g-ssvety.o
+
EH_MECHANISM=-gcc
THREADSLIB= -lpthread
GMEM_LIB = gmemlib
@@ -2160,6 +2168,8 @@ ifeq ($(strip $(filter-out darwin%,$(osys))),)
$(X86_TARGET_PAIRS) \
system.ads<system-darwin-x86.ads
endif
+
+ EXTRA_GNATRTL_NONTASKING_OBJS=g-sse.o g-ssvety.o
endif
ifeq ($(strip $(filter-out %x86_64,$(arch))),)
@@ -2178,6 +2188,8 @@ ifeq ($(strip $(filter-out darwin%,$(osys))),)
$(X86_64_TARGET_PAIRS) \
system.ads<system-darwin-x86_64.ads
endif
+
+ EXTRA_GNATRTL_NONTASKING_OBJS=g-sse.o g-ssvety.o
endif
ifeq ($(strip $(filter-out powerpc%,$(arch))),)
diff --git a/gcc/ada/osint.adb b/gcc/ada/osint.adb
index 8da01c2..9a2e7ee 100644
--- a/gcc/ada/osint.adb
+++ b/gcc/ada/osint.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2012, 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- --
@@ -444,6 +444,15 @@ package body Osint is
-- Start of processing for Add_Default_Search_Dirs
begin
+ -- If there was a -gnateO switch, add all object directories from the
+ -- file given in argument to the library search list.
+
+ if Object_Path_File_Name /= null then
+ Path_File_Name := String_Access (Object_Path_File_Name);
+ pragma Assert (Path_File_Name'Length > 0);
+ Get_Dirs_From_File (Additional_Source_Dir => False);
+ end if;
+
-- After the locations specified on the command line, the next places
-- to look for files are the directories specified by the appropriate
-- environment variable. Get this value, extract the directory names
diff --git a/gcc/ada/osint.ads b/gcc/ada/osint.ads
index a4fc334..48663f5 100644
--- a/gcc/ada/osint.ads
+++ b/gcc/ada/osint.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2012, 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- --
@@ -324,7 +324,8 @@ package Osint is
procedure Add_Default_Search_Dirs;
-- This routine adds the default search dirs indicated by the environment
- -- variables and sdefault package.
+ -- variables and sdefault package, as well as the library search dirs set
+ -- by option -gnateO for GNAT2WHY.
procedure Add_Lib_Search_Dir (Dir : String);
-- Add Dir at the end of the library file search path
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index 88e61dc..e02f575 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -211,6 +211,7 @@ package Rtsfind is
System_Arith_64,
System_AST_Handling,
System_Assertions,
+ System_Atomic_Primitives,
System_Aux_DEC,
System_Bit_Ops,
System_Boolean_Array_Operations,
@@ -730,6 +731,19 @@ package Rtsfind is
RE_Assert_Failure, -- System.Assertions
RE_Raise_Assert_Failure, -- System.Assertions
+ RE_Atomic_Compare_Exchange_8, -- System.Atomic_Primitives
+ RE_Atomic_Compare_Exchange_16, -- System.Atomic_Primitives
+ RE_Atomic_Compare_Exchange_32, -- System.Atomic_Primitives
+ RE_Atomic_Compare_Exchange_64, -- System.Atomic_Primitives
+ RE_Atomic_Load_8, -- System.Atomic_Primitives
+ RE_Atomic_Load_16, -- System.Atomic_Primitives
+ RE_Atomic_Load_32, -- System.Atomic_Primitives
+ RE_Atomic_Load_64, -- System.Atomic_Primitives
+ RE_Uint8, -- System.Atomic_Primitives
+ RE_Uint16, -- System.Atomic_Primitives
+ RE_Uint32, -- System.Atomic_Primitives
+ RE_Uint64, -- System.Atomic_Primitives
+
RE_AST_Handler, -- System.Aux_DEC
RE_Import_Value, -- System.Aux_DEC
RE_No_AST_Handler, -- System.Aux_DEC
@@ -1938,6 +1952,19 @@ package Rtsfind is
RE_Assert_Failure => System_Assertions,
RE_Raise_Assert_Failure => System_Assertions,
+ RE_Atomic_Compare_Exchange_8 => System_Atomic_Primitives,
+ RE_Atomic_Compare_Exchange_16 => System_Atomic_Primitives,
+ RE_Atomic_Compare_Exchange_32 => System_Atomic_Primitives,
+ RE_Atomic_Compare_Exchange_64 => System_Atomic_Primitives,
+ RE_Atomic_Load_8 => System_Atomic_Primitives,
+ RE_Atomic_Load_16 => System_Atomic_Primitives,
+ RE_Atomic_Load_32 => System_Atomic_Primitives,
+ RE_Atomic_Load_64 => System_Atomic_Primitives,
+ RE_Uint8 => System_Atomic_Primitives,
+ RE_Uint16 => System_Atomic_Primitives,
+ RE_Uint32 => System_Atomic_Primitives,
+ RE_Uint64 => System_Atomic_Primitives,
+
RE_AST_Handler => System_Aux_DEC,
RE_Import_Value => System_Aux_DEC,
RE_No_AST_Handler => System_Aux_DEC,
diff --git a/gcc/ada/s-atopri.ads b/gcc/ada/s-atopri.ads
new file mode 100644
index 0000000..6f39cf0
--- /dev/null
+++ b/gcc/ada/s-atopri.ads
@@ -0,0 +1,120 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . A T O M I C _ P R I M I T I V E S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2012, 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.Atomic_Primitives is
+ pragma Preelaborate;
+
+ type uint8 is mod 2**8
+ with Size => 8;
+
+ type uint16 is mod 2**16
+ with Size => 16;
+
+ type uint32 is mod 2**32
+ with Size => 32;
+
+ type uint64 is mod 2**64
+ with Size => 64;
+
+ Relaxed : constant := 0;
+ Consume : constant := 1;
+ Acquire : constant := 2;
+ Release : constant := 3;
+ Acq_Rel : constant := 4;
+ Seq_Cst : constant := 5;
+ Last : constant := 6;
+
+ subtype Mem_Model is Integer range Relaxed .. Last;
+
+ function Atomic_Compare_Exchange_8
+ (X : Address;
+ X_Old : uint8;
+ X_Copy : uint8) return Boolean;
+ pragma Import (Intrinsic,
+ Atomic_Compare_Exchange_8,
+ "__sync_bool_compare_and_swap_1");
+
+ -- ??? Should use __atomic_compare_exchange_1 (doesn't work yet):
+ -- function Atomic_Compare_Exchange_8
+ -- (X : Address;
+ -- X_Old : Address;
+ -- X_Copy : uint8;
+ -- Success_Model : Mem_Model := Seq_Cst;
+ -- Failure_Model : Mem_Model := Seq_Cst) return Boolean;
+ -- pragma Import (Intrinsic,
+ -- Atomic_Compare_Exchange_8,
+ -- "__atomic_compare_exchange_1");
+
+ function Atomic_Compare_Exchange_16
+ (X : Address;
+ X_Old : uint16;
+ X_Copy : uint16) return Boolean;
+ pragma Import (Intrinsic,
+ Atomic_Compare_Exchange_16,
+ "__sync_bool_compare_and_swap_2");
+
+ function Atomic_Compare_Exchange_32
+ (X : Address;
+ X_Old : uint32;
+ X_Copy : uint32) return Boolean;
+ pragma Import (Intrinsic,
+ Atomic_Compare_Exchange_32,
+ "__sync_bool_compare_and_swap_4");
+
+ function Atomic_Compare_Exchange_64
+ (X : Address;
+ X_Old : uint64;
+ X_Copy : uint64) return Boolean;
+ pragma Import (Intrinsic,
+ Atomic_Compare_Exchange_64,
+ "__sync_bool_compare_and_swap_8");
+
+ function Atomic_Load_8
+ (X : Address;
+ Model : Mem_Model := Seq_Cst) return uint8;
+ pragma Import (Intrinsic, Atomic_Load_8, "__atomic_load_1");
+
+ function Atomic_Load_16
+ (X : Address;
+ Model : Mem_Model := Seq_Cst) return uint16;
+ pragma Import (Intrinsic, Atomic_Load_16, "__atomic_load_2");
+
+ function Atomic_Load_32
+ (X : Address;
+ Model : Mem_Model := Seq_Cst) return uint32;
+ pragma Import (Intrinsic, Atomic_Load_32, "__atomic_load_4");
+
+ function Atomic_Load_64
+ (X : Address;
+ Model : Mem_Model := Seq_Cst) return uint64;
+ pragma Import (Intrinsic, Atomic_Load_64, "__atomic_load_8");
+
+end System.Atomic_Primitives;
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 6b45c07..6feb84c 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -1666,6 +1666,9 @@ package body Sem_Ch5 is
if not Is_Entity_Name (Iter_Name)
and then (Nkind (Parent (N)) /= N_Quantified_Expression
+
+ -- The following two tests need comments ???
+
or else Operating_Mode = Check_Semantics
or else Alfa_Mode)
then
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index ab08e77..ef5f8b4 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -2624,10 +2624,10 @@ package body Sem_Res is
-- an error. We can't do this earlier, because it would cause legal
-- cases to get errors (when some other type has an abstract "+").
- if Ada_Version >= Ada_2005 and then
- Nkind (N) in N_Op and then
- Is_Overloaded (N) and then
- Is_Universal_Numeric_Type (Etype (Entity (N)))
+ if Ada_Version >= Ada_2005
+ and then Nkind (N) in N_Op
+ and then Is_Overloaded (N)
+ and then Is_Universal_Numeric_Type (Etype (Entity (N)))
then
Get_First_Interp (N, I, It);
while Present (It.Typ) loop
@@ -6118,15 +6118,36 @@ package body Sem_Res is
Condition : constant Node_Id := First (Expressions (N));
Then_Expr : constant Node_Id := Next (Condition);
Else_Expr : Node_Id := Next (Then_Expr);
+ Else_Typ : Entity_Id;
+ Then_Typ : Entity_Id;
begin
Resolve (Condition, Any_Boolean);
Resolve (Then_Expr, Typ);
+ Then_Typ := Etype (Then_Expr);
+
+ -- When the "then" and "else" expressions are of a scalar type, insert
+ -- a conversion to ensure the generation of a constraint check.
+
+ if Is_Scalar_Type (Then_Typ)
+ and then Then_Typ /= Typ
+ then
+ Rewrite (Then_Expr, Convert_To (Typ, Then_Expr));
+ Analyze_And_Resolve (Then_Expr, Typ);
+ end if;
-- If ELSE expression present, just resolve using the determined type
if Present (Else_Expr) then
Resolve (Else_Expr, Typ);
+ Else_Typ := Etype (Else_Expr);
+
+ if Is_Scalar_Type (Else_Typ)
+ and then Else_Typ /= Typ
+ then
+ Rewrite (Else_Expr, Convert_To (Typ, Else_Expr));
+ Analyze_And_Resolve (Else_Expr, Typ);
+ end if;
-- If no ELSE expression is present, root type must be Standard.Boolean
-- and we provide a Standard.True result converted to the appropriate
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index e7958058..b8e4d81 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -740,15 +740,16 @@ package body Sem_Util is
N : Node_Id) return Entity_Id
is
Loc : constant Source_Ptr := Sloc (N);
- Bas : Entity_Id;
- -- The base type that is to be constrained by the defaults.
-
Disc : Entity_Id;
+ Bas : Entity_Id;
+ -- The base type that is to be constrained by the defaults
+
begin
if not Has_Discriminants (T) or else Is_Constrained (T) then
return T;
end if;
+
Bas := Base_Type (T);
-- If T is non-private but its base type is private, this is
@@ -757,9 +758,7 @@ package body Sem_Util is
-- proper discriminants are to be found in the full view of
-- the base.
- if Is_Private_Type (Bas)
- and then Present (Full_View (Bas))
- then
+ if Is_Private_Type (Bas) and then Present (Full_View (Bas)) then
Bas := Full_View (Bas);
end if;
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index 0972d9c..e9f1c8e 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -1252,7 +1252,7 @@ package Sinfo is
-- to the node for the spec of the instance, inserted as part of the
-- semantic processing for instantiations in Sem_Ch12.
- -- Is_Accessibility_Actual (Flag12-Sem)
+ -- Is_Accessibility_Actual (Flag13-Sem)
-- Present in N_Parameter_Association nodes. True if the parameter is
-- an extra actual that carries the accessibility level of the actual
-- for an access parameter, in a function that dispatches on result and