------------------------------------------------------------------------------ -- -- -- GNAT COMPILER COMPONENTS -- -- -- -- E X P_ D I S T -- -- -- -- B o d y -- -- -- -- Copyright (C) 1992-2018, 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. 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 COPYING3. If not, go to -- -- http://www.gnu.org/licenses for a complete copy of the license. -- -- -- -- GNAT was originally developed by the GNAT team at New York University. -- -- Extensive contributions were provided by Ada Core Technologies Inc. -- -- -- ------------------------------------------------------------------------------ with Atree; use Atree; with Einfo; use Einfo; with Elists; use Elists; with Exp_Atag; use Exp_Atag; with Exp_Strm; use Exp_Strm; with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; with Lib; use Lib; with Nlists; use Nlists; with Nmake; use Nmake; with Opt; use Opt; with Rtsfind; use Rtsfind; with Sem; use Sem; with Sem_Aux; use Sem_Aux; with Sem_Cat; use Sem_Cat; with Sem_Ch3; use Sem_Ch3; with Sem_Ch8; use Sem_Ch8; with Sem_Ch12; use Sem_Ch12; with Sem_Dist; use Sem_Dist; with Sem_Eval; use Sem_Eval; with Sem_Util; use Sem_Util; with Sinfo; use Sinfo; with Stand; use Stand; with Stringt; use Stringt; with Tbuild; use Tbuild; with Ttypes; use Ttypes; with Uintp; use Uintp; with GNAT.HTable; use GNAT.HTable; package body Exp_Dist is -- The following model has been used to implement distributed objects: -- given a designated type D and a RACW type R, then a record of the form: -- type Stub is tagged record -- [...declaration similar to s-parint.ads RACW_Stub_Type...] -- end record; -- is built. This type has two properties: -- 1) Since it has the same structure as RACW_Stub_Type, it can -- be converted to and from this type to make it suitable for -- System.Partition_Interface.Get_Unique_Remote_Pointer in order -- to avoid memory leaks when the same remote object arrives on the -- same partition through several paths; -- 2) It also has the same dispatching table as the designated type D, -- and thus can be used as an object designated by a value of type -- R on any partition other than the one on which the object has -- been created, since only dispatching calls will be performed and -- the fields themselves will not be used. We call Derive_Subprograms -- to fake half a derivation to ensure that the subprograms do have -- the same dispatching table. First_RCI_Subprogram_Id : constant := 2; -- RCI subprograms are numbered starting at 2. The RCI receiver for -- an RCI package can thus identify calls received through remote -- access-to-subprogram dereferences by the fact that they have a -- (primitive) subprogram id of 0, and 1 is used for the internal RAS -- information lookup operation. (This is for the Garlic code generation, -- where subprograms are identified by numbers; in the PolyORB version, -- they are identified by name, with a numeric suffix for homonyms.) type Hash_Index is range 0 .. 50; ----------------------- -- Local subprograms -- ----------------------- function Hash (F : Entity_Id) return Hash_Index; -- DSA expansion associates stubs to distributed object types using a hash -- table on entity ids. function Hash (F : Name_Id) return Hash_Index; -- The generation of subprogram identifiers requires an overload counter -- to be associated with each remote subprogram name. These counters are -- maintained in a hash table on name ids. type Subprogram_Identifiers is record Str_Identifier : String_Id; Int_Identifier : Int; end record; package Subprogram_Identifier_Table is new Simple_HTable (Header_Num => Hash_Index, Element => Subprogram_Identifiers, No_Element => (No_String, 0), Key => Entity_Id, Hash => Hash, Equal => "="); -- Mapping between a remote subprogram and the corresponding subprogram -- identifiers. package Overload_Counter_Table is new Simple_HTable (Header_Num => Hash_Index, Element => Int, No_Element => 0, Key => Name_Id, Hash => Hash, Equal => "="); -- Mapping between a subprogram name and an integer that counts the number -- of defining subprogram names with that Name_Id encountered so far in a -- given context (an interface). function Get_Subprogram_Ids (Def : Entity_Id) return Subprogram_Identifiers; function Get_Subprogram_Id (Def : Entity_Id) return String_Id; function Get_Subprogram_Id (Def : Entity_Id) return Int; -- Given a subprogram defined in a RCI package, get its distribution -- subprogram identifiers (the distribution identifiers are a unique -- subprogram number, and the non-qualified subprogram name, in the -- casing used for the subprogram declaration; if the name is overloaded, -- a double underscore and a serial number are appended. -- -- The integer identifier is used to perform remote calls with GARLIC; -- the string identifier is used in the case of PolyORB. -- -- Although the PolyORB DSA receiving stubs will make a caseless comparison -- when receiving a call, the calling stubs will create requests with the -- exact casing of the defining unit name of the called subprogram, so as -- to allow calls to subprograms on distributed nodes that do distinguish -- between casings. -- -- NOTE: Another design would be to allow a representation clause on -- subprogram specs: for Subp'Distribution_Identifier use "fooBar"; pragma Warnings (Off, Get_Subprogram_Id); -- One homonym only is unreferenced (specific to the GARLIC version) procedure Add_RAS_Dereference_TSS (N : Node_Id); -- Add a subprogram body for RAS Dereference TSS procedure Add_RAS_Proxy_And_Analyze (Decls : List_Id; Vis_Decl : Node_Id; All_Calls_Remote_E : Entity_Id; Proxy_Object_Addr : out Entity_Id); -- Add the proxy type required, on the receiving (server) side, to handle -- calls to the subprogram declared by Vis_Decl through a remote access -- to subprogram type. All_Calls_Remote_E must be Standard_True if a pragma -- All_Calls_Remote applies, Standard_False otherwise. The new proxy type -- is appended to Decls. Proxy_Object_Addr is a constant of type -- System.Address that designates an instance of the proxy object. function Build_Remote_Subprogram_Proxy_Type (Loc : Source_Ptr; ACR_Expression : Node_Id) return Node_Id; -- Build and return a tagged record type definition for an RCI subprogram -- proxy type. ACR_Expression is used as the initialization value for the -- All_Calls_Remote component. function Build_Get_Unique_RP_Call (Loc : Source_Ptr; Pointer : Entity_Id; Stub_Type : Entity_Id) return List_Id; -- Build a call to Get_Unique_Remote_Pointer (Pointer), followed by a -- tag fixup (Get_Unique_Remote_Pointer may have changed Pointer'Tag to -- RACW_Stub_Type'Tag, while the desired tag is that of Stub_Type). function Build_Stub_Tag (Loc : Source_Ptr; RACW_Type : Entity_Id) return Node_Id; -- Return an expression denoting the tag of the stub type associated with -- RACW_Type. function Build_Subprogram_Calling_Stubs (Vis_Decl : Node_Id; Subp_Id : Node_Id; Asynchronous : Boolean; Dynamically_Asynchronous : Boolean := False; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Locator : Entity_Id := Empty; New_Name : Name_Id := No_Name) return Node_Id; -- Build the calling stub for a given subprogram with the subprogram ID -- being Subp_Id. If Stub_Type is given, then the "addr" field of -- parameters of this type will be marshalled instead of the object itself. -- It will then be converted into Stub_Type before performing the real -- call. If Dynamically_Asynchronous is True, then it will be computed at -- run time whether the call is asynchronous or not. Otherwise, the value -- of the formal Asynchronous will be used. If Locator is not Empty, it -- will be used instead of RCI_Cache. If New_Name is given, then it will -- be used instead of the original name. function Build_RPC_Receiver_Specification (RPC_Receiver : Entity_Id; Request_Parameter : Entity_Id) return Node_Id; -- Make a subprogram specification for an RPC receiver, with the given -- defining unit name and formal parameter. function Build_Ordered_Parameters_List (Spec : Node_Id) return List_Id; -- Return an ordered parameter list: unconstrained parameters are put -- at the beginning of the list and constrained ones are put after. If -- there are no parameters, an empty list is returned. Special case: -- the controlling formal of the equivalent RACW operation for a RAS -- type is always left in first position. function Transmit_As_Unconstrained (Typ : Entity_Id) return Boolean; -- True when Typ is an unconstrained type, or a null-excluding access type. -- In either case, this means stubs cannot contain a default-initialized -- object declaration of such type. procedure Add_Calling_Stubs_To_Declarations (Pkg_Spec : Node_Id); -- Add calling stubs to the declarative part function Could_Be_Asynchronous (Spec : Node_Id) return Boolean; -- Return True if nothing prevents the program whose specification is -- given to be asynchronous (i.e. no [IN] OUT parameters). function Pack_Entity_Into_Stream_Access (Loc : Source_Ptr; Stream : Node_Id; Object : Entity_Id; Etyp : Entity_Id := Empty) return Node_Id; -- Pack Object (of type Etyp) into Stream. If Etyp is not given, -- then Etype (Object) will be used if present. If the type is -- constrained, then 'Write will be used to output the object, -- If the type is unconstrained, 'Output will be used. function Pack_Node_Into_Stream (Loc : Source_Ptr; Stream : Entity_Id; Object : Node_Id; Etyp : Entity_Id) return Node_Id; -- Similar to above, with an arbitrary node instead of an entity function Pack_Node_Into_Stream_Access (Loc : Source_Ptr; Stream : Node_Id; Object : Node_Id; Etyp : Entity_Id) return Node_Id; -- Similar to above, with Stream instead of Stream'Access function Make_Selected_Component (Loc : Source_Ptr; Prefix : Entity_Id; Selector_Name : Name_Id) return Node_Id; -- Return a selected_component whose prefix denotes the given entity, and -- with the given Selector_Name. function Scope_Of_Spec (Spec : Node_Id) return Entity_Id; -- Return the scope represented by a given spec procedure Set_Renaming_TSS (Typ : Entity_Id; Nam : Entity_Id; TSS_Nam : TSS_Name_Type); -- Create a renaming declaration of subprogram Nam, and register it as a -- TSS for Typ with name TSS_Nam. function Need_Extra_Constrained (Parameter : Node_Id) return Boolean; -- Return True if the current parameter needs an extra formal to reflect -- its constrained status. function Is_RACW_Controlling_Formal (Parameter : Node_Id; Stub_Type : Entity_Id) return Boolean; -- Return True if the current parameter is a controlling formal argument -- of type Stub_Type or access to Stub_Type. procedure Declare_Create_NVList (Loc : Source_Ptr; NVList : Entity_Id; Decls : List_Id; Stmts : List_Id); -- Append the declaration of NVList to Decls, and its -- initialization to Stmts. function Add_Parameter_To_NVList (Loc : Source_Ptr; NVList : Entity_Id; Parameter : Entity_Id; Constrained : Boolean; RACW_Ctrl : Boolean := False; Any : Entity_Id) return Node_Id; -- Return a call to Add_Item to add the Any corresponding to the designated -- formal Parameter (with the indicated Constrained status) to NVList. -- RACW_Ctrl must be set to True for controlling formals of distributed -- object primitive operations. -------------------- -- Stub_Structure -- -------------------- -- This record describes various tree fragments associated with the -- generation of RACW calling stubs. One such record exists for every -- distributed object type, i.e. each tagged type that is the designated -- type of one or more RACW type. type Stub_Structure is record Stub_Type : Entity_Id; -- Stub type: this type has the same primitive operations as the -- designated types, but the provided bodies for these operations -- a remote call to an actual target object potentially located on -- another partition; each value of the stub type encapsulates a -- reference to a remote object. Stub_Type_Access : Entity_Id; -- A local access type designating the stub type (this is not an RACW -- type). RPC_Receiver_Decl : Node_Id; -- Declaration for the RPC receiver entity associated with the -- designated type. As an exception, in the case of GARLIC, for an RACW -- that implements a RAS, no object RPC receiver is generated. Instead, -- RPC_Receiver_Decl is the declaration after which the RPC receiver -- would have been inserted. Body_Decls : List_Id; -- List of subprogram bodies to be included in generated code: bodies -- for the RACW's stream attributes, and for the primitive operations -- of the stub type. RACW_Type : Entity_Id; -- One of the RACW types designating this distributed object type -- (they are all interchangeable; we use any one of them in order to -- avoid having to create various anonymous access types). end record; Empty_Stub_Structure : constant Stub_Structure := (Empty, Empty, Empty, No_List, Empty); package Stubs_Table is new Simple_HTable (Header_Num => Hash_Index, Element => Stub_Structure, No_Element => Empty_Stub_Structure, Key => Entity_Id, Hash => Hash, Equal => "="); -- Mapping between a RACW designated type and its stub type package Asynchronous_Flags_Table is new Simple_HTable (Header_Num => Hash_Index, Element => Entity_Id, No_Element => Empty, Key => Entity_Id, Hash => Hash, Equal => "="); -- Mapping between a RACW type and a constant having the value True -- if the RACW is asynchronous and False otherwise. package RCI_Locator_Table is new Simple_HTable (Header_Num => Hash_Index, Element => Entity_Id, No_Element => Empty, Key => Entity_Id, Hash => Hash, Equal => "="); -- Mapping between a RCI package on which All_Calls_Remote applies and -- the generic instantiation of RCI_Locator for this package. package RCI_Calling_Stubs_Table is new Simple_HTable (Header_Num => Hash_Index, Element => Entity_Id, No_Element => Empty, Key => Entity_Id, Hash => Hash, Equal => "="); -- Mapping between a RCI subprogram and the corresponding calling stubs function Get_Stub_Elements (RACW_Type : Entity_Id) return Stub_Structure; -- Return the stub information associated with the given RACW type procedure Add_Stub_Type (Designated_Type : Entity_Id; RACW_Type : Entity_Id; Decls : List_Id; Stub_Type : out Entity_Id; Stub_Type_Access : out Entity_Id; RPC_Receiver_Decl : out Node_Id; Body_Decls : out List_Id; Existing : out Boolean); -- Add the declaration of the stub type, the access to stub type and the -- object RPC receiver at the end of Decls. If these already exist, -- then nothing is added in the tree but the right values are returned -- anyhow and Existing is set to True. function Get_And_Reset_RACW_Bodies (RACW_Type : Entity_Id) return List_Id; -- Retrieve the Body_Decls list associated to RACW_Type in the stub -- structure table, reset it to No_List, and return the previous value. procedure Add_RACW_Asynchronous_Flag (Declarations : List_Id; RACW_Type : Entity_Id); -- Declare a boolean constant associated with RACW_Type whose value -- indicates at run time whether a pragma Asynchronous applies to it. procedure Assign_Subprogram_Identifier (Def : Entity_Id; Spn : Int; Id : out String_Id); -- Determine the distribution subprogram identifier to -- be used for remote subprogram Def, return it in Id and -- store it in a hash table for later retrieval by -- Get_Subprogram_Id. Spn is the subprogram number. function RCI_Package_Locator (Loc : Source_Ptr; Package_Spec : Node_Id) return Node_Id; -- Instantiate the generic package RCI_Locator in order to locate the -- RCI package whose spec is given as argument. function Make_Tag_Check (Loc : Source_Ptr; N : Node_Id) return Node_Id; -- Surround a node N by a tag check, as in: -- begin -- ; -- exception -- when E : Ada.Tags.Tag_Error => -- Raise_Exception (Program_Error'Identity, -- Exception_Message (E)); -- end; function Input_With_Tag_Check (Loc : Source_Ptr; Var_Type : Entity_Id; Stream : Node_Id) return Node_Id; -- Return a function with the following form: -- function R return Var_Type is -- begin -- return Var_Type'Input (S); -- exception -- when E : Ada.Tags.Tag_Error => -- Raise_Exception (Program_Error'Identity, -- Exception_Message (E)); -- end R; procedure Build_Actual_Object_Declaration (Object : Entity_Id; Etyp : Entity_Id; Variable : Boolean; Expr : Node_Id; Decls : List_Id); -- Build the declaration of an object with the given defining identifier, -- initialized with Expr if provided, to serve as actual parameter in a -- server stub. If Variable is true, the declared object will be a variable -- (case of an out or in out formal), else it will be a constant. Object's -- Ekind is set accordingly. The declaration, as well as any other -- declarations it requires, are appended to Decls. -------------------------------------------- -- Hooks for PCS-specific code generation -- -------------------------------------------- -- Part of the code generation circuitry for distribution needs to be -- tailored for each implementation of the PCS. For each routine that -- needs to be specialized, a Specific_ wrapper is created, -- which calls the corresponding in package -- _Support. procedure Specific_Add_RACW_Features (RACW_Type : Entity_Id; Desig : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; RPC_Receiver_Decl : Node_Id; Body_Decls : List_Id); -- Add declaration for TSSs for a given RACW type. The declarations are -- added just after the declaration of the RACW type itself. If the RACW -- appears in the main unit, Body_Decls is a list of declarations to which -- the bodies are appended. Else Body_Decls is No_List. -- PCS-specific ancillary subprogram for Add_RACW_Features. procedure Specific_Add_RAST_Features (Vis_Decl : Node_Id; RAS_Type : Entity_Id); -- Add declaration for TSSs for a given RAS type. PCS-specific ancillary -- subprogram for Add_RAST_Features. -- An RPC_Target record is used during construction of calling stubs -- to pass PCS-specific tree fragments corresponding to the information -- necessary to locate the target of a remote subprogram call. type RPC_Target (PCS_Kind : PCS_Names) is record case PCS_Kind is when Name_PolyORB_DSA => Object : Node_Id; -- An expression whose value is a PolyORB reference to the target -- object. when others => Partition : Entity_Id; -- A variable containing the Partition_ID of the target partition RPC_Receiver : Node_Id; -- An expression whose value is the address of the target RPC -- receiver. end case; end record; procedure Specific_Build_General_Calling_Stubs (Decls : List_Id; Statements : List_Id; Target : RPC_Target; Subprogram_Id : Node_Id; Asynchronous : Node_Id := Empty; Is_Known_Asynchronous : Boolean := False; Is_Known_Non_Asynchronous : Boolean := False; Is_Function : Boolean; Spec : Node_Id; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Nod : Node_Id); -- Build calling stubs for general purpose. The parameters are: -- Decls : A place to put declarations -- Statements : A place to put statements -- Target : PCS-specific target information (see details in -- RPC_Target declaration). -- Subprogram_Id : A node containing the subprogram ID -- Asynchronous : True if an APC must be made instead of an RPC. -- The value needs not be supplied if one of the -- Is_Known_... is True. -- Is_Known_Async... : True if we know that this is asynchronous -- Is_Known_Non_A... : True if we know that this is not asynchronous -- Spec : Node with a Parameter_Specifications and a -- Result_Definition if applicable -- Stub_Type : For case of RACW stubs, parameters of type access -- to Stub_Type will be marshalled using the address -- address of the object (the addr field) rather -- than using the 'Write on the stub itself -- Nod : Used to provide sloc for generated code function Specific_Build_Stub_Target (Loc : Source_Ptr; Decls : List_Id; RCI_Locator : Entity_Id; Controlling_Parameter : Entity_Id) return RPC_Target; -- Build call target information nodes for use within calling stubs. In the -- RCI case, RCI_Locator is the entity for the instance of RCI_Locator. If -- for an RACW, Controlling_Parameter is the entity for the controlling -- formal parameter used to determine the location of the target of the -- call. Decls provides a location where variable declarations can be -- appended to construct the necessary values. function Specific_RPC_Receiver_Decl (RACW_Type : Entity_Id) return Node_Id; -- Build the RPC receiver, for RACW, if applicable, else return Empty procedure Specific_Build_RPC_Receiver_Body (RPC_Receiver : Entity_Id; Request : out Entity_Id; Subp_Id : out Entity_Id; Subp_Index : out Entity_Id; Stmts : out List_Id; Decl : out Node_Id); -- Make a subprogram body for an RPC receiver, with the given -- defining unit name. On return: -- - Subp_Id is the subprogram identifier from the PCS. -- - Subp_Index is the index in the list of subprograms -- used for dispatching (a variable of type Subprogram_Id). -- - Stmts is the place where the request dispatching -- statements can occur, -- - Decl is the subprogram body declaration. function Specific_Build_Subprogram_Receiving_Stubs (Vis_Decl : Node_Id; Asynchronous : Boolean; Dynamically_Asynchronous : Boolean := False; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Parent_Primitive : Entity_Id := Empty) return Node_Id; -- Build the receiving stub for a given subprogram. The subprogram -- declaration is also built by this procedure, and the value returned -- is a N_Subprogram_Body. If a parameter of type access to Stub_Type is -- found in the specification, then its address is read from the stream -- instead of the object itself and converted into an access to -- class-wide type before doing the real call using any of the RACW type -- pointing on the designated type. procedure Specific_Add_Obj_RPC_Receiver_Completion (Loc : Source_Ptr; Decls : List_Id; RPC_Receiver : Entity_Id; Stub_Elements : Stub_Structure); -- Add the necessary code to Decls after the completion of generation -- of the RACW RPC receiver described by Stub_Elements. procedure Specific_Add_Receiving_Stubs_To_Declarations (Pkg_Spec : Node_Id; Decls : List_Id; Stmts : List_Id); -- Add receiving stubs to the declarative part of an RCI unit -------------------- -- GARLIC_Support -- -------------------- package GARLIC_Support is -- Support for generating DSA code that uses the GARLIC PCS -- The subprograms below provide the GARLIC versions of the -- corresponding Specific_ routine declared above. procedure Add_RACW_Features (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; RPC_Receiver_Decl : Node_Id; Body_Decls : List_Id); procedure Add_RAST_Features (Vis_Decl : Node_Id; RAS_Type : Entity_Id); procedure Build_General_Calling_Stubs (Decls : List_Id; Statements : List_Id; Target_Partition : Entity_Id; -- From RPC_Target Target_RPC_Receiver : Node_Id; -- From RPC_Target Subprogram_Id : Node_Id; Asynchronous : Node_Id := Empty; Is_Known_Asynchronous : Boolean := False; Is_Known_Non_Asynchronous : Boolean := False; Is_Function : Boolean; Spec : Node_Id; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Nod : Node_Id); function Build_Stub_Target (Loc : Source_Ptr; Decls : List_Id; RCI_Locator : Entity_Id; Controlling_Parameter : Entity_Id) return RPC_Target; function RPC_Receiver_Decl (RACW_Type : Entity_Id) return Node_Id; function Build_Subprogram_Receiving_Stubs (Vis_Decl : Node_Id; Asynchronous : Boolean; Dynamically_Asynchronous : Boolean := False; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Parent_Primitive : Entity_Id := Empty) return Node_Id; procedure Add_Obj_RPC_Receiver_Completion (Loc : Source_Ptr; Decls : List_Id; RPC_Receiver : Entity_Id; Stub_Elements : Stub_Structure); procedure Add_Receiving_Stubs_To_Declarations (Pkg_Spec : Node_Id; Decls : List_Id; Stmts : List_Id); procedure Build_RPC_Receiver_Body (RPC_Receiver : Entity_Id; Request : out Entity_Id; Subp_Id : out Entity_Id; Subp_Index : out Entity_Id; Stmts : out List_Id; Decl : out Node_Id); end GARLIC_Support; --------------------- -- PolyORB_Support -- --------------------- package PolyORB_Support is -- Support for generating DSA code that uses the PolyORB PCS -- The subprograms below provide the PolyORB versions of the -- corresponding Specific_ routine declared above. procedure Add_RACW_Features (RACW_Type : Entity_Id; Desig : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; RPC_Receiver_Decl : Node_Id; Body_Decls : List_Id); procedure Add_RAST_Features (Vis_Decl : Node_Id; RAS_Type : Entity_Id); procedure Build_General_Calling_Stubs (Decls : List_Id; Statements : List_Id; Target_Object : Node_Id; -- From RPC_Target Subprogram_Id : Node_Id; Asynchronous : Node_Id := Empty; Is_Known_Asynchronous : Boolean := False; Is_Known_Non_Asynchronous : Boolean := False; Is_Function : Boolean; Spec : Node_Id; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Nod : Node_Id); function Build_Stub_Target (Loc : Source_Ptr; Decls : List_Id; RCI_Locator : Entity_Id; Controlling_Parameter : Entity_Id) return RPC_Target; function RPC_Receiver_Decl (RACW_Type : Entity_Id) return Node_Id; function Build_Subprogram_Receiving_Stubs (Vis_Decl : Node_Id; Asynchronous : Boolean; Dynamically_Asynchronous : Boolean := False; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Parent_Primitive : Entity_Id := Empty) return Node_Id; procedure Add_Obj_RPC_Receiver_Completion (Loc : Source_Ptr; Decls : List_Id; RPC_Receiver : Entity_Id; Stub_Elements : Stub_Structure); procedure Add_Receiving_Stubs_To_Declarations (Pkg_Spec : Node_Id; Decls : List_Id; Stmts : List_Id); procedure Build_RPC_Receiver_Body (RPC_Receiver : Entity_Id; Request : out Entity_Id; Subp_Id : out Entity_Id; Subp_Index : out Entity_Id; Stmts : out List_Id; Decl : out Node_Id); procedure Reserve_NamingContext_Methods; -- Mark the method names for interface NamingContext as already used in -- the overload table, so no clashes occur with user code (with the -- PolyORB PCS, RCIs Implement The NamingContext interface to allow -- their methods to be accessed as objects, for the implementation of -- remote access-to-subprogram types). ------------- -- Helpers -- ------------- package Helpers is -- Routines to build distribution helper subprograms for user-defined -- types. For implementation of the Distributed systems annex (DSA) -- over the PolyORB generic middleware components, it is necessary to -- generate several supporting subprograms for each application data -- type used in inter-partition communication. These subprograms are: -- A Typecode function returning a high-level description of the -- type's structure; -- Two conversion functions allowing conversion of values of the -- type from and to the generic data containers used by PolyORB. -- These generic containers are called 'Any' type values after the -- CORBA terminology, and hence the conversion subprograms are -- named To_Any and From_Any. function Build_From_Any_Call (Typ : Entity_Id; N : Node_Id; Decls : List_Id) return Node_Id; -- Build call to From_Any attribute function of type Typ with -- expression N as actual parameter. Decls is the declarations list -- for an appropriate enclosing scope of the point where the call -- will be inserted; if the From_Any attribute for Typ needs to be -- generated at this point, its declaration is appended to Decls. procedure Build_From_Any_Function (Loc : Source_Ptr; Typ : Entity_Id; Decl : out Node_Id; Fnam : out Entity_Id); -- Build From_Any attribute function for Typ. Loc is the reference -- location for generated nodes, Typ is the type for which the -- conversion function is generated. On return, Decl and Fnam contain -- the declaration and entity for the newly-created function. function Build_To_Any_Call (Loc : Source_Ptr; N : Node_Id; Decls : List_Id; Constrained : Boolean := False) return Node_Id; -- Build call to To_Any attribute function with expression as actual -- parameter. Loc is the reference location of generated nodes, -- Decls is the declarations list for an appropriate enclosing scope -- of the point where the call will be inserted; if the To_Any -- attribute for the type of N needs to be generated at this point, -- its declaration is appended to Decls. For the case of a limited -- type, there is an additional parameter Constrained indicating -- whether 'Write (when True) or 'Output (when False) is used. procedure Build_To_Any_Function (Loc : Source_Ptr; Typ : Entity_Id; Decl : out Node_Id; Fnam : out Entity_Id); -- Build To_Any attribute function for Typ. Loc is the reference -- location for generated nodes, Typ is the type for which the -- conversion function is generated. On return, Decl and Fnam contain -- the declaration and entity for the newly-created function. function Build_TypeCode_Call (Loc : Source_Ptr; Typ : Entity_Id; Decls : List_Id) return Node_Id; -- Build call to TypeCode attribute function for Typ. Decls is the -- declarations list for an appropriate enclosing scope of the point -- where the call will be inserted; if the To_Any attribute for Typ -- needs to be generated at this point, its declaration is appended -- to Decls. procedure Build_TypeCode_Function (Loc : Source_Ptr; Typ : Entity_Id; Decl : out Node_Id; Fnam : out Entity_Id); -- Build TypeCode attribute function for Typ. Loc is the reference -- location for generated nodes, Typ is the type for which the -- typecode function is generated. On return, Decl and Fnam contain -- the declaration and entity for the newly-created function. procedure Build_Name_And_Repository_Id (E : Entity_Id; Name_Str : out String_Id; Repo_Id_Str : out String_Id); -- In the PolyORB distribution model, each distributed object type -- and each distributed operation has a globally unique identifier, -- its Repository Id. This subprogram builds and returns two strings -- for entity E (a distributed object type or operation): one -- containing the name of E, the second containing its repository id. procedure Assign_Opaque_From_Any (Loc : Source_Ptr; Stms : List_Id; Typ : Entity_Id; N : Node_Id; Target : Entity_Id; Constrained : Boolean := False); -- For a Target object of type Typ, which has opaque representation -- as a sequence of octets determined by stream attributes (which -- includes all limited types), append code to Stmts performing the -- equivalent of: -- Target := Typ'From_Any (N) -- -- or, if Target is Empty: -- return Typ'From_Any (N) -- -- Constrained determines whether 'Input (when False) or 'Read -- (when True) is used. end Helpers; end PolyORB_Support; -- The following PolyORB-specific subprograms are made visible to Exp_Attr: function Build_From_Any_Call (Typ : Entity_Id; N : Node_Id; Decls : List_Id) return Node_Id renames PolyORB_Support.Helpers.Build_From_Any_Call; function Build_To_Any_Call (Loc : Source_Ptr; N : Node_Id; Decls : List_Id; Constrained : Boolean := False) return Node_Id renames PolyORB_Support.Helpers.Build_To_Any_Call; function Build_TypeCode_Call (Loc : Source_Ptr; Typ : Entity_Id; Decls : List_Id) return Node_Id renames PolyORB_Support.Helpers.Build_TypeCode_Call; ------------------------------------ -- Local variables and structures -- ------------------------------------ RCI_Cache : Node_Id; -- Needs comments ??? Output_From_Constrained : constant array (Boolean) of Name_Id := (False => Name_Output, True => Name_Write); -- The attribute to choose depending on the fact that the parameter -- is constrained or not. There is no such thing as Input_From_Constrained -- since this require separate mechanisms ('Input is a function while -- 'Read is a procedure). generic with procedure Process_Subprogram_Declaration (Decl : Node_Id); -- Generate calling or receiving stub for this subprogram declaration procedure Build_Package_Stubs (Pkg_Spec : Node_Id); -- Recursively visit the given RCI Package_Specification, calling -- Process_Subprogram_Declaration for each remote subprogram. ------------------------- -- Build_Package_Stubs -- ------------------------- procedure Build_Package_Stubs (Pkg_Spec : Node_Id) is Decls : constant List_Id := Visible_Declarations (Pkg_Spec); Decl : Node_Id; procedure Visit_Nested_Pkg (Nested_Pkg_Decl : Node_Id); -- Recurse for the given nested package declaration ---------------------- -- Visit_Nested_Pkg -- ---------------------- procedure Visit_Nested_Pkg (Nested_Pkg_Decl : Node_Id) is Nested_Pkg_Spec : constant Node_Id := Specification (Nested_Pkg_Decl); begin Push_Scope (Scope_Of_Spec (Nested_Pkg_Spec)); Build_Package_Stubs (Nested_Pkg_Spec); Pop_Scope; end Visit_Nested_Pkg; -- Start of processing for Build_Package_Stubs begin Decl := First (Decls); while Present (Decl) loop case Nkind (Decl) is when N_Subprogram_Declaration => -- Note: we test Comes_From_Source on Spec, not Decl, because -- in the case of a subprogram instance, only the specification -- (not the declaration) is marked as coming from source. if Comes_From_Source (Specification (Decl)) then Process_Subprogram_Declaration (Decl); end if; when N_Package_Declaration => -- Case of a nested package or package instantiation coming -- from source. Note that the anonymous wrapper package for -- subprogram instances is not flagged Is_Generic_Instance at -- this point, so there is a distinct circuit to handle them -- (see case N_Subprogram_Instantiation below). declare Pkg_Ent : constant Entity_Id := Defining_Unit_Name (Specification (Decl)); begin if Comes_From_Source (Decl) or else (Is_Generic_Instance (Pkg_Ent) and then Comes_From_Source (Get_Unit_Instantiation_Node (Pkg_Ent))) then Visit_Nested_Pkg (Decl); end if; end; when N_Subprogram_Instantiation => -- The subprogram declaration for an instance of a generic -- subprogram is wrapped in a package that does not come from -- source, so we need to explicitly traverse it here. if Comes_From_Source (Decl) then Visit_Nested_Pkg (Instance_Spec (Decl)); end if; when others => null; end case; Next (Decl); end loop; end Build_Package_Stubs; --------------------------------------- -- Add_Calling_Stubs_To_Declarations -- --------------------------------------- procedure Add_Calling_Stubs_To_Declarations (Pkg_Spec : Node_Id) is Loc : constant Source_Ptr := Sloc (Pkg_Spec); Current_Subprogram_Number : Int := First_RCI_Subprogram_Id; -- Subprogram id 0 is reserved for calls received from -- remote access-to-subprogram dereferences. RCI_Instantiation : Node_Id; procedure Visit_Subprogram (Decl : Node_Id); -- Generate calling stub for one remote subprogram ---------------------- -- Visit_Subprogram -- ---------------------- procedure Visit_Subprogram (Decl : Node_Id) is Loc : constant Source_Ptr := Sloc (Decl); Spec : constant Node_Id := Specification (Decl); Subp_Stubs : Node_Id; Subp_Str : String_Id; pragma Warnings (Off, Subp_Str); begin -- Disable expansion of stubs if serious errors have been diagnosed, -- because otherwise some illegal remote subprogram declarations -- could cause cascaded errors in stubs. if Serious_Errors_Detected /= 0 then return; end if; Assign_Subprogram_Identifier (Defining_Unit_Name (Spec), Current_Subprogram_Number, Subp_Str); Subp_Stubs := Build_Subprogram_Calling_Stubs (Vis_Decl => Decl, Subp_Id => Build_Subprogram_Id (Loc, Defining_Unit_Name (Spec)), Asynchronous => Nkind (Spec) = N_Procedure_Specification and then Is_Asynchronous (Defining_Unit_Name (Spec))); Append_To (List_Containing (Decl), Subp_Stubs); Analyze (Subp_Stubs); Current_Subprogram_Number := Current_Subprogram_Number + 1; end Visit_Subprogram; procedure Visit_Spec is new Build_Package_Stubs (Visit_Subprogram); -- Start of processing for Add_Calling_Stubs_To_Declarations begin Push_Scope (Scope_Of_Spec (Pkg_Spec)); -- The first thing added is an instantiation of the generic package -- System.Partition_Interface.RCI_Locator with the name of this remote -- package. This will act as an interface with the name server to -- determine the Partition_ID and the RPC_Receiver for the receiver -- of this package. RCI_Instantiation := RCI_Package_Locator (Loc, Pkg_Spec); RCI_Cache := Defining_Unit_Name (RCI_Instantiation); Append_To (Visible_Declarations (Pkg_Spec), RCI_Instantiation); Analyze (RCI_Instantiation); -- For each subprogram declaration visible in the spec, we do build a -- body. We also increment a counter to assign a different Subprogram_Id -- to each subprogram. The receiving stubs processing uses the same -- mechanism and will thus assign the same Id and do the correct -- dispatching. Overload_Counter_Table.Reset; PolyORB_Support.Reserve_NamingContext_Methods; Visit_Spec (Pkg_Spec); Pop_Scope; end Add_Calling_Stubs_To_Declarations; ----------------------------- -- Add_Parameter_To_NVList -- ----------------------------- function Add_Parameter_To_NVList (Loc : Source_Ptr; NVList : Entity_Id; Parameter : Entity_Id; Constrained : Boolean; RACW_Ctrl : Boolean := False; Any : Entity_Id) return Node_Id is Parameter_Name_String : String_Id; Parameter_Mode : Node_Id; function Parameter_Passing_Mode (Loc : Source_Ptr; Parameter : Entity_Id; Constrained : Boolean) return Node_Id; -- Return an expression that denotes the parameter passing mode to be -- used for Parameter in distribution stubs, where Constrained is -- Parameter's constrained status. ---------------------------- -- Parameter_Passing_Mode -- ---------------------------- function Parameter_Passing_Mode (Loc : Source_Ptr; Parameter : Entity_Id; Constrained : Boolean) return Node_Id is Lib_RE : RE_Id; begin if Out_Present (Parameter) then if In_Present (Parameter) or else not Constrained then -- Unconstrained formals must be translated -- to 'in' or 'inout', not 'out', because -- they need to be constrained by the actual. Lib_RE := RE_Mode_Inout; else Lib_RE := RE_Mode_Out; end if; else Lib_RE := RE_Mode_In; end if; return New_Occurrence_Of (RTE (Lib_RE), Loc); end Parameter_Passing_Mode; -- Start of processing for Add_Parameter_To_NVList begin if Nkind (Parameter) = N_Defining_Identifier then Get_Name_String (Chars (Parameter)); else Get_Name_String (Chars (Defining_Identifier (Parameter))); end if; Parameter_Name_String := String_From_Name_Buffer; if RACW_Ctrl or else Nkind (Parameter) = N_Defining_Identifier then -- When the parameter passed to Add_Parameter_To_NVList is an -- Extra_Constrained parameter, Parameter is an N_Defining_ -- Identifier, instead of a complete N_Parameter_Specification. -- Thus, we explicitly set 'in' mode in this case. Parameter_Mode := New_Occurrence_Of (RTE (RE_Mode_In), Loc); else Parameter_Mode := Parameter_Passing_Mode (Loc, Parameter, Constrained); end if; return Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_NVList_Add_Item), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (NVList, Loc), Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_To_PolyORB_String), Loc), Parameter_Associations => New_List ( Make_String_Literal (Loc, Strval => Parameter_Name_String))), New_Occurrence_Of (Any, Loc), Parameter_Mode)); end Add_Parameter_To_NVList; -------------------------------- -- Add_RACW_Asynchronous_Flag -- -------------------------------- procedure Add_RACW_Asynchronous_Flag (Declarations : List_Id; RACW_Type : Entity_Id) is Loc : constant Source_Ptr := Sloc (RACW_Type); Asynchronous_Flag : constant Entity_Id := Make_Defining_Identifier (Loc, New_External_Name (Chars (RACW_Type), 'A')); begin -- Declare the asynchronous flag. This flag will be changed to True -- whenever it is known that the RACW type is asynchronous. Append_To (Declarations, Make_Object_Declaration (Loc, Defining_Identifier => Asynchronous_Flag, Constant_Present => True, Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc), Expression => New_Occurrence_Of (Standard_False, Loc))); Asynchronous_Flags_Table.Set (RACW_Type, Asynchronous_Flag); end Add_RACW_Asynchronous_Flag; ----------------------- -- Add_RACW_Features -- ----------------------- procedure Add_RACW_Features (RACW_Type : Entity_Id) is Desig : constant Entity_Id := Etype (Designated_Type (RACW_Type)); Same_Scope : constant Boolean := Scope (Desig) = Scope (RACW_Type); Pkg_Spec : Node_Id; Decls : List_Id; Body_Decls : List_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; RPC_Receiver_Decl : Node_Id; Existing : Boolean; -- True when appropriate stubs have already been generated (this is the -- case when another RACW with the same designated type has already been -- encountered), in which case we reuse the previous stubs rather than -- generating new ones. begin if not Expander_Active then return; end if; -- Mark the current package declaration as containing an RACW, so that -- the bodies for the calling stubs and the RACW stream subprograms -- are attached to the tree when the corresponding body is encountered. Set_Has_RACW (Current_Scope); -- Look for place to declare the RACW stub type and RACW operations Pkg_Spec := Empty; if Same_Scope then -- Case of declaring the RACW in the same package as its designated -- type: we know that the designated type is a private type, so we -- use the private declarations list. Pkg_Spec := Package_Specification_Of_Scope (Current_Scope); if Present (Private_Declarations (Pkg_Spec)) then Decls := Private_Declarations (Pkg_Spec); else Decls := Visible_Declarations (Pkg_Spec); end if; else -- Case of declaring the RACW in another package than its designated -- type: use the private declarations list if present; otherwise -- use the visible declarations. Decls := List_Containing (Declaration_Node (RACW_Type)); end if; -- If we were unable to find the declarations, that means that the -- completion of the type was missing. We can safely return and let the -- error be caught by the semantic analysis. if No (Decls) then return; end if; Add_Stub_Type (Designated_Type => Desig, RACW_Type => RACW_Type, Decls => Decls, Stub_Type => Stub_Type, Stub_Type_Access => Stub_Type_Access, RPC_Receiver_Decl => RPC_Receiver_Decl, Body_Decls => Body_Decls, Existing => Existing); -- If this RACW is not in the main unit, do not generate primitive or -- TSS bodies. if not Entity_Is_In_Main_Unit (RACW_Type) then Body_Decls := No_List; end if; Add_RACW_Asynchronous_Flag (Declarations => Decls, RACW_Type => RACW_Type); Specific_Add_RACW_Features (RACW_Type => RACW_Type, Desig => Desig, Stub_Type => Stub_Type, Stub_Type_Access => Stub_Type_Access, RPC_Receiver_Decl => RPC_Receiver_Decl, Body_Decls => Body_Decls); -- If we already have stubs for this designated type, nothing to do if Existing then return; end if; if Is_Frozen (Desig) then Validate_RACW_Primitives (RACW_Type); Add_RACW_Primitive_Declarations_And_Bodies (Designated_Type => Desig, Insertion_Node => RPC_Receiver_Decl, Body_Decls => Body_Decls); else -- Validate_RACW_Primitives requires the list of all primitives of -- the designated type, so defer processing until Desig is frozen. -- See Exp_Ch3.Freeze_Type. Add_Access_Type_To_Process (E => Desig, A => RACW_Type); end if; end Add_RACW_Features; ------------------------------------------------ -- Add_RACW_Primitive_Declarations_And_Bodies -- ------------------------------------------------ procedure Add_RACW_Primitive_Declarations_And_Bodies (Designated_Type : Entity_Id; Insertion_Node : Node_Id; Body_Decls : List_Id) is Loc : constant Source_Ptr := Sloc (Insertion_Node); -- Set Sloc of generated declaration copy of insertion node Sloc, so -- the declarations are recognized as belonging to the current package. Stub_Elements : constant Stub_Structure := Stubs_Table.Get (Designated_Type); pragma Assert (Stub_Elements /= Empty_Stub_Structure); Is_RAS : constant Boolean := not Comes_From_Source (Stub_Elements.RACW_Type); -- Case of the RACW generated to implement a remote access-to- -- subprogram type. Build_Bodies : constant Boolean := In_Extended_Main_Code_Unit (Stub_Elements.Stub_Type); -- True when bodies must be prepared in Body_Decls. Bodies are generated -- only when the main unit is the unit that contains the stub type. Current_Insertion_Node : Node_Id := Insertion_Node; RPC_Receiver : Entity_Id; RPC_Receiver_Statements : List_Id; RPC_Receiver_Case_Alternatives : constant List_Id := New_List; RPC_Receiver_Elsif_Parts : List_Id := No_List; RPC_Receiver_Request : Entity_Id := Empty; RPC_Receiver_Subp_Id : Entity_Id := Empty; RPC_Receiver_Subp_Index : Entity_Id := Empty; Subp_Str : String_Id; Current_Primitive_Elmt : Elmt_Id; Current_Primitive : Entity_Id; Current_Primitive_Body : Node_Id; Current_Primitive_Spec : Node_Id; Current_Primitive_Decl : Node_Id; Current_Primitive_Number : Int := 0; Current_Primitive_Alias : Node_Id; Current_Receiver : Entity_Id; Current_Receiver_Body : Node_Id; RPC_Receiver_Decl : Node_Id; Possibly_Asynchronous : Boolean; begin if not Expander_Active then return; end if; if not Is_RAS then RPC_Receiver := Make_Temporary (Loc, 'P'); Specific_Build_RPC_Receiver_Body (RPC_Receiver => RPC_Receiver, Request => RPC_Receiver_Request, Subp_Id => RPC_Receiver_Subp_Id, Subp_Index => RPC_Receiver_Subp_Index, Stmts => RPC_Receiver_Statements, Decl => RPC_Receiver_Decl); if Get_PCS_Name = Name_PolyORB_DSA then -- For the case of PolyORB, we need to map a textual operation -- name into a primitive index. Currently we do so using a simple -- sequence of string comparisons. RPC_Receiver_Elsif_Parts := New_List; end if; end if; -- Build callers, receivers for every primitive operations and a RPC -- receiver for this type. Note that we use Direct_Primitive_Operations, -- not Primitive_Operations, because we really want just the primitives -- of the tagged type itself, and in the case of a tagged synchronized -- type we do not want to get the primitives of the corresponding -- record type). if Present (Direct_Primitive_Operations (Designated_Type)) then Overload_Counter_Table.Reset; Current_Primitive_Elmt := First_Elmt (Direct_Primitive_Operations (Designated_Type)); while Current_Primitive_Elmt /= No_Elmt loop Current_Primitive := Node (Current_Primitive_Elmt); -- Copy the primitive of all the parents, except predefined ones -- that are not remotely dispatching. Also omit hidden primitives -- (occurs in the case of primitives of interface progenitors -- other than immediate ancestors of the Designated_Type). if Chars (Current_Primitive) /= Name_uSize and then Chars (Current_Primitive) /= Name_uAlignment and then not (Is_TSS (Current_Primitive, TSS_Deep_Finalize) or else Is_TSS (Current_Primitive, TSS_Stream_Input) or else Is_TSS (Current_Primitive, TSS_Stream_Output) or else Is_TSS (Current_Primitive, TSS_Stream_Read) or else Is_TSS (Current_Primitive, TSS_Stream_Write) or else Is_Predefined_Interface_Primitive (Current_Primitive)) and then not Is_Hidden (Current_Primitive) then -- The first thing to do is build an up-to-date copy of the -- spec with all the formals referencing Controlling_Type -- transformed into formals referencing Stub_Type. Since this -- primitive may have been inherited, go back the alias chain -- until the real primitive has been found. Current_Primitive_Alias := Ultimate_Alias (Current_Primitive); -- Copy the spec from the original declaration for the purpose -- of declaring an overriding subprogram: we need to replace -- the type of each controlling formal with Stub_Type. The -- primitive may have been declared for Controlling_Type or -- inherited from some ancestor type for which we do not have -- an easily determined Entity_Id. We have no systematic way -- of knowing which type to substitute Stub_Type for. Instead, -- Copy_Specification relies on the flag Is_Controlling_Formal -- to determine which formals to change. Current_Primitive_Spec := Copy_Specification (Loc, Spec => Parent (Current_Primitive_Alias), Ctrl_Type => Stub_Elements.Stub_Type); Current_Primitive_Decl := Make_Subprogram_Declaration (Loc, Specification => Current_Primitive_Spec); Insert_After_And_Analyze (Current_Insertion_Node, Current_Primitive_Decl); Current_Insertion_Node := Current_Primitive_Decl; Possibly_Asynchronous := Nkind (Current_Primitive_Spec) = N_Procedure_Specification and then Could_Be_Asynchronous (Current_Primitive_Spec); Assign_Subprogram_Identifier ( Defining_Unit_Name (Current_Primitive_Spec), Current_Primitive_Number, Subp_Str); if Build_Bodies then Current_Primitive_Body := Build_Subprogram_Calling_Stubs (Vis_Decl => Current_Primitive_Decl, Subp_Id => Build_Subprogram_Id (Loc, Defining_Unit_Name (Current_Primitive_Spec)), Asynchronous => Possibly_Asynchronous, Dynamically_Asynchronous => Possibly_Asynchronous, Stub_Type => Stub_Elements.Stub_Type, RACW_Type => Stub_Elements.RACW_Type); Append_To (Body_Decls, Current_Primitive_Body); -- Analyzing the body here would cause the Stub type to -- be frozen, thus preventing subsequent primitive -- declarations. For this reason, it will be analyzed -- later in the regular flow (and in the context of the -- appropriate unit body, see Append_RACW_Bodies). end if; -- Build the receiver stubs if Build_Bodies and then not Is_RAS then Current_Receiver_Body := Specific_Build_Subprogram_Receiving_Stubs (Vis_Decl => Current_Primitive_Decl, Asynchronous => Possibly_Asynchronous, Dynamically_Asynchronous => Possibly_Asynchronous, Stub_Type => Stub_Elements.Stub_Type, RACW_Type => Stub_Elements.RACW_Type, Parent_Primitive => Current_Primitive); Current_Receiver := Defining_Unit_Name (Specification (Current_Receiver_Body)); Append_To (Body_Decls, Current_Receiver_Body); -- Add a case alternative to the receiver if Get_PCS_Name = Name_PolyORB_DSA then Append_To (RPC_Receiver_Elsif_Parts, Make_Elsif_Part (Loc, Condition => Make_Function_Call (Loc, Name => New_Occurrence_Of ( RTE (RE_Caseless_String_Eq), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (RPC_Receiver_Subp_Id, Loc), Make_String_Literal (Loc, Subp_Str))), Then_Statements => New_List ( Make_Assignment_Statement (Loc, Name => New_Occurrence_Of ( RPC_Receiver_Subp_Index, Loc), Expression => Make_Integer_Literal (Loc, Intval => Current_Primitive_Number))))); end if; Append_To (RPC_Receiver_Case_Alternatives, Make_Case_Statement_Alternative (Loc, Discrete_Choices => New_List ( Make_Integer_Literal (Loc, Current_Primitive_Number)), Statements => New_List ( Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (Current_Receiver, Loc), Parameter_Associations => New_List ( New_Occurrence_Of (RPC_Receiver_Request, Loc)))))); end if; -- Increment the index of current primitive Current_Primitive_Number := Current_Primitive_Number + 1; end if; Next_Elmt (Current_Primitive_Elmt); end loop; end if; -- Build the case statement and the heart of the subprogram if Build_Bodies and then not Is_RAS then if Get_PCS_Name = Name_PolyORB_DSA and then Present (First (RPC_Receiver_Elsif_Parts)) then Append_To (RPC_Receiver_Statements, Make_Implicit_If_Statement (Designated_Type, Condition => New_Occurrence_Of (Standard_False, Loc), Then_Statements => New_List, Elsif_Parts => RPC_Receiver_Elsif_Parts)); end if; Append_To (RPC_Receiver_Case_Alternatives, Make_Case_Statement_Alternative (Loc, Discrete_Choices => New_List (Make_Others_Choice (Loc)), Statements => New_List (Make_Null_Statement (Loc)))); Append_To (RPC_Receiver_Statements, Make_Case_Statement (Loc, Expression => New_Occurrence_Of (RPC_Receiver_Subp_Index, Loc), Alternatives => RPC_Receiver_Case_Alternatives)); Append_To (Body_Decls, RPC_Receiver_Decl); Specific_Add_Obj_RPC_Receiver_Completion (Loc, Body_Decls, RPC_Receiver, Stub_Elements); -- Do not analyze RPC receiver body at this stage since it references -- subprograms that have not been analyzed yet. It will be analyzed in -- the regular flow (see Append_RACW_Bodies). end if; end Add_RACW_Primitive_Declarations_And_Bodies; ----------------------------- -- Add_RAS_Dereference_TSS -- ----------------------------- procedure Add_RAS_Dereference_TSS (N : Node_Id) is Loc : constant Source_Ptr := Sloc (N); Type_Def : constant Node_Id := Type_Definition (N); RAS_Type : constant Entity_Id := Defining_Identifier (N); Fat_Type : constant Entity_Id := Equivalent_Type (RAS_Type); RACW_Type : constant Entity_Id := Underlying_RACW_Type (RAS_Type); RACW_Primitive_Name : Node_Id; Proc : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Make_TSS_Name (RAS_Type, TSS_RAS_Dereference)); Proc_Spec : Node_Id; Param_Specs : List_Id; Param_Assoc : constant List_Id := New_List; Stmts : constant List_Id := New_List; RAS_Parameter : constant Entity_Id := Make_Temporary (Loc, 'P'); Is_Function : constant Boolean := Nkind (Type_Def) = N_Access_Function_Definition; Is_Degenerate : Boolean; -- Set to True if the subprogram_specification for this RAS has an -- anonymous access parameter (see Process_Remote_AST_Declaration). Spec : constant Node_Id := Type_Def; Current_Parameter : Node_Id; -- Start of processing for Add_RAS_Dereference_TSS begin -- The Dereference TSS for a remote access-to-subprogram type has the -- form: -- [function|procedure] ras_typeRD (RAS_Value, ) -- [return <>] -- This is called whenever a value of a RAS type is dereferenced -- First construct a list of parameter specifications: -- The first formal is the RAS values Param_Specs := New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => RAS_Parameter, In_Present => True, Parameter_Type => New_Occurrence_Of (Fat_Type, Loc))); -- The following formals are copied from the type declaration Is_Degenerate := False; Current_Parameter := First (Parameter_Specifications (Type_Def)); Parameters : while Present (Current_Parameter) loop if Nkind (Parameter_Type (Current_Parameter)) = N_Access_Definition then Is_Degenerate := True; end if; Append_To (Param_Specs, Make_Parameter_Specification (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Chars => Chars (Defining_Identifier (Current_Parameter))), In_Present => In_Present (Current_Parameter), Out_Present => Out_Present (Current_Parameter), Parameter_Type => New_Copy_Tree (Parameter_Type (Current_Parameter)), Expression => New_Copy_Tree (Expression (Current_Parameter)))); Append_To (Param_Assoc, Make_Identifier (Loc, Chars => Chars (Defining_Identifier (Current_Parameter)))); Next (Current_Parameter); end loop Parameters; if Is_Degenerate then Prepend_To (Param_Assoc, New_Occurrence_Of (RAS_Parameter, Loc)); -- Generate a dummy body. This code will never actually be executed, -- because null is the only legal value for a degenerate RAS type. -- For legality's sake (in order to avoid generating a function that -- does not contain a return statement), we include a dummy recursive -- call on the TSS itself. Append_To (Stmts, Make_Raise_Program_Error (Loc, Reason => PE_Explicit_Raise)); RACW_Primitive_Name := New_Occurrence_Of (Proc, Loc); else -- For a normal RAS type, we cast the RAS formal to the corresponding -- tagged type, and perform a dispatching call to its Call primitive -- operation. Prepend_To (Param_Assoc, Unchecked_Convert_To (RACW_Type, New_Occurrence_Of (RAS_Parameter, Loc))); RACW_Primitive_Name := Make_Selected_Component (Loc, Prefix => Scope (RACW_Type), Selector_Name => Name_uCall); end if; if Is_Function then Append_To (Stmts, Make_Simple_Return_Statement (Loc, Expression => Make_Function_Call (Loc, Name => RACW_Primitive_Name, Parameter_Associations => Param_Assoc))); else Append_To (Stmts, Make_Procedure_Call_Statement (Loc, Name => RACW_Primitive_Name, Parameter_Associations => Param_Assoc)); end if; -- Build the complete subprogram if Is_Function then Proc_Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Proc, Parameter_Specifications => Param_Specs, Result_Definition => New_Occurrence_Of ( Entity (Result_Definition (Spec)), Loc)); Set_Ekind (Proc, E_Function); Set_Etype (Proc, New_Occurrence_Of (Entity (Result_Definition (Spec)), Loc)); else Proc_Spec := Make_Procedure_Specification (Loc, Defining_Unit_Name => Proc, Parameter_Specifications => Param_Specs); Set_Ekind (Proc, E_Procedure); Set_Etype (Proc, Standard_Void_Type); end if; Discard_Node ( Make_Subprogram_Body (Loc, Specification => Proc_Spec, Declarations => New_List, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts))); Set_TSS (Fat_Type, Proc); end Add_RAS_Dereference_TSS; ------------------------------- -- Add_RAS_Proxy_And_Analyze -- ------------------------------- procedure Add_RAS_Proxy_And_Analyze (Decls : List_Id; Vis_Decl : Node_Id; All_Calls_Remote_E : Entity_Id; Proxy_Object_Addr : out Entity_Id) is Loc : constant Source_Ptr := Sloc (Vis_Decl); Subp_Name : constant Entity_Id := Defining_Unit_Name (Specification (Vis_Decl)); Pkg_Name : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => New_External_Name (Chars (Subp_Name), 'P', -1)); Proxy_Type : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => New_External_Name (Related_Id => Chars (Subp_Name), Suffix => 'P')); Proxy_Type_Full_View : constant Entity_Id := Make_Defining_Identifier (Loc, Chars (Proxy_Type)); Subp_Decl_Spec : constant Node_Id := Build_RAS_Primitive_Specification (Subp_Spec => Specification (Vis_Decl), Remote_Object_Type => Proxy_Type); Subp_Body_Spec : constant Node_Id := Build_RAS_Primitive_Specification (Subp_Spec => Specification (Vis_Decl), Remote_Object_Type => Proxy_Type); Vis_Decls : constant List_Id := New_List; Pvt_Decls : constant List_Id := New_List; Actuals : constant List_Id := New_List; Formal : Node_Id; Perform_Call : Node_Id; begin -- type subpP is tagged limited private; Append_To (Vis_Decls, Make_Private_Type_Declaration (Loc, Defining_Identifier => Proxy_Type, Tagged_Present => True, Limited_Present => True)); -- [subprogram] Call -- (Self : access subpP; -- ...other-formals...) -- [return T]; Append_To (Vis_Decls, Make_Subprogram_Declaration (Loc, Specification => Subp_Decl_Spec)); -- A : constant System.Address; Proxy_Object_Addr := Make_Defining_Identifier (Loc, Name_uA); Append_To (Vis_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Proxy_Object_Addr, Constant_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Address), Loc))); -- private -- type subpP is tagged limited record -- All_Calls_Remote : Boolean := [All_Calls_Remote?]; -- ... -- end record; Append_To (Pvt_Decls, Make_Full_Type_Declaration (Loc, Defining_Identifier => Proxy_Type_Full_View, Type_Definition => Build_Remote_Subprogram_Proxy_Type (Loc, New_Occurrence_Of (All_Calls_Remote_E, Loc)))); -- Trick semantic analysis into swapping the public and full view when -- freezing the public view. Set_Comes_From_Source (Proxy_Type_Full_View, True); -- procedure Call -- (Self : access O; -- ...other-formals...) is -- begin -- P (...other-formals...); -- end Call; -- function Call -- (Self : access O; -- ...other-formals...) -- return T is -- begin -- return F (...other-formals...); -- end Call; if Nkind (Subp_Decl_Spec) = N_Procedure_Specification then Perform_Call := Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (Subp_Name, Loc), Parameter_Associations => Actuals); else Perform_Call := Make_Simple_Return_Statement (Loc, Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (Subp_Name, Loc), Parameter_Associations => Actuals)); end if; Formal := First (Parameter_Specifications (Subp_Decl_Spec)); pragma Assert (Present (Formal)); loop Next (Formal); exit when No (Formal); Append_To (Actuals, New_Occurrence_Of (Defining_Identifier (Formal), Loc)); end loop; -- O : aliased subpP; Append_To (Pvt_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Name_uO), Aliased_Present => True, Object_Definition => New_Occurrence_Of (Proxy_Type, Loc))); -- A : constant System.Address := O'Address; Append_To (Pvt_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Chars (Proxy_Object_Addr)), Constant_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Address), Loc), Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of ( Defining_Identifier (Last (Pvt_Decls)), Loc), Attribute_Name => Name_Address))); Append_To (Decls, Make_Package_Declaration (Loc, Specification => Make_Package_Specification (Loc, Defining_Unit_Name => Pkg_Name, Visible_Declarations => Vis_Decls, Private_Declarations => Pvt_Decls, End_Label => Empty))); Analyze (Last (Decls)); Append_To (Decls, Make_Package_Body (Loc, Defining_Unit_Name => Make_Defining_Identifier (Loc, Chars (Pkg_Name)), Declarations => New_List ( Make_Subprogram_Body (Loc, Specification => Subp_Body_Spec, Declarations => New_List, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => New_List (Perform_Call)))))); Analyze (Last (Decls)); end Add_RAS_Proxy_And_Analyze; ----------------------- -- Add_RAST_Features -- ----------------------- procedure Add_RAST_Features (Vis_Decl : Node_Id) is RAS_Type : constant Entity_Id := Equivalent_Type (Defining_Identifier (Vis_Decl)); begin pragma Assert (No (TSS (RAS_Type, TSS_RAS_Access))); Add_RAS_Dereference_TSS (Vis_Decl); Specific_Add_RAST_Features (Vis_Decl, RAS_Type); end Add_RAST_Features; ------------------- -- Add_Stub_Type -- ------------------- procedure Add_Stub_Type (Designated_Type : Entity_Id; RACW_Type : Entity_Id; Decls : List_Id; Stub_Type : out Entity_Id; Stub_Type_Access : out Entity_Id; RPC_Receiver_Decl : out Node_Id; Body_Decls : out List_Id; Existing : out Boolean) is Loc : constant Source_Ptr := Sloc (RACW_Type); Stub_Elements : constant Stub_Structure := Stubs_Table.Get (Designated_Type); Stub_Type_Decl : Node_Id; Stub_Type_Access_Decl : Node_Id; begin if Stub_Elements /= Empty_Stub_Structure then Stub_Type := Stub_Elements.Stub_Type; Stub_Type_Access := Stub_Elements.Stub_Type_Access; RPC_Receiver_Decl := Stub_Elements.RPC_Receiver_Decl; Body_Decls := Stub_Elements.Body_Decls; Existing := True; return; end if; Existing := False; Stub_Type := Make_Temporary (Loc, 'S'); Set_Ekind (Stub_Type, E_Record_Type); Set_Is_RACW_Stub_Type (Stub_Type); Stub_Type_Access := Make_Defining_Identifier (Loc, Chars => New_External_Name (Related_Id => Chars (Stub_Type), Suffix => 'A')); RPC_Receiver_Decl := Specific_RPC_Receiver_Decl (RACW_Type); -- Create new stub type, copying components from generic RACW_Stub_Type Stub_Type_Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => Stub_Type, Type_Definition => Make_Record_Definition (Loc, Tagged_Present => True, Limited_Present => True, Component_List => Make_Component_List (Loc, Component_Items => Copy_Component_List (RTE (RE_RACW_Stub_Type), Loc)))); -- Does the stub type need to explicitly implement interfaces from the -- designated type??? -- In particular are there issues in the case where the designated type -- is a synchronized interface??? Stub_Type_Access_Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => Stub_Type_Access, Type_Definition => Make_Access_To_Object_Definition (Loc, All_Present => True, Subtype_Indication => New_Occurrence_Of (Stub_Type, Loc))); Append_To (Decls, Stub_Type_Decl); Analyze (Last (Decls)); Append_To (Decls, Stub_Type_Access_Decl); Analyze (Last (Decls)); -- We can't directly derive the stub type from the designated type, -- because we don't want any components or discriminants from the real -- type, so instead we manually fake a derivation to get an appropriate -- dispatch table. Derive_Subprograms (Parent_Type => Designated_Type, Derived_Type => Stub_Type); if Present (RPC_Receiver_Decl) then Append_To (Decls, RPC_Receiver_Decl); else -- Case of RACW implementing a RAS with the GARLIC PCS: there is -- no RPC receiver in that case, this is just an indication of -- where to insert code in the tree (see comment in declaration of -- type Stub_Structure). RPC_Receiver_Decl := Last (Decls); end if; Body_Decls := New_List; Stubs_Table.Set (Designated_Type, (Stub_Type => Stub_Type, Stub_Type_Access => Stub_Type_Access, RPC_Receiver_Decl => RPC_Receiver_Decl, Body_Decls => Body_Decls, RACW_Type => RACW_Type)); end Add_Stub_Type; ------------------------ -- Append_RACW_Bodies -- ------------------------ procedure Append_RACW_Bodies (Decls : List_Id; Spec_Id : Entity_Id) is E : Entity_Id; begin E := First_Entity (Spec_Id); while Present (E) loop if Is_Remote_Access_To_Class_Wide_Type (E) then Append_List_To (Decls, Get_And_Reset_RACW_Bodies (E)); end if; Next_Entity (E); end loop; end Append_RACW_Bodies; ---------------------------------- -- Assign_Subprogram_Identifier -- ---------------------------------- procedure Assign_Subprogram_Identifier (Def : Entity_Id; Spn : Int; Id : out String_Id) is N : constant Name_Id := Chars (Def); Overload_Order : constant Int := Overload_Counter_Table.Get (N) + 1; begin Overload_Counter_Table.Set (N, Overload_Order); Get_Name_String (N); -- Homonym handling: as in Exp_Dbug, but much simpler, because the only -- entities for which we have to generate names here need only to be -- disambiguated within their own scope. if Overload_Order > 1 then Name_Buffer (Name_Len + 1 .. Name_Len + 2) := "__"; Name_Len := Name_Len + 2; Add_Nat_To_Name_Buffer (Overload_Order); end if; Id := String_From_Name_Buffer; Subprogram_Identifier_Table.Set (Def, Subprogram_Identifiers'(Str_Identifier => Id, Int_Identifier => Spn)); end Assign_Subprogram_Identifier; ------------------------------------- -- Build_Actual_Object_Declaration -- ------------------------------------- procedure Build_Actual_Object_Declaration (Object : Entity_Id; Etyp : Entity_Id; Variable : Boolean; Expr : Node_Id; Decls : List_Id) is Loc : constant Source_Ptr := Sloc (Object); begin -- Declare a temporary object for the actual, possibly initialized with -- a 'Input/From_Any call. -- Complication arises in the case of limited types, for which such a -- declaration is illegal in Ada 95. In that case, we first generate a -- renaming declaration of the 'Input call, and then if needed we -- generate an overlaid non-constant view. if Ada_Version <= Ada_95 and then Is_Limited_Type (Etyp) and then Present (Expr) then -- Object : Etyp renames Append_To (Decls, Make_Object_Renaming_Declaration (Loc, Defining_Identifier => Object, Subtype_Mark => New_Occurrence_Of (Etyp, Loc), Name => Expr)); if Variable then -- The name defined by the renaming declaration denotes a -- constant view; create a non-constant object at the same address -- to be used as the actual. declare Constant_Object : constant Entity_Id := Make_Temporary (Loc, 'P'); begin Set_Defining_Identifier (Last (Decls), Constant_Object); -- We have an unconstrained Etyp: build the actual constrained -- subtype for the value we just read from the stream. -- subtype S is ; Append_To (Decls, Build_Actual_Subtype (Etyp, New_Occurrence_Of (Constant_Object, Loc))); -- Object : S; Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Object, Object_Definition => New_Occurrence_Of (Defining_Identifier (Last (Decls)), Loc))); Set_Ekind (Object, E_Variable); -- Suppress default initialization: -- pragma Import (Ada, Object); Append_To (Decls, Make_Pragma (Loc, Chars => Name_Import, Pragma_Argument_Associations => New_List ( Make_Pragma_Argument_Association (Loc, Chars => Name_Convention, Expression => Make_Identifier (Loc, Name_Ada)), Make_Pragma_Argument_Association (Loc, Chars => Name_Entity, Expression => New_Occurrence_Of (Object, Loc))))); -- for Object'Address use Constant_Object'Address; Append_To (Decls, Make_Attribute_Definition_Clause (Loc, Name => New_Occurrence_Of (Object, Loc), Chars => Name_Address, Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Constant_Object, Loc), Attribute_Name => Name_Address))); end; end if; else -- General case of a regular object declaration. Object is flagged -- constant unless it has mode out or in out, to allow the backend -- to optimize where possible. -- Object : [constant] Etyp [:= ]; Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Object, Constant_Present => Present (Expr) and then not Variable, Object_Definition => New_Occurrence_Of (Etyp, Loc), Expression => Expr)); if Constant_Present (Last (Decls)) then Set_Ekind (Object, E_Constant); else Set_Ekind (Object, E_Variable); end if; end if; end Build_Actual_Object_Declaration; ------------------------------ -- Build_Get_Unique_RP_Call -- ------------------------------ function Build_Get_Unique_RP_Call (Loc : Source_Ptr; Pointer : Entity_Id; Stub_Type : Entity_Id) return List_Id is begin return New_List ( Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Get_Unique_Remote_Pointer), Loc), Parameter_Associations => New_List ( Unchecked_Convert_To (RTE (RE_RACW_Stub_Type_Access), New_Occurrence_Of (Pointer, Loc)))), Make_Assignment_Statement (Loc, Name => Make_Selected_Component (Loc, Prefix => New_Occurrence_Of (Pointer, Loc), Selector_Name => New_Occurrence_Of (First_Tag_Component (Designated_Type (Etype (Pointer))), Loc)), Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stub_Type, Loc), Attribute_Name => Name_Tag))); -- Note: The assignment to Pointer._Tag is safe here because -- we carefully ensured that Stub_Type has exactly the same layout -- as System.Partition_Interface.RACW_Stub_Type. end Build_Get_Unique_RP_Call; ----------------------------------- -- Build_Ordered_Parameters_List -- ----------------------------------- function Build_Ordered_Parameters_List (Spec : Node_Id) return List_Id is Constrained_List : List_Id; Unconstrained_List : List_Id; Current_Parameter : Node_Id; Ptyp : Node_Id; First_Parameter : Node_Id; For_RAS : Boolean := False; begin if No (Parameter_Specifications (Spec)) then return New_List; end if; Constrained_List := New_List; Unconstrained_List := New_List; First_Parameter := First (Parameter_Specifications (Spec)); if Nkind (Parameter_Type (First_Parameter)) = N_Access_Definition and then Chars (Defining_Identifier (First_Parameter)) = Name_uS then For_RAS := True; end if; -- Loop through the parameters and add them to the right list. Note that -- we treat a parameter of a null-excluding access type as unconstrained -- because we can't declare an object of such a type with default -- initialization. Current_Parameter := First_Parameter; while Present (Current_Parameter) loop Ptyp := Parameter_Type (Current_Parameter); if (Nkind (Ptyp) = N_Access_Definition or else not Transmit_As_Unconstrained (Etype (Ptyp))) and then not (For_RAS and then Current_Parameter = First_Parameter) then Append_To (Constrained_List, New_Copy (Current_Parameter)); else Append_To (Unconstrained_List, New_Copy (Current_Parameter)); end if; Next (Current_Parameter); end loop; -- Unconstrained parameters are returned first Append_List_To (Unconstrained_List, Constrained_List); return Unconstrained_List; end Build_Ordered_Parameters_List; ---------------------------------- -- Build_Passive_Partition_Stub -- ---------------------------------- procedure Build_Passive_Partition_Stub (U : Node_Id) is Pkg_Spec : Node_Id; Pkg_Ent : Entity_Id; L : List_Id; Reg : Node_Id; Loc : constant Source_Ptr := Sloc (U); begin -- Verify that the implementation supports distribution, by accessing -- a type defined in the proper version of system.rpc declare Dist_OK : Entity_Id; pragma Warnings (Off, Dist_OK); begin Dist_OK := RTE (RE_Params_Stream_Type); end; -- Use body if present, spec otherwise if Nkind (U) = N_Package_Declaration then Pkg_Spec := Specification (U); L := Visible_Declarations (Pkg_Spec); else Pkg_Spec := Parent (Corresponding_Spec (U)); L := Declarations (U); end if; Pkg_Ent := Defining_Entity (Pkg_Spec); Reg := Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Register_Passive_Package), Loc), Parameter_Associations => New_List ( Make_String_Literal (Loc, Fully_Qualified_Name_String (Pkg_Ent, Append_NUL => False)), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Pkg_Ent, Loc), Attribute_Name => Name_Version))); Append_To (L, Reg); Analyze (Reg); end Build_Passive_Partition_Stub; -------------------------------------- -- Build_RPC_Receiver_Specification -- -------------------------------------- function Build_RPC_Receiver_Specification (RPC_Receiver : Entity_Id; Request_Parameter : Entity_Id) return Node_Id is Loc : constant Source_Ptr := Sloc (RPC_Receiver); begin return Make_Procedure_Specification (Loc, Defining_Unit_Name => RPC_Receiver, Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Request_Parameter, Parameter_Type => New_Occurrence_Of (RTE (RE_Request_Access), Loc)))); end Build_RPC_Receiver_Specification; ---------------------------------------- -- Build_Remote_Subprogram_Proxy_Type -- ---------------------------------------- function Build_Remote_Subprogram_Proxy_Type (Loc : Source_Ptr; ACR_Expression : Node_Id) return Node_Id is begin return Make_Record_Definition (Loc, Tagged_Present => True, Limited_Present => True, Component_List => Make_Component_List (Loc, Component_Items => New_List ( Make_Component_Declaration (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Name_All_Calls_Remote), Component_Definition => Make_Component_Definition (Loc, Subtype_Indication => New_Occurrence_Of (Standard_Boolean, Loc)), Expression => ACR_Expression), Make_Component_Declaration (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Name_Receiver), Component_Definition => Make_Component_Definition (Loc, Subtype_Indication => New_Occurrence_Of (RTE (RE_Address), Loc)), Expression => New_Occurrence_Of (RTE (RE_Null_Address), Loc)), Make_Component_Declaration (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Name_Subp_Id), Component_Definition => Make_Component_Definition (Loc, Subtype_Indication => New_Occurrence_Of (RTE (RE_Subprogram_Id), Loc)))))); end Build_Remote_Subprogram_Proxy_Type; -------------------- -- Build_Stub_Tag -- -------------------- function Build_Stub_Tag (Loc : Source_Ptr; RACW_Type : Entity_Id) return Node_Id is Stub_Type : constant Entity_Id := Corresponding_Stub_Type (RACW_Type); begin return Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stub_Type, Loc), Attribute_Name => Name_Tag); end Build_Stub_Tag; ------------------------------------ -- Build_Subprogram_Calling_Stubs -- ------------------------------------ function Build_Subprogram_Calling_Stubs (Vis_Decl : Node_Id; Subp_Id : Node_Id; Asynchronous : Boolean; Dynamically_Asynchronous : Boolean := False; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Locator : Entity_Id := Empty; New_Name : Name_Id := No_Name) return Node_Id is Loc : constant Source_Ptr := Sloc (Vis_Decl); Decls : constant List_Id := New_List; Statements : constant List_Id := New_List; Subp_Spec : Node_Id; -- The specification of the body Controlling_Parameter : Entity_Id := Empty; Asynchronous_Expr : Node_Id := Empty; RCI_Locator : Entity_Id; Spec_To_Use : Node_Id; procedure Insert_Partition_Check (Parameter : Node_Id); -- Check that the parameter has been elaborated on the same partition -- than the controlling parameter (E.4(19)). ---------------------------- -- Insert_Partition_Check -- ---------------------------- procedure Insert_Partition_Check (Parameter : Node_Id) is Parameter_Entity : constant Entity_Id := Defining_Identifier (Parameter); begin -- The expression that will be built is of the form: -- if not Same_Partition (Parameter, Controlling_Parameter) then -- raise Constraint_Error; -- end if; -- We do not check that Parameter is in Stub_Type since such a check -- has been inserted at the point of call already (a tag check since -- we have multiple controlling operands). Append_To (Decls, Make_Raise_Constraint_Error (Loc, Condition => Make_Op_Not (Loc, Right_Opnd => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Same_Partition), Loc), Parameter_Associations => New_List ( Unchecked_Convert_To (RTE (RE_RACW_Stub_Type_Access), New_Occurrence_Of (Parameter_Entity, Loc)), Unchecked_Convert_To (RTE (RE_RACW_Stub_Type_Access), New_Occurrence_Of (Controlling_Parameter, Loc))))), Reason => CE_Partition_Check_Failed)); end Insert_Partition_Check; -- Start of processing for Build_Subprogram_Calling_Stubs begin Subp_Spec := Copy_Specification (Loc, Spec => Specification (Vis_Decl), New_Name => New_Name); if Locator = Empty then RCI_Locator := RCI_Cache; Spec_To_Use := Specification (Vis_Decl); else RCI_Locator := Locator; Spec_To_Use := Subp_Spec; end if; -- Find a controlling argument if we have a stub type. Also check -- if this subprogram can be made asynchronous. if Present (Stub_Type) and then Present (Parameter_Specifications (Spec_To_Use)) then declare Current_Parameter : Node_Id := First (Parameter_Specifications (Spec_To_Use)); begin while Present (Current_Parameter) loop if Is_RACW_Controlling_Formal (Current_Parameter, Stub_Type) then if Controlling_Parameter = Empty then Controlling_Parameter := Defining_Identifier (Current_Parameter); else Insert_Partition_Check (Current_Parameter); end if; end if; Next (Current_Parameter); end loop; end; end if; pragma Assert (No (Stub_Type) or else Present (Controlling_Parameter)); if Dynamically_Asynchronous then Asynchronous_Expr := Make_Selected_Component (Loc, Prefix => Controlling_Parameter, Selector_Name => Name_Asynchronous); end if; Specific_Build_General_Calling_Stubs (Decls => Decls, Statements => Statements, Target => Specific_Build_Stub_Target (Loc, Decls, RCI_Locator, Controlling_Parameter), Subprogram_Id => Subp_Id, Asynchronous => Asynchronous_Expr, Is_Known_Asynchronous => Asynchronous and then not Dynamically_Asynchronous, Is_Known_Non_Asynchronous => not Asynchronous and then not Dynamically_Asynchronous, Is_Function => Nkind (Spec_To_Use) = N_Function_Specification, Spec => Spec_To_Use, Stub_Type => Stub_Type, RACW_Type => RACW_Type, Nod => Vis_Decl); RCI_Calling_Stubs_Table.Set (Defining_Unit_Name (Specification (Vis_Decl)), Defining_Unit_Name (Spec_To_Use)); return Make_Subprogram_Body (Loc, Specification => Subp_Spec, Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements)); end Build_Subprogram_Calling_Stubs; ------------------------- -- Build_Subprogram_Id -- ------------------------- function Build_Subprogram_Id (Loc : Source_Ptr; E : Entity_Id) return Node_Id is begin if Get_Subprogram_Ids (E).Str_Identifier = No_String then declare Current_Declaration : Node_Id; Current_Subp : Entity_Id; Current_Subp_Str : String_Id; Current_Subp_Number : Int := First_RCI_Subprogram_Id; pragma Warnings (Off, Current_Subp_Str); begin -- Build_Subprogram_Id is called outside of the context of -- generating calling or receiving stubs. Hence we are processing -- an 'Access attribute_reference for an RCI subprogram, for the -- purpose of obtaining a RAS value. pragma Assert (Is_Remote_Call_Interface (Scope (E)) and then (Nkind (Parent (E)) = N_Procedure_Specification or else Nkind (Parent (E)) = N_Function_Specification)); Current_Declaration := First (Visible_Declarations (Package_Specification_Of_Scope (Scope (E)))); while Present (Current_Declaration) loop if Nkind (Current_Declaration) = N_Subprogram_Declaration and then Comes_From_Source (Current_Declaration) then Current_Subp := Defining_Unit_Name (Specification ( Current_Declaration)); Assign_Subprogram_Identifier (Current_Subp, Current_Subp_Number, Current_Subp_Str); Current_Subp_Number := Current_Subp_Number + 1; end if; Next (Current_Declaration); end loop; end; end if; case Get_PCS_Name is when Name_PolyORB_DSA => return Make_String_Literal (Loc, Get_Subprogram_Id (E)); when others => return Make_Integer_Literal (Loc, Get_Subprogram_Id (E)); end case; end Build_Subprogram_Id; ------------------------ -- Copy_Specification -- ------------------------ function Copy_Specification (Loc : Source_Ptr; Spec : Node_Id; Ctrl_Type : Entity_Id := Empty; New_Name : Name_Id := No_Name) return Node_Id is Parameters : List_Id := No_List; Current_Parameter : Node_Id; Current_Identifier : Entity_Id; Current_Type : Node_Id; Name_For_New_Spec : Name_Id; New_Identifier : Entity_Id; -- Comments needed in body below ??? begin if New_Name = No_Name then pragma Assert (Nkind (Spec) = N_Function_Specification or else Nkind (Spec) = N_Procedure_Specification); Name_For_New_Spec := Chars (Defining_Unit_Name (Spec)); else Name_For_New_Spec := New_Name; end if; if Present (Parameter_Specifications (Spec)) then Parameters := New_List; Current_Parameter := First (Parameter_Specifications (Spec)); while Present (Current_Parameter) loop Current_Identifier := Defining_Identifier (Current_Parameter); Current_Type := Parameter_Type (Current_Parameter); if Nkind (Current_Type) = N_Access_Definition then if Present (Ctrl_Type) then pragma Assert (Is_Controlling_Formal (Current_Identifier)); Current_Type := Make_Access_Definition (Loc, Subtype_Mark => New_Occurrence_Of (Ctrl_Type, Loc), Null_Exclusion_Present => Null_Exclusion_Present (Current_Type)); else Current_Type := Make_Access_Definition (Loc, Subtype_Mark => New_Copy_Tree (Subtype_Mark (Current_Type)), Null_Exclusion_Present => Null_Exclusion_Present (Current_Type)); end if; else if Present (Ctrl_Type) and then Is_Controlling_Formal (Current_Identifier) then Current_Type := New_Occurrence_Of (Ctrl_Type, Loc); else Current_Type := New_Copy_Tree (Current_Type); end if; end if; New_Identifier := Make_Defining_Identifier (Loc, Chars (Current_Identifier)); Append_To (Parameters, Make_Parameter_Specification (Loc, Defining_Identifier => New_Identifier, Parameter_Type => Current_Type, In_Present => In_Present (Current_Parameter), Out_Present => Out_Present (Current_Parameter), Expression => New_Copy_Tree (Expression (Current_Parameter)))); -- For a regular formal parameter (that needs to be marshalled -- in the context of remote calls), set the Etype now, because -- marshalling processing might need it. if Is_Entity_Name (Current_Type) then Set_Etype (New_Identifier, Entity (Current_Type)); -- Current_Type is an access definition, special processing -- (not requiring etype) will occur for marshalling. else null; end if; Next (Current_Parameter); end loop; end if; case Nkind (Spec) is when N_Access_Function_Definition | N_Function_Specification => return Make_Function_Specification (Loc, Defining_Unit_Name => Make_Defining_Identifier (Loc, Chars => Name_For_New_Spec), Parameter_Specifications => Parameters, Result_Definition => New_Occurrence_Of (Entity (Result_Definition (Spec)), Loc)); when N_Access_Procedure_Definition | N_Procedure_Specification => return Make_Procedure_Specification (Loc, Defining_Unit_Name => Make_Defining_Identifier (Loc, Chars => Name_For_New_Spec), Parameter_Specifications => Parameters); when others => raise Program_Error; end case; end Copy_Specification; ----------------------------- -- Corresponding_Stub_Type -- ----------------------------- function Corresponding_Stub_Type (RACW_Type : Entity_Id) return Entity_Id is Desig : constant Entity_Id := Etype (Designated_Type (RACW_Type)); Stub_Elements : constant Stub_Structure := Stubs_Table.Get (Desig); begin return Stub_Elements.Stub_Type; end Corresponding_Stub_Type; --------------------------- -- Could_Be_Asynchronous -- --------------------------- function Could_Be_Asynchronous (Spec : Node_Id) return Boolean is Current_Parameter : Node_Id; begin if Present (Parameter_Specifications (Spec)) then Current_Parameter := First (Parameter_Specifications (Spec)); while Present (Current_Parameter) loop if Out_Present (Current_Parameter) then return False; end if; Next (Current_Parameter); end loop; end if; return True; end Could_Be_Asynchronous; --------------------------- -- Declare_Create_NVList -- --------------------------- procedure Declare_Create_NVList (Loc : Source_Ptr; NVList : Entity_Id; Decls : List_Id; Stmts : List_Id) is begin Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => NVList, Aliased_Present => False, Object_Definition => New_Occurrence_Of (RTE (RE_NVList_Ref), Loc))); Append_To (Stmts, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_NVList_Create), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (NVList, Loc)))); end Declare_Create_NVList; --------------------------------------------- -- Expand_All_Calls_Remote_Subprogram_Call -- --------------------------------------------- procedure Expand_All_Calls_Remote_Subprogram_Call (N : Node_Id) is Loc : constant Source_Ptr := Sloc (N); Called_Subprogram : constant Entity_Id := Entity (Name (N)); RCI_Package : constant Entity_Id := Scope (Called_Subprogram); RCI_Locator_Decl : Node_Id; RCI_Locator : Entity_Id; Calling_Stubs : Node_Id; E_Calling_Stubs : Entity_Id; begin E_Calling_Stubs := RCI_Calling_Stubs_Table.Get (Called_Subprogram); if E_Calling_Stubs = Empty then RCI_Locator := RCI_Locator_Table.Get (RCI_Package); -- The RCI_Locator package and calling stub are is inserted at the -- top level in the current unit, and must appear in the proper scope -- so that it is not prematurely removed by the GCC back end. declare Scop : constant Entity_Id := Cunit_Entity (Current_Sem_Unit); begin if Ekind (Scop) = E_Package_Body then Push_Scope (Spec_Entity (Scop)); elsif Ekind (Scop) = E_Subprogram_Body then Push_Scope (Corresponding_Spec (Unit_Declaration_Node (Scop))); else Push_Scope (Scop); end if; end; if RCI_Locator = Empty then RCI_Locator_Decl := RCI_Package_Locator (Loc, Package_Specification (RCI_Package)); Prepend_To (Current_Sem_Unit_Declarations, RCI_Locator_Decl); Analyze (RCI_Locator_Decl); RCI_Locator := Defining_Unit_Name (RCI_Locator_Decl); else RCI_Locator_Decl := Parent (RCI_Locator); end if; Calling_Stubs := Build_Subprogram_Calling_Stubs (Vis_Decl => Parent (Parent (Called_Subprogram)), Subp_Id => Build_Subprogram_Id (Loc, Called_Subprogram), Asynchronous => Nkind (N) = N_Procedure_Call_Statement and then Is_Asynchronous (Called_Subprogram), Locator => RCI_Locator, New_Name => New_Internal_Name ('S')); Insert_After (RCI_Locator_Decl, Calling_Stubs); Analyze (Calling_Stubs); Pop_Scope; E_Calling_Stubs := Defining_Unit_Name (Specification (Calling_Stubs)); end if; Rewrite (Name (N), New_Occurrence_Of (E_Calling_Stubs, Loc)); end Expand_All_Calls_Remote_Subprogram_Call; --------------------------------- -- Expand_Calling_Stubs_Bodies -- --------------------------------- procedure Expand_Calling_Stubs_Bodies (Unit_Node : Node_Id) is Spec : constant Node_Id := Specification (Unit_Node); begin Add_Calling_Stubs_To_Declarations (Spec); end Expand_Calling_Stubs_Bodies; ----------------------------------- -- Expand_Receiving_Stubs_Bodies -- ----------------------------------- procedure Expand_Receiving_Stubs_Bodies (Unit_Node : Node_Id) is Spec : Node_Id; Decls : List_Id; Stubs_Decls : List_Id; Stubs_Stmts : List_Id; begin if Nkind (Unit_Node) = N_Package_Declaration then Spec := Specification (Unit_Node); Decls := Private_Declarations (Spec); if No (Decls) then Decls := Visible_Declarations (Spec); end if; Push_Scope (Scope_Of_Spec (Spec)); Specific_Add_Receiving_Stubs_To_Declarations (Spec, Decls, Decls); else Spec := Package_Specification_Of_Scope (Corresponding_Spec (Unit_Node)); Decls := Declarations (Unit_Node); Push_Scope (Scope_Of_Spec (Unit_Node)); Stubs_Decls := New_List; Stubs_Stmts := New_List; Specific_Add_Receiving_Stubs_To_Declarations (Spec, Stubs_Decls, Stubs_Stmts); Insert_List_Before (First (Decls), Stubs_Decls); declare HSS_Stmts : constant List_Id := Statements (Handled_Statement_Sequence (Unit_Node)); First_HSS_Stmt : constant Node_Id := First (HSS_Stmts); begin if No (First_HSS_Stmt) then Append_List_To (HSS_Stmts, Stubs_Stmts); else Insert_List_Before (First_HSS_Stmt, Stubs_Stmts); end if; end; end if; Pop_Scope; end Expand_Receiving_Stubs_Bodies; -------------------- -- GARLIC_Support -- -------------------- package body GARLIC_Support is -- Local subprograms procedure Add_RACW_Read_Attribute (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; Body_Decls : List_Id); -- Add Read attribute for the RACW type. The declaration and attribute -- definition clauses are inserted right after the declaration of -- RACW_Type. If Body_Decls is not No_List, the subprogram body is -- appended to it (case where the RACW declaration is in the main unit). procedure Add_RACW_Write_Attribute (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; RPC_Receiver : Node_Id; Body_Decls : List_Id); -- Same as above for the Write attribute function Stream_Parameter return Node_Id; function Result return Node_Id; function Object return Node_Id renames Result; -- Functions to create occurrences of the formal parameter names of the -- 'Read and 'Write attributes. Loc : Source_Ptr; -- Shared source location used by Add_{Read,Write}_Read_Attribute and -- their ancillary subroutines (set on entry by Add_RACW_Features). procedure Add_RAS_Access_TSS (N : Node_Id); -- Add a subprogram body for RAS Access TSS ------------------------------------- -- Add_Obj_RPC_Receiver_Completion -- ------------------------------------- procedure Add_Obj_RPC_Receiver_Completion (Loc : Source_Ptr; Decls : List_Id; RPC_Receiver : Entity_Id; Stub_Elements : Stub_Structure) is begin -- The RPC receiver body should not be the completion of the -- declaration recorded in the stub structure, because then the -- occurrences of the formal parameters within the body should refer -- to the entities from the declaration, not from the completion, to -- which we do not have easy access. Instead, the RPC receiver body -- acts as its own declaration, and the RPC receiver declaration is -- completed by a renaming-as-body. Append_To (Decls, Make_Subprogram_Renaming_Declaration (Loc, Specification => Copy_Specification (Loc, Specification (Stub_Elements.RPC_Receiver_Decl)), Name => New_Occurrence_Of (RPC_Receiver, Loc))); end Add_Obj_RPC_Receiver_Completion; ----------------------- -- Add_RACW_Features -- ----------------------- procedure Add_RACW_Features (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; RPC_Receiver_Decl : Node_Id; Body_Decls : List_Id) is RPC_Receiver : Node_Id; Is_RAS : constant Boolean := not Comes_From_Source (RACW_Type); begin Loc := Sloc (RACW_Type); if Is_RAS then -- For a RAS, the RPC receiver is that of the RCI unit, not that -- of the corresponding distributed object type. We retrieve its -- address from the local proxy object. RPC_Receiver := Make_Selected_Component (Loc, Prefix => Unchecked_Convert_To (RTE (RE_RAS_Proxy_Type_Access), Object), Selector_Name => Make_Identifier (Loc, Name_Receiver)); else RPC_Receiver := Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of ( Defining_Unit_Name (Specification (RPC_Receiver_Decl)), Loc), Attribute_Name => Name_Address); end if; Add_RACW_Write_Attribute (RACW_Type, Stub_Type, Stub_Type_Access, RPC_Receiver, Body_Decls); Add_RACW_Read_Attribute (RACW_Type, Stub_Type, Stub_Type_Access, Body_Decls); end Add_RACW_Features; ----------------------------- -- Add_RACW_Read_Attribute -- ----------------------------- procedure Add_RACW_Read_Attribute (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; Body_Decls : List_Id) is Proc_Decl : Node_Id; Attr_Decl : Node_Id; Body_Node : Node_Id; Statements : constant List_Id := New_List; Decls : List_Id; Local_Statements : List_Id; Remote_Statements : List_Id; -- Various parts of the procedure Pnam : constant Entity_Id := Make_Temporary (Loc, 'R'); Asynchronous_Flag : constant Entity_Id := Asynchronous_Flags_Table.Get (RACW_Type); pragma Assert (Present (Asynchronous_Flag)); -- Prepare local identifiers Source_Partition : Entity_Id; Source_Receiver : Entity_Id; Source_Address : Entity_Id; Local_Stub : Entity_Id; Stubbed_Result : Entity_Id; -- Start of processing for Add_RACW_Read_Attribute begin Build_Stream_Procedure (Loc, RACW_Type, Body_Node, Pnam, Statements, Outp => True); Proc_Decl := Make_Subprogram_Declaration (Loc, Copy_Specification (Loc, Specification (Body_Node))); Attr_Decl := Make_Attribute_Definition_Clause (Loc, Name => New_Occurrence_Of (RACW_Type, Loc), Chars => Name_Read, Expression => New_Occurrence_Of ( Defining_Unit_Name (Specification (Proc_Decl)), Loc)); Insert_After (Declaration_Node (RACW_Type), Proc_Decl); Insert_After (Proc_Decl, Attr_Decl); if No (Body_Decls) then -- Case of processing an RACW type from another unit than the -- main one: do not generate a body. return; end if; -- Prepare local identifiers Source_Partition := Make_Temporary (Loc, 'P'); Source_Receiver := Make_Temporary (Loc, 'S'); Source_Address := Make_Temporary (Loc, 'P'); Local_Stub := Make_Temporary (Loc, 'L'); Stubbed_Result := Make_Temporary (Loc, 'S'); -- Generate object declarations Decls := New_List ( Make_Object_Declaration (Loc, Defining_Identifier => Source_Partition, Object_Definition => New_Occurrence_Of (RTE (RE_Partition_ID), Loc)), Make_Object_Declaration (Loc, Defining_Identifier => Source_Receiver, Object_Definition => New_Occurrence_Of (RTE (RE_Unsigned_64), Loc)), Make_Object_Declaration (Loc, Defining_Identifier => Source_Address, Object_Definition => New_Occurrence_Of (RTE (RE_Unsigned_64), Loc)), Make_Object_Declaration (Loc, Defining_Identifier => Local_Stub, Aliased_Present => True, Object_Definition => New_Occurrence_Of (Stub_Type, Loc)), Make_Object_Declaration (Loc, Defining_Identifier => Stubbed_Result, Object_Definition => New_Occurrence_Of (Stub_Type_Access, Loc), Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Local_Stub, Loc), Attribute_Name => Name_Unchecked_Access))); -- Read the source Partition_ID and RPC_Receiver from incoming stream Append_List_To (Statements, New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Partition_ID), Loc), Attribute_Name => Name_Read, Expressions => New_List ( Stream_Parameter, New_Occurrence_Of (Source_Partition, Loc))), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Unsigned_64), Loc), Attribute_Name => Name_Read, Expressions => New_List ( Stream_Parameter, New_Occurrence_Of (Source_Receiver, Loc))), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Unsigned_64), Loc), Attribute_Name => Name_Read, Expressions => New_List ( Stream_Parameter, New_Occurrence_Of (Source_Address, Loc))))); -- Build_Get_Unique_RP_Call needs the type of Stubbed_Result Set_Etype (Stubbed_Result, Stub_Type_Access); -- If the Address is Null_Address, then return a null object, unless -- RACW_Type is null-excluding, in which case unconditionally raise -- CONSTRAINT_ERROR instead. declare Zero_Statements : List_Id; -- Statements executed when a zero value is received begin if Can_Never_Be_Null (RACW_Type) then Zero_Statements := New_List ( Make_Raise_Constraint_Error (Loc, Reason => CE_Null_Not_Allowed)); else Zero_Statements := New_List ( Make_Assignment_Statement (Loc, Name => Result, Expression => Make_Null (Loc)), Make_Simple_Return_Statement (Loc)); end if; Append_To (Statements, Make_Implicit_If_Statement (RACW_Type, Condition => Make_Op_Eq (Loc, Left_Opnd => New_Occurrence_Of (Source_Address, Loc), Right_Opnd => Make_Integer_Literal (Loc, Uint_0)), Then_Statements => Zero_Statements)); end; -- If the RACW denotes an object created on the current partition, -- Local_Statements will be executed. The real object will be used. Local_Statements := New_List ( Make_Assignment_Statement (Loc, Name => Result, Expression => Unchecked_Convert_To (RACW_Type, OK_Convert_To (RTE (RE_Address), New_Occurrence_Of (Source_Address, Loc))))); -- If the object is located on another partition, then a stub object -- will be created with all the information needed to rebuild the -- real object at the other end. Remote_Statements := New_List ( Make_Assignment_Statement (Loc, Name => Make_Selected_Component (Loc, Prefix => Stubbed_Result, Selector_Name => Name_Origin), Expression => New_Occurrence_Of (Source_Partition, Loc)), Make_Assignment_Statement (Loc, Name => Make_Selected_Component (Loc, Prefix => Stubbed_Result, Selector_Name => Name_Receiver), Expression => New_Occurrence_Of (Source_Receiver, Loc)), Make_Assignment_Statement (Loc, Name => Make_Selected_Component (Loc, Prefix => Stubbed_Result, Selector_Name => Name_Addr), Expression => New_Occurrence_Of (Source_Address, Loc))); Append_To (Remote_Statements, Make_Assignment_Statement (Loc, Name => Make_Selected_Component (Loc, Prefix => Stubbed_Result, Selector_Name => Name_Asynchronous), Expression => New_Occurrence_Of (Asynchronous_Flag, Loc))); Append_List_To (Remote_Statements, Build_Get_Unique_RP_Call (Loc, Stubbed_Result, Stub_Type)); -- ??? Issue with asynchronous calls here: the Asynchronous flag is -- set on the stub type if, and only if, the RACW type has a pragma -- Asynchronous. This is incorrect for RACWs that implement RAS -- types, because in that case the /designated subprogram/ (not the -- type) might be asynchronous, and that causes the stub to need to -- be asynchronous too. A solution is to transport a RAS as a struct -- containing a RACW and an asynchronous flag, and to properly alter -- the Asynchronous component in the stub type in the RAS's Input -- TSS. Append_To (Remote_Statements, Make_Assignment_Statement (Loc, Name => Result, Expression => Unchecked_Convert_To (RACW_Type, New_Occurrence_Of (Stubbed_Result, Loc)))); -- Distinguish between the local and remote cases, and execute the -- appropriate piece of code. Append_To (Statements, Make_Implicit_If_Statement (RACW_Type, Condition => Make_Op_Eq (Loc, Left_Opnd => Make_Function_Call (Loc, Name => New_Occurrence_Of ( RTE (RE_Get_Local_Partition_Id), Loc)), Right_Opnd => New_Occurrence_Of (Source_Partition, Loc)), Then_Statements => Local_Statements, Else_Statements => Remote_Statements)); Set_Declarations (Body_Node, Decls); Append_To (Body_Decls, Body_Node); end Add_RACW_Read_Attribute; ------------------------------ -- Add_RACW_Write_Attribute -- ------------------------------ procedure Add_RACW_Write_Attribute (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; RPC_Receiver : Node_Id; Body_Decls : List_Id) is Body_Node : Node_Id; Proc_Decl : Node_Id; Attr_Decl : Node_Id; Statements : constant List_Id := New_List; Local_Statements : List_Id; Remote_Statements : List_Id; Null_Statements : List_Id; Pnam : constant Entity_Id := Make_Temporary (Loc, 'R'); begin Build_Stream_Procedure (Loc, RACW_Type, Body_Node, Pnam, Statements, Outp => False); Proc_Decl := Make_Subprogram_Declaration (Loc, Copy_Specification (Loc, Specification (Body_Node))); Attr_Decl := Make_Attribute_Definition_Clause (Loc, Name => New_Occurrence_Of (RACW_Type, Loc), Chars => Name_Write, Expression => New_Occurrence_Of ( Defining_Unit_Name (Specification (Proc_Decl)), Loc)); Insert_After (Declaration_Node (RACW_Type), Proc_Decl); Insert_After (Proc_Decl, Attr_Decl); if No (Body_Decls) then return; end if; -- Build the code fragment corresponding to the marshalling of a -- local object. Local_Statements := New_List ( Pack_Entity_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => RTE (RE_Get_Local_Partition_Id)), Pack_Node_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => OK_Convert_To (RTE (RE_Unsigned_64), RPC_Receiver), Etyp => RTE (RE_Unsigned_64)), Pack_Node_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => OK_Convert_To (RTE (RE_Unsigned_64), Make_Attribute_Reference (Loc, Prefix => Make_Explicit_Dereference (Loc, Prefix => Object), Attribute_Name => Name_Address)), Etyp => RTE (RE_Unsigned_64))); -- Build the code fragment corresponding to the marshalling of -- a remote object. Remote_Statements := New_List ( Pack_Node_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => Make_Selected_Component (Loc, Prefix => Unchecked_Convert_To (Stub_Type_Access, Object), Selector_Name => Make_Identifier (Loc, Name_Origin)), Etyp => RTE (RE_Partition_ID)), Pack_Node_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => Make_Selected_Component (Loc, Prefix => Unchecked_Convert_To (Stub_Type_Access, Object), Selector_Name => Make_Identifier (Loc, Name_Receiver)), Etyp => RTE (RE_Unsigned_64)), Pack_Node_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => Make_Selected_Component (Loc, Prefix => Unchecked_Convert_To (Stub_Type_Access, Object), Selector_Name => Make_Identifier (Loc, Name_Addr)), Etyp => RTE (RE_Unsigned_64))); -- Build code fragment corresponding to marshalling of a null object Null_Statements := New_List ( Pack_Entity_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => RTE (RE_Get_Local_Partition_Id)), Pack_Node_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => OK_Convert_To (RTE (RE_Unsigned_64), RPC_Receiver), Etyp => RTE (RE_Unsigned_64)), Pack_Node_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => Make_Integer_Literal (Loc, Uint_0), Etyp => RTE (RE_Unsigned_64))); Append_To (Statements, Make_Implicit_If_Statement (RACW_Type, Condition => Make_Op_Eq (Loc, Left_Opnd => Object, Right_Opnd => Make_Null (Loc)), Then_Statements => Null_Statements, Elsif_Parts => New_List ( Make_Elsif_Part (Loc, Condition => Make_Op_Eq (Loc, Left_Opnd => Make_Attribute_Reference (Loc, Prefix => Object, Attribute_Name => Name_Tag), Right_Opnd => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stub_Type, Loc), Attribute_Name => Name_Tag)), Then_Statements => Remote_Statements)), Else_Statements => Local_Statements)); Append_To (Body_Decls, Body_Node); end Add_RACW_Write_Attribute; ------------------------ -- Add_RAS_Access_TSS -- ------------------------ procedure Add_RAS_Access_TSS (N : Node_Id) is Loc : constant Source_Ptr := Sloc (N); Ras_Type : constant Entity_Id := Defining_Identifier (N); Fat_Type : constant Entity_Id := Equivalent_Type (Ras_Type); -- Ras_Type is the access to subprogram type while Fat_Type is the -- corresponding record type. RACW_Type : constant Entity_Id := Underlying_RACW_Type (Ras_Type); Desig : constant Entity_Id := Etype (Designated_Type (RACW_Type)); Stub_Elements : constant Stub_Structure := Stubs_Table.Get (Desig); pragma Assert (Stub_Elements /= Empty_Stub_Structure); Proc : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Make_TSS_Name (Ras_Type, TSS_RAS_Access)); Proc_Spec : Node_Id; -- Formal parameters Package_Name : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Name_P); -- Target package Subp_Id : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Name_S); -- Target subprogram Asynch_P : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Name_Asynchronous); -- Is the procedure to which the 'Access applies asynchronous? All_Calls_Remote : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Name_All_Calls_Remote); -- True if an All_Calls_Remote pragma applies to the RCI unit -- that contains the subprogram. -- Common local variables Proc_Decls : List_Id; Proc_Statements : List_Id; Origin : constant Entity_Id := Make_Temporary (Loc, 'P'); -- Additional local variables for the local case Proxy_Addr : constant Entity_Id := Make_Temporary (Loc, 'P'); -- Additional local variables for the remote case Local_Stub : constant Entity_Id := Make_Temporary (Loc, 'L'); Stub_Ptr : constant Entity_Id := Make_Temporary (Loc, 'S'); function Set_Field (Field_Name : Name_Id; Value : Node_Id) return Node_Id; -- Construct an assignment that sets the named component in the -- returned record --------------- -- Set_Field -- --------------- function Set_Field (Field_Name : Name_Id; Value : Node_Id) return Node_Id is begin return Make_Assignment_Statement (Loc, Name => Make_Selected_Component (Loc, Prefix => Stub_Ptr, Selector_Name => Field_Name), Expression => Value); end Set_Field; -- Start of processing for Add_RAS_Access_TSS begin Proc_Decls := New_List ( -- Common declarations Make_Object_Declaration (Loc, Defining_Identifier => Origin, Constant_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Partition_ID), Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Get_Active_Partition_Id), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Package_Name, Loc)))), -- Declaration use only in the local case: proxy address Make_Object_Declaration (Loc, Defining_Identifier => Proxy_Addr, Object_Definition => New_Occurrence_Of (RTE (RE_Unsigned_64), Loc)), -- Declarations used only in the remote case: stub object and -- stub pointer. Make_Object_Declaration (Loc, Defining_Identifier => Local_Stub, Aliased_Present => True, Object_Definition => New_Occurrence_Of (Stub_Elements.Stub_Type, Loc)), Make_Object_Declaration (Loc, Defining_Identifier => Stub_Ptr, Object_Definition => New_Occurrence_Of (Stub_Elements.Stub_Type_Access, Loc), Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Local_Stub, Loc), Attribute_Name => Name_Unchecked_Access))); Set_Etype (Stub_Ptr, Stub_Elements.Stub_Type_Access); -- Build_Get_Unique_RP_Call needs above information -- Note: Here we assume that the Fat_Type is a record -- containing just a pointer to a proxy or stub object. Proc_Statements := New_List ( -- Generate: -- Get_RAS_Info (Pkg, Subp, PA); -- if Origin = Local_Partition_Id -- and then not All_Calls_Remote -- then -- return Fat_Type!(PA); -- end if; Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Get_RAS_Info), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Package_Name, Loc), New_Occurrence_Of (Subp_Id, Loc), New_Occurrence_Of (Proxy_Addr, Loc))), Make_Implicit_If_Statement (N, Condition => Make_And_Then (Loc, Left_Opnd => Make_Op_Eq (Loc, Left_Opnd => New_Occurrence_Of (Origin, Loc), Right_Opnd => Make_Function_Call (Loc, New_Occurrence_Of ( RTE (RE_Get_Local_Partition_Id), Loc))), Right_Opnd => Make_Op_Not (Loc, New_Occurrence_Of (All_Calls_Remote, Loc))), Then_Statements => New_List ( Make_Simple_Return_Statement (Loc, Unchecked_Convert_To (Fat_Type, OK_Convert_To (RTE (RE_Address), New_Occurrence_Of (Proxy_Addr, Loc)))))), Set_Field (Name_Origin, New_Occurrence_Of (Origin, Loc)), Set_Field (Name_Receiver, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Get_RCI_Package_Receiver), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Package_Name, Loc)))), Set_Field (Name_Addr, New_Occurrence_Of (Proxy_Addr, Loc)), -- E.4.1(9) A remote call is asynchronous if it is a call to -- a procedure or a call through a value of an access-to-procedure -- type to which a pragma Asynchronous applies. -- Asynch_P is true when the procedure is asynchronous; -- Asynch_T is true when the type is asynchronous. Set_Field (Name_Asynchronous, Make_Or_Else (Loc, New_Occurrence_Of (Asynch_P, Loc), New_Occurrence_Of (Boolean_Literals ( Is_Asynchronous (Ras_Type)), Loc)))); Append_List_To (Proc_Statements, Build_Get_Unique_RP_Call (Loc, Stub_Ptr, Stub_Elements.Stub_Type)); -- Return the newly created value Append_To (Proc_Statements, Make_Simple_Return_Statement (Loc, Expression => Unchecked_Convert_To (Fat_Type, New_Occurrence_Of (Stub_Ptr, Loc)))); Proc_Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Proc, Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Package_Name, Parameter_Type => New_Occurrence_Of (Standard_String, Loc)), Make_Parameter_Specification (Loc, Defining_Identifier => Subp_Id, Parameter_Type => New_Occurrence_Of (RTE (RE_Subprogram_Id), Loc)), Make_Parameter_Specification (Loc, Defining_Identifier => Asynch_P, Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc)), Make_Parameter_Specification (Loc, Defining_Identifier => All_Calls_Remote, Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc))), Result_Definition => New_Occurrence_Of (Fat_Type, Loc)); -- Set the kind and return type of the function to prevent -- ambiguities between Ras_Type and Fat_Type in subsequent analysis. Set_Ekind (Proc, E_Function); Set_Etype (Proc, Fat_Type); Discard_Node ( Make_Subprogram_Body (Loc, Specification => Proc_Spec, Declarations => Proc_Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Proc_Statements))); Set_TSS (Fat_Type, Proc); end Add_RAS_Access_TSS; ----------------------- -- Add_RAST_Features -- ----------------------- procedure Add_RAST_Features (Vis_Decl : Node_Id; RAS_Type : Entity_Id) is pragma Unreferenced (RAS_Type); begin Add_RAS_Access_TSS (Vis_Decl); end Add_RAST_Features; ----------------------------------------- -- Add_Receiving_Stubs_To_Declarations -- ----------------------------------------- procedure Add_Receiving_Stubs_To_Declarations (Pkg_Spec : Node_Id; Decls : List_Id; Stmts : List_Id) is Loc : constant Source_Ptr := Sloc (Pkg_Spec); Request_Parameter : Node_Id; Pkg_RPC_Receiver : constant Entity_Id := Make_Temporary (Loc, 'H'); Pkg_RPC_Receiver_Statements : List_Id; Pkg_RPC_Receiver_Cases : constant List_Id := New_List; Pkg_RPC_Receiver_Body : Node_Id; -- A Pkg_RPC_Receiver is built to decode the request Lookup_RAS : Node_Id; Lookup_RAS_Info : constant Entity_Id := Make_Temporary (Loc, 'R'); -- A remote subprogram is created to allow peers to look up RAS -- information using subprogram ids. Subp_Id : Entity_Id; Subp_Index : Entity_Id; -- Subprogram_Id as read from the incoming stream Current_Subp_Number : Int := First_RCI_Subprogram_Id; Current_Stubs : Node_Id; Subp_Info_Array : constant Entity_Id := Make_Temporary (Loc, 'I'); Subp_Info_List : constant List_Id := New_List; Register_Pkg_Actuals : constant List_Id := New_List; All_Calls_Remote_E : Entity_Id; Proxy_Object_Addr : Entity_Id; procedure Append_Stubs_To (RPC_Receiver_Cases : List_Id; Stubs : Node_Id; Subprogram_Number : Int); -- Add one case to the specified RPC receiver case list -- associating Subprogram_Number with the subprogram declared -- by Declaration, for which we have receiving stubs in Stubs. procedure Visit_Subprogram (Decl : Node_Id); -- Generate receiving stub for one remote subprogram --------------------- -- Append_Stubs_To -- --------------------- procedure Append_Stubs_To (RPC_Receiver_Cases : List_Id; Stubs : Node_Id; Subprogram_Number : Int) is begin Append_To (RPC_Receiver_Cases, Make_Case_Statement_Alternative (Loc, Discrete_Choices => New_List (Make_Integer_Literal (Loc, Subprogram_Number)), Statements => New_List ( Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (Defining_Entity (Stubs), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Request_Parameter, Loc)))))); end Append_Stubs_To; ---------------------- -- Visit_Subprogram -- ---------------------- procedure Visit_Subprogram (Decl : Node_Id) is Loc : constant Source_Ptr := Sloc (Decl); Spec : constant Node_Id := Specification (Decl); Subp_Def : constant Entity_Id := Defining_Unit_Name (Spec); Subp_Val : String_Id; pragma Warnings (Off, Subp_Val); begin -- Disable expansion of stubs if serious errors have been -- diagnosed, because otherwise some illegal remote subprogram -- declarations could cause cascaded errors in stubs. if Serious_Errors_Detected /= 0 then return; end if; -- Build receiving stub Current_Stubs := Build_Subprogram_Receiving_Stubs (Vis_Decl => Decl, Asynchronous => Nkind (Spec) = N_Procedure_Specification and then Is_Asynchronous (Subp_Def)); Append_To (Decls, Current_Stubs); Analyze (Current_Stubs); -- Build RAS proxy Add_RAS_Proxy_And_Analyze (Decls, Vis_Decl => Decl, All_Calls_Remote_E => All_Calls_Remote_E, Proxy_Object_Addr => Proxy_Object_Addr); -- Compute distribution identifier Assign_Subprogram_Identifier (Subp_Def, Current_Subp_Number, Subp_Val); pragma Assert (Current_Subp_Number = Get_Subprogram_Id (Subp_Def)); -- Add subprogram descriptor (RCI_Subp_Info) to the subprograms -- table for this receiver. This aggregate must be kept consistent -- with the declaration of RCI_Subp_Info in -- System.Partition_Interface. Append_To (Subp_Info_List, Make_Component_Association (Loc, Choices => New_List ( Make_Integer_Literal (Loc, Current_Subp_Number)), Expression => Make_Aggregate (Loc, Component_Associations => New_List ( -- Addr => Make_Component_Association (Loc, Choices => New_List (Make_Identifier (Loc, Name_Addr)), Expression => New_Occurrence_Of (Proxy_Object_Addr, Loc)))))); Append_Stubs_To (Pkg_RPC_Receiver_Cases, Stubs => Current_Stubs, Subprogram_Number => Current_Subp_Number); Current_Subp_Number := Current_Subp_Number + 1; end Visit_Subprogram; procedure Visit_Spec is new Build_Package_Stubs (Visit_Subprogram); -- Start of processing for Add_Receiving_Stubs_To_Declarations begin -- Building receiving stubs consist in several operations: -- - a package RPC receiver must be built. This subprogram -- will get a Subprogram_Id from the incoming stream -- and will dispatch the call to the right subprogram; -- - a receiving stub for each subprogram visible in the package -- spec. This stub will read all the parameters from the stream, -- and put the result as well as the exception occurrence in the -- output stream; -- - a dummy package with an empty spec and a body made of an -- elaboration part, whose job is to register the receiving -- part of this RCI package on the name server. This is done -- by calling System.Partition_Interface.Register_Receiving_Stub. Build_RPC_Receiver_Body ( RPC_Receiver => Pkg_RPC_Receiver, Request => Request_Parameter, Subp_Id => Subp_Id, Subp_Index => Subp_Index, Stmts => Pkg_RPC_Receiver_Statements, Decl => Pkg_RPC_Receiver_Body); pragma Assert (Subp_Id = Subp_Index); -- A null subp_id denotes a call through a RAS, in which case the -- next Uint_64 element in the stream is the address of the local -- proxy object, from which we can retrieve the actual subprogram id. Append_To (Pkg_RPC_Receiver_Statements, Make_Implicit_If_Statement (Pkg_Spec, Condition => Make_Op_Eq (Loc, New_Occurrence_Of (Subp_Id, Loc), Make_Integer_Literal (Loc, 0)), Then_Statements => New_List ( Make_Assignment_Statement (Loc, Name => New_Occurrence_Of (Subp_Id, Loc), Expression => Make_Selected_Component (Loc, Prefix => Unchecked_Convert_To (RTE (RE_RAS_Proxy_Type_Access), OK_Convert_To (RTE (RE_Address), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Unsigned_64), Loc), Attribute_Name => Name_Input, Expressions => New_List ( Make_Selected_Component (Loc, Prefix => Request_Parameter, Selector_Name => Name_Params))))), Selector_Name => Make_Identifier (Loc, Name_Subp_Id)))))); -- Build a subprogram for RAS information lookups Lookup_RAS := Make_Subprogram_Declaration (Loc, Specification => Make_Function_Specification (Loc, Defining_Unit_Name => Lookup_RAS_Info, Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Name_Subp_Id), In_Present => True, Parameter_Type => New_Occurrence_Of (RTE (RE_Subprogram_Id), Loc))), Result_Definition => New_Occurrence_Of (RTE (RE_Unsigned_64), Loc))); Append_To (Decls, Lookup_RAS); Analyze (Lookup_RAS); Current_Stubs := Build_Subprogram_Receiving_Stubs (Vis_Decl => Lookup_RAS, Asynchronous => False); Append_To (Decls, Current_Stubs); Analyze (Current_Stubs); Append_Stubs_To (Pkg_RPC_Receiver_Cases, Stubs => Current_Stubs, Subprogram_Number => 1); -- For each subprogram, the receiving stub will be built and a -- case statement will be made on the Subprogram_Id to dispatch -- to the right subprogram. All_Calls_Remote_E := Boolean_Literals (Has_All_Calls_Remote (Defining_Entity (Pkg_Spec))); Overload_Counter_Table.Reset; Visit_Spec (Pkg_Spec); -- If we receive an invalid Subprogram_Id, it is best to do nothing -- rather than raising an exception since we do not want someone -- to crash a remote partition by sending invalid subprogram ids. -- This is consistent with the other parts of the case statement -- since even in presence of incorrect parameters in the stream, -- every exception will be caught and (if the subprogram is not an -- APC) put into the result stream and sent away. Append_To (Pkg_RPC_Receiver_Cases, Make_Case_Statement_Alternative (Loc, Discrete_Choices => New_List (Make_Others_Choice (Loc)), Statements => New_List (Make_Null_Statement (Loc)))); Append_To (Pkg_RPC_Receiver_Statements, Make_Case_Statement (Loc, Expression => New_Occurrence_Of (Subp_Id, Loc), Alternatives => Pkg_RPC_Receiver_Cases)); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Subp_Info_Array, Constant_Present => True, Aliased_Present => True, Object_Definition => Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (RTE (RE_RCI_Subp_Info_Array), Loc), Constraint => Make_Index_Or_Discriminant_Constraint (Loc, New_List ( Make_Range (Loc, Low_Bound => Make_Integer_Literal (Loc, First_RCI_Subprogram_Id), High_Bound => Make_Integer_Literal (Loc, Intval => First_RCI_Subprogram_Id + List_Length (Subp_Info_List) - 1))))))); -- For a degenerate RCI with no visible subprograms, Subp_Info_List -- has zero length, and the declaration is for an empty array, in -- which case no initialization aggregate must be generated. if Present (First (Subp_Info_List)) then Set_Expression (Last (Decls), Make_Aggregate (Loc, Component_Associations => Subp_Info_List)); -- No initialization provided: remove CONSTANT so that the -- declaration is not an incomplete deferred constant. else Set_Constant_Present (Last (Decls), False); end if; Analyze (Last (Decls)); declare Subp_Info_Addr : Node_Id; -- Return statement for Lookup_RAS_Info: address of the subprogram -- information record for the requested subprogram id. begin if Present (First (Subp_Info_List)) then Subp_Info_Addr := Make_Selected_Component (Loc, Prefix => Make_Indexed_Component (Loc, Prefix => New_Occurrence_Of (Subp_Info_Array, Loc), Expressions => New_List ( Convert_To (Standard_Integer, Make_Identifier (Loc, Name_Subp_Id)))), Selector_Name => Make_Identifier (Loc, Name_Addr)); -- Case of no visible subprogram: just raise Constraint_Error, we -- know for sure we got junk from a remote partition. else Subp_Info_Addr := Make_Raise_Constraint_Error (Loc, Reason => CE_Range_Check_Failed); Set_Etype (Subp_Info_Addr, RTE (RE_Unsigned_64)); end if; Append_To (Decls, Make_Subprogram_Body (Loc, Specification => Copy_Specification (Loc, Parent (Lookup_RAS_Info)), Declarations => No_List, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => New_List ( Make_Simple_Return_Statement (Loc, Expression => OK_Convert_To (RTE (RE_Unsigned_64), Subp_Info_Addr)))))); end; Analyze (Last (Decls)); Append_To (Decls, Pkg_RPC_Receiver_Body); Analyze (Last (Decls)); -- Name Append_To (Register_Pkg_Actuals, Make_String_Literal (Loc, Strval => Fully_Qualified_Name_String (Defining_Entity (Pkg_Spec), Append_NUL => False))); -- Receiver Append_To (Register_Pkg_Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Pkg_RPC_Receiver, Loc), Attribute_Name => Name_Unrestricted_Access)); -- Version Append_To (Register_Pkg_Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Defining_Entity (Pkg_Spec), Loc), Attribute_Name => Name_Version)); -- Subp_Info Append_To (Register_Pkg_Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Subp_Info_Array, Loc), Attribute_Name => Name_Address)); -- Subp_Info_Len Append_To (Register_Pkg_Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Subp_Info_Array, Loc), Attribute_Name => Name_Length)); -- Generate the call Append_To (Stmts, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Register_Receiving_Stub), Loc), Parameter_Associations => Register_Pkg_Actuals)); Analyze (Last (Stmts)); end Add_Receiving_Stubs_To_Declarations; --------------------------------- -- Build_General_Calling_Stubs -- --------------------------------- procedure Build_General_Calling_Stubs (Decls : List_Id; Statements : List_Id; Target_Partition : Entity_Id; Target_RPC_Receiver : Node_Id; Subprogram_Id : Node_Id; Asynchronous : Node_Id := Empty; Is_Known_Asynchronous : Boolean := False; Is_Known_Non_Asynchronous : Boolean := False; Is_Function : Boolean; Spec : Node_Id; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Nod : Node_Id) is Loc : constant Source_Ptr := Sloc (Nod); Stream_Parameter : Node_Id; -- Name of the stream used to transmit parameters to the remote -- package. Result_Parameter : Node_Id; -- Name of the result parameter (in non-APC cases) which get the -- result of the remote subprogram. Exception_Return_Parameter : Node_Id; -- Name of the parameter which will hold the exception sent by the -- remote subprogram. Current_Parameter : Node_Id; -- Current parameter being handled Ordered_Parameters_List : constant List_Id := Build_Ordered_Parameters_List (Spec); Asynchronous_Statements : List_Id := No_List; Non_Asynchronous_Statements : List_Id := No_List; -- Statements specifics to the Asynchronous/Non-Asynchronous cases Extra_Formal_Statements : constant List_Id := New_List; -- List of statements for extra formal parameters. It will appear -- after the regular statements for writing out parameters. pragma Unreferenced (RACW_Type); -- Used only for the PolyORB case begin -- The general form of a calling stub for a given subprogram is: -- procedure X (...) is P : constant Partition_ID := -- RCI_Cache.Get_Active_Partition_ID; Stream, Result : aliased -- System.RPC.Params_Stream_Type (0); begin -- Put_Package_RPC_Receiver_In_Stream; (the package RPC receiver -- comes from RCI_Cache.Get_RCI_Package_Receiver) -- Put_Subprogram_Id_In_Stream; Put_Parameters_In_Stream; Do_RPC -- (Stream, Result); Read_Exception_Occurrence_From_Result; -- Raise_It; -- Read_Out_Parameters_And_Function_Return_From_Stream; end X; -- There are some variations: Do_APC is called for an asynchronous -- procedure and the part after the call is completely ommitted as -- well as the declaration of Result. For a function call, 'Input is -- always used to read the result even if it is constrained. Stream_Parameter := Make_Temporary (Loc, 'S'); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Stream_Parameter, Aliased_Present => True, Object_Definition => Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (RTE (RE_Params_Stream_Type), Loc), Constraint => Make_Index_Or_Discriminant_Constraint (Loc, Constraints => New_List (Make_Integer_Literal (Loc, 0)))))); if not Is_Known_Asynchronous then Result_Parameter := Make_Temporary (Loc, 'R'); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Result_Parameter, Aliased_Present => True, Object_Definition => Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (RTE (RE_Params_Stream_Type), Loc), Constraint => Make_Index_Or_Discriminant_Constraint (Loc, Constraints => New_List (Make_Integer_Literal (Loc, 0)))))); Exception_Return_Parameter := Make_Temporary (Loc, 'E'); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Exception_Return_Parameter, Object_Definition => New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc))); else Result_Parameter := Empty; Exception_Return_Parameter := Empty; end if; -- Put first the RPC receiver corresponding to the remote package Append_To (Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Unsigned_64), Loc), Attribute_Name => Name_Write, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stream_Parameter, Loc), Attribute_Name => Name_Access), Target_RPC_Receiver))); -- Then put the Subprogram_Id of the subprogram we want to call in -- the stream. Append_To (Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Subprogram_Id), Loc), Attribute_Name => Name_Write, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stream_Parameter, Loc), Attribute_Name => Name_Access), Subprogram_Id))); Current_Parameter := First (Ordered_Parameters_List); while Present (Current_Parameter) loop declare Typ : constant Node_Id := Parameter_Type (Current_Parameter); Etyp : Entity_Id; Constrained : Boolean; Value : Node_Id; Extra_Parameter : Entity_Id; begin if Is_RACW_Controlling_Formal (Current_Parameter, Stub_Type) then -- In the case of a controlling formal argument, we marshall -- its addr field rather than the local stub. Append_To (Statements, Pack_Node_Into_Stream (Loc, Stream => Stream_Parameter, Object => Make_Selected_Component (Loc, Prefix => Defining_Identifier (Current_Parameter), Selector_Name => Name_Addr), Etyp => RTE (RE_Unsigned_64))); else Value := New_Occurrence_Of (Defining_Identifier (Current_Parameter), Loc); -- Access type parameters are transmitted as in out -- parameters. However, a dereference is needed so that -- we marshall the designated object. if Nkind (Typ) = N_Access_Definition then Value := Make_Explicit_Dereference (Loc, Value); Etyp := Etype (Subtype_Mark (Typ)); else Etyp := Etype (Typ); end if; Constrained := not Transmit_As_Unconstrained (Etyp); -- Any parameter but unconstrained out parameters are -- transmitted to the peer. if In_Present (Current_Parameter) or else not Out_Present (Current_Parameter) or else not Constrained then Append_To (Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Etyp, Loc), Attribute_Name => Output_From_Constrained (Constrained), Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stream_Parameter, Loc), Attribute_Name => Name_Access), Value))); end if; end if; -- If the current parameter has a dynamic constrained status, -- then this status is transmitted as well. -- This should be done for accessibility as well ??? if Nkind (Typ) /= N_Access_Definition and then Need_Extra_Constrained (Current_Parameter) then -- In this block, we do not use the extra formal that has -- been created because it does not exist at the time of -- expansion when building calling stubs for remote access -- to subprogram types. We create an extra variable of this -- type and push it in the stream after the regular -- parameters. Extra_Parameter := Make_Temporary (Loc, 'P'); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Extra_Parameter, Constant_Present => True, Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc), Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of ( Defining_Identifier (Current_Parameter), Loc), Attribute_Name => Name_Constrained))); Append_To (Extra_Formal_Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Standard_Boolean, Loc), Attribute_Name => Name_Write, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stream_Parameter, Loc), Attribute_Name => Name_Access), New_Occurrence_Of (Extra_Parameter, Loc)))); end if; Next (Current_Parameter); end; end loop; -- Append the formal statements list to the statements Append_List_To (Statements, Extra_Formal_Statements); if not Is_Known_Non_Asynchronous then -- Build the call to System.RPC.Do_APC Asynchronous_Statements := New_List ( Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Do_Apc), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Target_Partition, Loc), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stream_Parameter, Loc), Attribute_Name => Name_Access)))); else Asynchronous_Statements := No_List; end if; if not Is_Known_Asynchronous then -- Build the call to System.RPC.Do_RPC Non_Asynchronous_Statements := New_List ( Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Do_Rpc), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Target_Partition, Loc), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stream_Parameter, Loc), Attribute_Name => Name_Access), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Result_Parameter, Loc), Attribute_Name => Name_Access)))); -- Read the exception occurrence from the result stream and -- reraise it. It does no harm if this is a Null_Occurrence since -- this does nothing. Append_To (Non_Asynchronous_Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc), Attribute_Name => Name_Read, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Result_Parameter, Loc), Attribute_Name => Name_Access), New_Occurrence_Of (Exception_Return_Parameter, Loc)))); Append_To (Non_Asynchronous_Statements, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Reraise_Occurrence), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Exception_Return_Parameter, Loc)))); if Is_Function then -- If this is a function call, then read the value and return -- it. The return value is written/read using 'Output/'Input. Append_To (Non_Asynchronous_Statements, Make_Tag_Check (Loc, Make_Simple_Return_Statement (Loc, Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of ( Etype (Result_Definition (Spec)), Loc), Attribute_Name => Name_Input, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Result_Parameter, Loc), Attribute_Name => Name_Access)))))); else -- Loop around parameters and assign out (or in out) -- parameters. In the case of RACW, controlling arguments -- cannot possibly have changed since they are remote, so -- we do not read them from the stream. Current_Parameter := First (Ordered_Parameters_List); while Present (Current_Parameter) loop declare Typ : constant Node_Id := Parameter_Type (Current_Parameter); Etyp : Entity_Id; Value : Node_Id; begin Value := New_Occurrence_Of (Defining_Identifier (Current_Parameter), Loc); if Nkind (Typ) = N_Access_Definition then Value := Make_Explicit_Dereference (Loc, Value); Etyp := Etype (Subtype_Mark (Typ)); else Etyp := Etype (Typ); end if; if (Out_Present (Current_Parameter) or else Nkind (Typ) = N_Access_Definition) and then Etyp /= Stub_Type then Append_To (Non_Asynchronous_Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Etyp, Loc), Attribute_Name => Name_Read, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Result_Parameter, Loc), Attribute_Name => Name_Access), Value))); end if; end; Next (Current_Parameter); end loop; end if; end if; if Is_Known_Asynchronous then Append_List_To (Statements, Asynchronous_Statements); elsif Is_Known_Non_Asynchronous then Append_List_To (Statements, Non_Asynchronous_Statements); else pragma Assert (Present (Asynchronous)); Prepend_To (Asynchronous_Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Standard_Boolean, Loc), Attribute_Name => Name_Write, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stream_Parameter, Loc), Attribute_Name => Name_Access), New_Occurrence_Of (Standard_True, Loc)))); Prepend_To (Non_Asynchronous_Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Standard_Boolean, Loc), Attribute_Name => Name_Write, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stream_Parameter, Loc), Attribute_Name => Name_Access), New_Occurrence_Of (Standard_False, Loc)))); Append_To (Statements, Make_Implicit_If_Statement (Nod, Condition => Asynchronous, Then_Statements => Asynchronous_Statements, Else_Statements => Non_Asynchronous_Statements)); end if; end Build_General_Calling_Stubs; ----------------------------- -- Build_RPC_Receiver_Body -- ----------------------------- procedure Build_RPC_Receiver_Body (RPC_Receiver : Entity_Id; Request : out Entity_Id; Subp_Id : out Entity_Id; Subp_Index : out Entity_Id; Stmts : out List_Id; Decl : out Node_Id) is Loc : constant Source_Ptr := Sloc (RPC_Receiver); RPC_Receiver_Spec : Node_Id; RPC_Receiver_Decls : List_Id; begin Request := Make_Defining_Identifier (Loc, Name_R); RPC_Receiver_Spec := Build_RPC_Receiver_Specification (RPC_Receiver => RPC_Receiver, Request_Parameter => Request); Subp_Id := Make_Temporary (Loc, 'P'); Subp_Index := Subp_Id; -- Subp_Id may not be a constant, because in the case of the RPC -- receiver for an RCI package, when a call is received from a RAS -- dereference, it will be assigned during subsequent processing. RPC_Receiver_Decls := New_List ( Make_Object_Declaration (Loc, Defining_Identifier => Subp_Id, Object_Definition => New_Occurrence_Of (RTE (RE_Subprogram_Id), Loc), Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Subprogram_Id), Loc), Attribute_Name => Name_Input, Expressions => New_List ( Make_Selected_Component (Loc, Prefix => Request, Selector_Name => Name_Params))))); Stmts := New_List; Decl := Make_Subprogram_Body (Loc, Specification => RPC_Receiver_Spec, Declarations => RPC_Receiver_Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)); end Build_RPC_Receiver_Body; ----------------------- -- Build_Stub_Target -- ----------------------- function Build_Stub_Target (Loc : Source_Ptr; Decls : List_Id; RCI_Locator : Entity_Id; Controlling_Parameter : Entity_Id) return RPC_Target is Target_Info : RPC_Target (PCS_Kind => Name_GARLIC_DSA); begin Target_Info.Partition := Make_Temporary (Loc, 'P'); if Present (Controlling_Parameter) then Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Target_Info.Partition, Constant_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Partition_ID), Loc), Expression => Make_Selected_Component (Loc, Prefix => Controlling_Parameter, Selector_Name => Name_Origin))); Target_Info.RPC_Receiver := Make_Selected_Component (Loc, Prefix => Controlling_Parameter, Selector_Name => Name_Receiver); else Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Target_Info.Partition, Constant_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Partition_ID), Loc), Expression => Make_Function_Call (Loc, Name => Make_Selected_Component (Loc, Prefix => Make_Identifier (Loc, Chars (RCI_Locator)), Selector_Name => Make_Identifier (Loc, Name_Get_Active_Partition_ID))))); Target_Info.RPC_Receiver := Make_Selected_Component (Loc, Prefix => Make_Identifier (Loc, Chars (RCI_Locator)), Selector_Name => Make_Identifier (Loc, Name_Get_RCI_Package_Receiver)); end if; return Target_Info; end Build_Stub_Target; -------------------------------------- -- Build_Subprogram_Receiving_Stubs -- -------------------------------------- function Build_Subprogram_Receiving_Stubs (Vis_Decl : Node_Id; Asynchronous : Boolean; Dynamically_Asynchronous : Boolean := False; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Parent_Primitive : Entity_Id := Empty) return Node_Id is Loc : constant Source_Ptr := Sloc (Vis_Decl); Request_Parameter : constant Entity_Id := Make_Temporary (Loc, 'R'); -- Formal parameter for receiving stubs: a descriptor for an incoming -- request. Decls : constant List_Id := New_List; -- All the parameters will get declared before calling the real -- subprograms. Also the out parameters will be declared. Statements : constant List_Id := New_List; Extra_Formal_Statements : constant List_Id := New_List; -- Statements concerning extra formal parameters After_Statements : constant List_Id := New_List; -- Statements to be executed after the subprogram call Inner_Decls : List_Id := No_List; -- In case of a function, the inner declarations are needed since -- the result may be unconstrained. Excep_Handlers : List_Id := No_List; Excep_Choice : Entity_Id; Excep_Code : List_Id; Parameter_List : constant List_Id := New_List; -- List of parameters to be passed to the subprogram Current_Parameter : Node_Id; Ordered_Parameters_List : constant List_Id := Build_Ordered_Parameters_List (Specification (Vis_Decl)); Subp_Spec : Node_Id; -- Subprogram specification Called_Subprogram : Node_Id; -- The subprogram to call Null_Raise_Statement : Node_Id; Dynamic_Async : Entity_Id; begin if Present (RACW_Type) then Called_Subprogram := New_Occurrence_Of (Parent_Primitive, Loc); else Called_Subprogram := New_Occurrence_Of (Defining_Unit_Name (Specification (Vis_Decl)), Loc); end if; if Dynamically_Asynchronous then Dynamic_Async := Make_Temporary (Loc, 'S'); else Dynamic_Async := Empty; end if; if not Asynchronous or Dynamically_Asynchronous then -- The first statement after the subprogram call is a statement to -- write a Null_Occurrence into the result stream. Null_Raise_Statement := Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc), Attribute_Name => Name_Write, Expressions => New_List ( Make_Selected_Component (Loc, Prefix => Request_Parameter, Selector_Name => Name_Result), New_Occurrence_Of (RTE (RE_Null_Occurrence), Loc))); if Dynamically_Asynchronous then Null_Raise_Statement := Make_Implicit_If_Statement (Vis_Decl, Condition => Make_Op_Not (Loc, New_Occurrence_Of (Dynamic_Async, Loc)), Then_Statements => New_List (Null_Raise_Statement)); end if; Append_To (After_Statements, Null_Raise_Statement); end if; -- Loop through every parameter and get its value from the stream. If -- the parameter is unconstrained, then the parameter is read using -- 'Input at the point of declaration. Current_Parameter := First (Ordered_Parameters_List); while Present (Current_Parameter) loop declare Etyp : Entity_Id; Constrained : Boolean; Need_Extra_Constrained : Boolean; -- True when an Extra_Constrained actual is required Object : constant Entity_Id := Make_Temporary (Loc, 'P'); Expr : Node_Id := Empty; Is_Controlling_Formal : constant Boolean := Is_RACW_Controlling_Formal (Current_Parameter, Stub_Type); begin if Is_Controlling_Formal then -- We have a controlling formal parameter. Read its address -- rather than a real object. The address is in Unsigned_64 -- form. Etyp := RTE (RE_Unsigned_64); else Etyp := Etype (Parameter_Type (Current_Parameter)); end if; Constrained := not Transmit_As_Unconstrained (Etyp); if In_Present (Current_Parameter) or else not Out_Present (Current_Parameter) or else not Constrained or else Is_Controlling_Formal then -- If an input parameter is constrained, then the read of -- the parameter is deferred until the beginning of the -- subprogram body. If it is unconstrained, then an -- expression is built for the object declaration and the -- variable is set using 'Input instead of 'Read. Note that -- this deferral does not change the order in which the -- actuals are read because Build_Ordered_Parameter_List -- puts them unconstrained first. if Constrained then Append_To (Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Etyp, Loc), Attribute_Name => Name_Read, Expressions => New_List ( Make_Selected_Component (Loc, Prefix => Request_Parameter, Selector_Name => Name_Params), New_Occurrence_Of (Object, Loc)))); else -- Build and append Input_With_Tag_Check function Append_To (Decls, Input_With_Tag_Check (Loc, Var_Type => Etyp, Stream => Make_Selected_Component (Loc, Prefix => Request_Parameter, Selector_Name => Name_Params))); -- Prepare function call expression Expr := Make_Function_Call (Loc, Name => New_Occurrence_Of (Defining_Unit_Name (Specification (Last (Decls))), Loc)); end if; end if; Need_Extra_Constrained := Nkind (Parameter_Type (Current_Parameter)) /= N_Access_Definition and then Ekind (Defining_Identifier (Current_Parameter)) /= E_Void and then Present (Extra_Constrained (Defining_Identifier (Current_Parameter))); -- We may not associate an extra constrained actual to a -- constant object, so if one is needed, declare the actual -- as a variable even if it won't be modified. Build_Actual_Object_Declaration (Object => Object, Etyp => Etyp, Variable => Need_Extra_Constrained or else Out_Present (Current_Parameter), Expr => Expr, Decls => Decls); -- An out parameter may be written back using a 'Write -- attribute instead of a 'Output because it has been -- constrained by the parameter given to the caller. Note that -- out controlling arguments in the case of a RACW are not put -- back in the stream because the pointer on them has not -- changed. if Out_Present (Current_Parameter) and then Etype (Parameter_Type (Current_Parameter)) /= Stub_Type then Append_To (After_Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Etyp, Loc), Attribute_Name => Name_Write, Expressions => New_List ( Make_Selected_Component (Loc, Prefix => Request_Parameter, Selector_Name => Name_Result), New_Occurrence_Of (Object, Loc)))); end if; -- For RACW controlling formals, the Etyp of Object is always -- an RACW, even if the parameter is not of an anonymous access -- type. In such case, we need to dereference it at call time. if Is_Controlling_Formal then if Nkind (Parameter_Type (Current_Parameter)) /= N_Access_Definition then Append_To (Parameter_List, Make_Parameter_Association (Loc, Selector_Name => New_Occurrence_Of ( Defining_Identifier (Current_Parameter), Loc), Explicit_Actual_Parameter => Make_Explicit_Dereference (Loc, Unchecked_Convert_To (RACW_Type, OK_Convert_To (RTE (RE_Address), New_Occurrence_Of (Object, Loc)))))); else Append_To (Parameter_List, Make_Parameter_Association (Loc, Selector_Name => New_Occurrence_Of ( Defining_Identifier (Current_Parameter), Loc), Explicit_Actual_Parameter => Unchecked_Convert_To (RACW_Type, OK_Convert_To (RTE (RE_Address), New_Occurrence_Of (Object, Loc))))); end if; else Append_To (Parameter_List, Make_Parameter_Association (Loc, Selector_Name => New_Occurrence_Of ( Defining_Identifier (Current_Parameter), Loc), Explicit_Actual_Parameter => New_Occurrence_Of (Object, Loc))); end if; -- If the current parameter needs an extra formal, then read it -- from the stream and set the corresponding semantic field in -- the variable. If the kind of the parameter identifier is -- E_Void, then this is a compiler generated parameter that -- doesn't need an extra constrained status. -- The case of Extra_Accessibility should also be handled ??? if Need_Extra_Constrained then declare Extra_Parameter : constant Entity_Id := Extra_Constrained (Defining_Identifier (Current_Parameter)); Formal_Entity : constant Entity_Id := Make_Defining_Identifier (Loc, Chars (Extra_Parameter)); Formal_Type : constant Entity_Id := Etype (Extra_Parameter); begin Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Formal_Entity, Object_Definition => New_Occurrence_Of (Formal_Type, Loc))); Append_To (Extra_Formal_Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of ( Formal_Type, Loc), Attribute_Name => Name_Read, Expressions => New_List ( Make_Selected_Component (Loc, Prefix => Request_Parameter, Selector_Name => Name_Params), New_Occurrence_Of (Formal_Entity, Loc)))); -- Note: the call to Set_Extra_Constrained below relies -- on the fact that Object's Ekind has been set by -- Build_Actual_Object_Declaration. Set_Extra_Constrained (Object, Formal_Entity); end; end if; end; Next (Current_Parameter); end loop; -- Append the formal statements list at the end of regular statements Append_List_To (Statements, Extra_Formal_Statements); if Nkind (Specification (Vis_Decl)) = N_Function_Specification then -- The remote subprogram is a function. We build an inner block to -- be able to hold a potentially unconstrained result in a -- variable. declare Etyp : constant Entity_Id := Etype (Result_Definition (Specification (Vis_Decl))); Result : constant Node_Id := Make_Temporary (Loc, 'R'); begin Inner_Decls := New_List ( Make_Object_Declaration (Loc, Defining_Identifier => Result, Constant_Present => True, Object_Definition => New_Occurrence_Of (Etyp, Loc), Expression => Make_Function_Call (Loc, Name => Called_Subprogram, Parameter_Associations => Parameter_List))); if Is_Class_Wide_Type (Etyp) then -- For a remote call to a function with a class-wide type, -- check that the returned value satisfies the requirements -- of E.4(18). Append_To (Inner_Decls, Make_Transportable_Check (Loc, New_Occurrence_Of (Result, Loc))); end if; Append_To (After_Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Etyp, Loc), Attribute_Name => Name_Output, Expressions => New_List ( Make_Selected_Component (Loc, Prefix => Request_Parameter, Selector_Name => Name_Result), New_Occurrence_Of (Result, Loc)))); end; Append_To (Statements, Make_Block_Statement (Loc, Declarations => Inner_Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => After_Statements))); else -- The remote subprogram is a procedure. We do not need any inner -- block in this case. if Dynamically_Asynchronous then Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Dynamic_Async, Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc))); Append_To (Statements, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Standard_Boolean, Loc), Attribute_Name => Name_Read, Expressions => New_List ( Make_Selected_Component (Loc, Prefix => Request_Parameter, Selector_Name => Name_Params), New_Occurrence_Of (Dynamic_Async, Loc)))); end if; Append_To (Statements, Make_Procedure_Call_Statement (Loc, Name => Called_Subprogram, Parameter_Associations => Parameter_List)); Append_List_To (Statements, After_Statements); end if; if Asynchronous and then not Dynamically_Asynchronous then -- For an asynchronous procedure, add a null exception handler Excep_Handlers := New_List ( Make_Implicit_Exception_Handler (Loc, Exception_Choices => New_List (Make_Others_Choice (Loc)), Statements => New_List (Make_Null_Statement (Loc)))); else -- In the other cases, if an exception is raised, then the -- exception occurrence is copied into the output stream and -- no other output parameter is written. Excep_Choice := Make_Temporary (Loc, 'E'); Excep_Code := New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc), Attribute_Name => Name_Write, Expressions => New_List ( Make_Selected_Component (Loc, Prefix => Request_Parameter, Selector_Name => Name_Result), New_Occurrence_Of (Excep_Choice, Loc)))); if Dynamically_Asynchronous then Excep_Code := New_List ( Make_Implicit_If_Statement (Vis_Decl, Condition => Make_Op_Not (Loc, New_Occurrence_Of (Dynamic_Async, Loc)), Then_Statements => Excep_Code)); end if; Excep_Handlers := New_List ( Make_Implicit_Exception_Handler (Loc, Choice_Parameter => Excep_Choice, Exception_Choices => New_List (Make_Others_Choice (Loc)), Statements => Excep_Code)); end if; Subp_Spec := Make_Procedure_Specification (Loc, Defining_Unit_Name => Make_Temporary (Loc, 'F'), Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Request_Parameter, Parameter_Type => New_Occurrence_Of (RTE (RE_Request_Access), Loc)))); return Make_Subprogram_Body (Loc, Specification => Subp_Spec, Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Statements, Exception_Handlers => Excep_Handlers)); end Build_Subprogram_Receiving_Stubs; ------------ -- Result -- ------------ function Result return Node_Id is begin return Make_Identifier (Loc, Name_V); end Result; ----------------------- -- RPC_Receiver_Decl -- ----------------------- function RPC_Receiver_Decl (RACW_Type : Entity_Id) return Node_Id is Loc : constant Source_Ptr := Sloc (RACW_Type); Is_RAS : constant Boolean := not Comes_From_Source (RACW_Type); begin -- No RPC receiver for remote access-to-subprogram if Is_RAS then return Empty; end if; return Make_Subprogram_Declaration (Loc, Build_RPC_Receiver_Specification (RPC_Receiver => Make_Temporary (Loc, 'R'), Request_Parameter => Make_Defining_Identifier (Loc, Name_R))); end RPC_Receiver_Decl; ---------------------- -- Stream_Parameter -- ---------------------- function Stream_Parameter return Node_Id is begin return Make_Identifier (Loc, Name_S); end Stream_Parameter; end GARLIC_Support; ------------------------------- -- Get_And_Reset_RACW_Bodies -- ------------------------------- function Get_And_Reset_RACW_Bodies (RACW_Type : Entity_Id) return List_Id is Desig : constant Entity_Id := Etype (Designated_Type (RACW_Type)); Stub_Elements : Stub_Structure := Stubs_Table.Get (Desig); Body_Decls : List_Id; -- Returned list of declarations begin if Stub_Elements = Empty_Stub_Structure then -- Stub elements may be missing as a consequence of a previously -- detected error. return No_List; end if; Body_Decls := Stub_Elements.Body_Decls; Stub_Elements.Body_Decls := No_List; Stubs_Table.Set (Desig, Stub_Elements); return Body_Decls; end Get_And_Reset_RACW_Bodies; ----------------------- -- Get_Stub_Elements -- ----------------------- function Get_Stub_Elements (RACW_Type : Entity_Id) return Stub_Structure is Desig : constant Entity_Id := Etype (Designated_Type (RACW_Type)); Stub_Elements : constant Stub_Structure := Stubs_Table.Get (Desig); begin pragma Assert (Stub_Elements /= Empty_Stub_Structure); return Stub_Elements; end Get_Stub_Elements; ----------------------- -- Get_Subprogram_Id -- ----------------------- function Get_Subprogram_Id (Def : Entity_Id) return String_Id is Result : constant String_Id := Get_Subprogram_Ids (Def).Str_Identifier; begin pragma Assert (Result /= No_String); return Result; end Get_Subprogram_Id; ----------------------- -- Get_Subprogram_Id -- ----------------------- function Get_Subprogram_Id (Def : Entity_Id) return Int is begin return Get_Subprogram_Ids (Def).Int_Identifier; end Get_Subprogram_Id; ------------------------ -- Get_Subprogram_Ids -- ------------------------ function Get_Subprogram_Ids (Def : Entity_Id) return Subprogram_Identifiers is begin return Subprogram_Identifier_Table.Get (Def); end Get_Subprogram_Ids; ---------- -- Hash -- ---------- function Hash (F : Entity_Id) return Hash_Index is begin return Hash_Index (Natural (F) mod Positive (Hash_Index'Last + 1)); end Hash; function Hash (F : Name_Id) return Hash_Index is begin return Hash_Index (Natural (F) mod Positive (Hash_Index'Last + 1)); end Hash; -------------------------- -- Input_With_Tag_Check -- -------------------------- function Input_With_Tag_Check (Loc : Source_Ptr; Var_Type : Entity_Id; Stream : Node_Id) return Node_Id is begin return Make_Subprogram_Body (Loc, Specification => Make_Function_Specification (Loc, Defining_Unit_Name => Make_Temporary (Loc, 'S'), Result_Definition => New_Occurrence_Of (Var_Type, Loc)), Declarations => No_List, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, New_List ( Make_Tag_Check (Loc, Make_Simple_Return_Statement (Loc, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Var_Type, Loc), Attribute_Name => Name_Input, Expressions => New_List (Stream))))))); end Input_With_Tag_Check; -------------------------------- -- Is_RACW_Controlling_Formal -- -------------------------------- function Is_RACW_Controlling_Formal (Parameter : Node_Id; Stub_Type : Entity_Id) return Boolean is Typ : Entity_Id; begin -- If the kind of the parameter is E_Void, then it is not a controlling -- formal (this can happen in the context of RAS). if Ekind (Defining_Identifier (Parameter)) = E_Void then return False; end if; -- If the parameter is not a controlling formal, then it cannot be -- possibly a RACW_Controlling_Formal. if not Is_Controlling_Formal (Defining_Identifier (Parameter)) then return False; end if; Typ := Parameter_Type (Parameter); return (Nkind (Typ) = N_Access_Definition and then Etype (Subtype_Mark (Typ)) = Stub_Type) or else Etype (Typ) = Stub_Type; end Is_RACW_Controlling_Formal; ------------------------------ -- Make_Transportable_Check -- ------------------------------ function Make_Transportable_Check (Loc : Source_Ptr; Expr : Node_Id) return Node_Id is begin return Make_Raise_Program_Error (Loc, Condition => Make_Op_Not (Loc, Build_Get_Transportable (Loc, Make_Selected_Component (Loc, Prefix => Expr, Selector_Name => Make_Identifier (Loc, Name_uTag)))), Reason => PE_Non_Transportable_Actual); end Make_Transportable_Check; ----------------------------- -- Make_Selected_Component -- ----------------------------- function Make_Selected_Component (Loc : Source_Ptr; Prefix : Entity_Id; Selector_Name : Name_Id) return Node_Id is begin return Make_Selected_Component (Loc, Prefix => New_Occurrence_Of (Prefix, Loc), Selector_Name => Make_Identifier (Loc, Selector_Name)); end Make_Selected_Component; -------------------- -- Make_Tag_Check -- -------------------- function Make_Tag_Check (Loc : Source_Ptr; N : Node_Id) return Node_Id is Occ : constant Entity_Id := Make_Temporary (Loc, 'E'); begin return Make_Block_Statement (Loc, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => New_List (N), Exception_Handlers => New_List ( Make_Implicit_Exception_Handler (Loc, Choice_Parameter => Occ, Exception_Choices => New_List (New_Occurrence_Of (RTE (RE_Tag_Error), Loc)), Statements => New_List (Make_Procedure_Call_Statement (Loc, New_Occurrence_Of (RTE (RE_Raise_Program_Error_Unknown_Tag), Loc), New_List (New_Occurrence_Of (Occ, Loc)))))))); end Make_Tag_Check; ---------------------------- -- Need_Extra_Constrained -- ---------------------------- function Need_Extra_Constrained (Parameter : Node_Id) return Boolean is Etyp : constant Entity_Id := Etype (Parameter_Type (Parameter)); begin return Out_Present (Parameter) and then Has_Discriminants (Etyp) and then not Is_Constrained (Etyp) and then Is_Definite_Subtype (Etyp); end Need_Extra_Constrained; ------------------------------------ -- Pack_Entity_Into_Stream_Access -- ------------------------------------ function Pack_Entity_Into_Stream_Access (Loc : Source_Ptr; Stream : Node_Id; Object : Entity_Id; Etyp : Entity_Id := Empty) return Node_Id is Typ : Entity_Id; begin if Present (Etyp) then Typ := Etyp; else Typ := Etype (Object); end if; return Pack_Node_Into_Stream_Access (Loc, Stream => Stream, Object => New_Occurrence_Of (Object, Loc), Etyp => Typ); end Pack_Entity_Into_Stream_Access; --------------------------- -- Pack_Node_Into_Stream -- --------------------------- function Pack_Node_Into_Stream (Loc : Source_Ptr; Stream : Entity_Id; Object : Node_Id; Etyp : Entity_Id) return Node_Id is Write_Attribute : Name_Id := Name_Write; begin if not Is_Constrained (Etyp) then Write_Attribute := Name_Output; end if; return Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Etyp, Loc), Attribute_Name => Write_Attribute, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Stream, Loc), Attribute_Name => Name_Access), Object)); end Pack_Node_Into_Stream; ---------------------------------- -- Pack_Node_Into_Stream_Access -- ---------------------------------- function Pack_Node_Into_Stream_Access (Loc : Source_Ptr; Stream : Node_Id; Object : Node_Id; Etyp : Entity_Id) return Node_Id is Write_Attribute : Name_Id := Name_Write; begin if not Is_Constrained (Etyp) then Write_Attribute := Name_Output; end if; return Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Etyp, Loc), Attribute_Name => Write_Attribute, Expressions => New_List ( Stream, Object)); end Pack_Node_Into_Stream_Access; --------------------- -- PolyORB_Support -- --------------------- package body PolyORB_Support is -- Local subprograms procedure Add_RACW_Read_Attribute (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; Body_Decls : List_Id); -- Add Read attribute for the RACW type. The declaration and attribute -- definition clauses are inserted right after the declaration of -- RACW_Type. If Body_Decls is not No_List, the subprogram body is -- appended to it (case where the RACW declaration is in the main unit). procedure Add_RACW_Write_Attribute (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; Body_Decls : List_Id); -- Same as above for the Write attribute procedure Add_RACW_From_Any (RACW_Type : Entity_Id; Body_Decls : List_Id); -- Add the From_Any TSS for this RACW type procedure Add_RACW_To_Any (RACW_Type : Entity_Id; Body_Decls : List_Id); -- Add the To_Any TSS for this RACW type procedure Add_RACW_TypeCode (Designated_Type : Entity_Id; RACW_Type : Entity_Id; Body_Decls : List_Id); -- Add the TypeCode TSS for this RACW type procedure Add_RAS_From_Any (RAS_Type : Entity_Id); -- Add the From_Any TSS for this RAS type procedure Add_RAS_To_Any (RAS_Type : Entity_Id); -- Add the To_Any TSS for this RAS type procedure Add_RAS_TypeCode (RAS_Type : Entity_Id); -- Add the TypeCode TSS for this RAS type procedure Add_RAS_Access_TSS (N : Node_Id); -- Add a subprogram body for RAS Access TSS ------------------------------------- -- Add_Obj_RPC_Receiver_Completion -- ------------------------------------- procedure Add_Obj_RPC_Receiver_Completion (Loc : Source_Ptr; Decls : List_Id; RPC_Receiver : Entity_Id; Stub_Elements : Stub_Structure) is Desig : constant Entity_Id := Etype (Designated_Type (Stub_Elements.RACW_Type)); begin Append_To (Decls, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of ( RTE (RE_Register_Obj_Receiving_Stub), Loc), Parameter_Associations => New_List ( -- Name Make_String_Literal (Loc, Fully_Qualified_Name_String (Desig, Append_NUL => False)), -- Handler Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of ( Defining_Unit_Name (Parent (RPC_Receiver)), Loc), Attribute_Name => Name_Access), -- Receiver Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of ( Defining_Identifier ( Stub_Elements.RPC_Receiver_Decl), Loc), Attribute_Name => Name_Access)))); end Add_Obj_RPC_Receiver_Completion; ----------------------- -- Add_RACW_Features -- ----------------------- procedure Add_RACW_Features (RACW_Type : Entity_Id; Desig : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; RPC_Receiver_Decl : Node_Id; Body_Decls : List_Id) is pragma Unreferenced (RPC_Receiver_Decl); begin Add_RACW_From_Any (RACW_Type => RACW_Type, Body_Decls => Body_Decls); Add_RACW_To_Any (RACW_Type => RACW_Type, Body_Decls => Body_Decls); Add_RACW_Write_Attribute (RACW_Type => RACW_Type, Stub_Type => Stub_Type, Stub_Type_Access => Stub_Type_Access, Body_Decls => Body_Decls); Add_RACW_Read_Attribute (RACW_Type => RACW_Type, Stub_Type => Stub_Type, Stub_Type_Access => Stub_Type_Access, Body_Decls => Body_Decls); Add_RACW_TypeCode (Designated_Type => Desig, RACW_Type => RACW_Type, Body_Decls => Body_Decls); end Add_RACW_Features; ----------------------- -- Add_RACW_From_Any -- ----------------------- procedure Add_RACW_From_Any (RACW_Type : Entity_Id; Body_Decls : List_Id) is Loc : constant Source_Ptr := Sloc (RACW_Type); Is_RAS : constant Boolean := not Comes_From_Source (RACW_Type); Fnam : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => New_External_Name (Chars (RACW_Type), 'F')); Func_Spec : Node_Id; Func_Decl : Node_Id; Func_Body : Node_Id; Statements : List_Id; -- Various parts of the subprogram Any_Parameter : constant Entity_Id := Make_Defining_Identifier (Loc, Name_A); Asynchronous_Flag : constant Entity_Id := Asynchronous_Flags_Table.Get (RACW_Type); -- The flag object declared in Add_RACW_Asynchronous_Flag begin Func_Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Fnam, Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Any_Parameter, Parameter_Type => New_Occurrence_Of (RTE (RE_Any), Loc))), Result_Definition => New_Occurrence_Of (RACW_Type, Loc)); -- NOTE: The usage occurrences of RACW_Parameter must refer to the -- entity in the declaration spec, not those of the body spec. Func_Decl := Make_Subprogram_Declaration (Loc, Func_Spec); Insert_After (Declaration_Node (RACW_Type), Func_Decl); Set_Renaming_TSS (RACW_Type, Fnam, TSS_From_Any); if No (Body_Decls) then return; end if; -- ??? Issue with asynchronous calls here: the Asynchronous flag is -- set on the stub type if, and only if, the RACW type has a pragma -- Asynchronous. This is incorrect for RACWs that implement RAS -- types, because in that case the /designated subprogram/ (not the -- type) might be asynchronous, and that causes the stub to need to -- be asynchronous too. A solution is to transport a RAS as a struct -- containing a RACW and an asynchronous flag, and to properly alter -- the Asynchronous component in the stub type in the RAS's _From_Any -- TSS. Statements := New_List ( Make_Simple_Return_Statement (Loc, Expression => Unchecked_Convert_To (RACW_Type, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Get_RACW), Loc), Parameter_Associations => New_List ( Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_FA_ObjRef), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any_Parameter, Loc))), Build_Stub_Tag (Loc, RACW_Type), New_Occurrence_Of (Boolean_Literals (Is_RAS), Loc), New_Occurrence_Of (Asynchronous_Flag, Loc)))))); Func_Body := Make_Subprogram_Body (Loc, Specification => Copy_Specification (Loc, Func_Spec), Declarations => No_List, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Statements)); Append_To (Body_Decls, Func_Body); end Add_RACW_From_Any; ----------------------------- -- Add_RACW_Read_Attribute -- ----------------------------- procedure Add_RACW_Read_Attribute (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; Body_Decls : List_Id) is pragma Unreferenced (Stub_Type, Stub_Type_Access); Loc : constant Source_Ptr := Sloc (RACW_Type); Proc_Decl : Node_Id; Attr_Decl : Node_Id; Body_Node : Node_Id; Decls : constant List_Id := New_List; Statements : constant List_Id := New_List; Reference : constant Entity_Id := Make_Defining_Identifier (Loc, Name_R); -- Various parts of the procedure Pnam : constant Entity_Id := Make_Temporary (Loc, 'R'); Is_RAS : constant Boolean := not Comes_From_Source (RACW_Type); Asynchronous_Flag : constant Entity_Id := Asynchronous_Flags_Table.Get (RACW_Type); pragma Assert (Present (Asynchronous_Flag)); function Stream_Parameter return Node_Id; function Result return Node_Id; -- Functions to create occurrences of the formal parameter names ------------ -- Result -- ------------ function Result return Node_Id is begin return Make_Identifier (Loc, Name_V); end Result; ---------------------- -- Stream_Parameter -- ---------------------- function Stream_Parameter return Node_Id is begin return Make_Identifier (Loc, Name_S); end Stream_Parameter; -- Start of processing for Add_RACW_Read_Attribute begin Build_Stream_Procedure (Loc, RACW_Type, Body_Node, Pnam, Statements, Outp => True); Proc_Decl := Make_Subprogram_Declaration (Loc, Copy_Specification (Loc, Specification (Body_Node))); Attr_Decl := Make_Attribute_Definition_Clause (Loc, Name => New_Occurrence_Of (RACW_Type, Loc), Chars => Name_Read, Expression => New_Occurrence_Of ( Defining_Unit_Name (Specification (Proc_Decl)), Loc)); Insert_After (Declaration_Node (RACW_Type), Proc_Decl); Insert_After (Proc_Decl, Attr_Decl); if No (Body_Decls) then return; end if; Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Reference, Object_Definition => New_Occurrence_Of (RTE (RE_Object_Ref), Loc))); Append_List_To (Statements, New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Object_Ref), Loc), Attribute_Name => Name_Read, Expressions => New_List ( Stream_Parameter, New_Occurrence_Of (Reference, Loc))), Make_Assignment_Statement (Loc, Name => Result, Expression => Unchecked_Convert_To (RACW_Type, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Get_RACW), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Reference, Loc), Build_Stub_Tag (Loc, RACW_Type), New_Occurrence_Of (Boolean_Literals (Is_RAS), Loc), New_Occurrence_Of (Asynchronous_Flag, Loc))))))); Set_Declarations (Body_Node, Decls); Append_To (Body_Decls, Body_Node); end Add_RACW_Read_Attribute; --------------------- -- Add_RACW_To_Any -- --------------------- procedure Add_RACW_To_Any (RACW_Type : Entity_Id; Body_Decls : List_Id) is Loc : constant Source_Ptr := Sloc (RACW_Type); Fnam : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => New_External_Name (Chars (RACW_Type), 'T')); Is_RAS : constant Boolean := not Comes_From_Source (RACW_Type); Stub_Elements : constant Stub_Structure := Get_Stub_Elements (RACW_Type); Func_Spec : Node_Id; Func_Decl : Node_Id; Func_Body : Node_Id; Decls : List_Id; Statements : List_Id; -- Various parts of the subprogram RACW_Parameter : constant Entity_Id := Make_Defining_Identifier (Loc, Name_R); Reference : constant Entity_Id := Make_Temporary (Loc, 'R'); Any : constant Entity_Id := Make_Temporary (Loc, 'A'); begin Func_Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Fnam, Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => RACW_Parameter, Parameter_Type => New_Occurrence_Of (RACW_Type, Loc))), Result_Definition => New_Occurrence_Of (RTE (RE_Any), Loc)); -- NOTE: The usage occurrences of RACW_Parameter must refer to the -- entity in the declaration spec, not in the body spec. Func_Decl := Make_Subprogram_Declaration (Loc, Func_Spec); Insert_After (Declaration_Node (RACW_Type), Func_Decl); Set_Renaming_TSS (RACW_Type, Fnam, TSS_To_Any); if No (Body_Decls) then return; end if; -- Generate: -- R : constant Object_Ref := -- Get_Reference -- (Address!(RACW), -- "typ", -- Stub_Type'Tag, -- Is_RAS, -- RPC_Receiver'Access); -- A : Any; Decls := New_List ( Make_Object_Declaration (Loc, Defining_Identifier => Reference, Constant_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Object_Ref), Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Get_Reference), Loc), Parameter_Associations => New_List ( Unchecked_Convert_To (RTE (RE_Address), New_Occurrence_Of (RACW_Parameter, Loc)), Make_String_Literal (Loc, Strval => Fully_Qualified_Name_String (Etype (Designated_Type (RACW_Type)), Append_NUL => False)), Build_Stub_Tag (Loc, RACW_Type), New_Occurrence_Of (Boolean_Literals (Is_RAS), Loc), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Defining_Identifier (Stub_Elements.RPC_Receiver_Decl), Loc), Attribute_Name => Name_Access)))), Make_Object_Declaration (Loc, Defining_Identifier => Any, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc))); -- Generate: -- Any := TA_ObjRef (Reference); -- Set_TC (Any, RPC_Receiver.Obj_TypeCode); -- return Any; Statements := New_List ( Make_Assignment_Statement (Loc, Name => New_Occurrence_Of (Any, Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_TA_ObjRef), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Reference, Loc)))), Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Set_TC), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc), Make_Selected_Component (Loc, Prefix => Defining_Identifier ( Stub_Elements.RPC_Receiver_Decl), Selector_Name => Name_Obj_TypeCode))), Make_Simple_Return_Statement (Loc, Expression => New_Occurrence_Of (Any, Loc))); Func_Body := Make_Subprogram_Body (Loc, Specification => Copy_Specification (Loc, Func_Spec), Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Statements)); Append_To (Body_Decls, Func_Body); end Add_RACW_To_Any; ----------------------- -- Add_RACW_TypeCode -- ----------------------- procedure Add_RACW_TypeCode (Designated_Type : Entity_Id; RACW_Type : Entity_Id; Body_Decls : List_Id) is Loc : constant Source_Ptr := Sloc (RACW_Type); Fnam : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => New_External_Name (Chars (RACW_Type), 'Y')); Stub_Elements : constant Stub_Structure := Stubs_Table.Get (Designated_Type); pragma Assert (Stub_Elements /= Empty_Stub_Structure); Func_Spec : Node_Id; Func_Decl : Node_Id; Func_Body : Node_Id; begin -- The spec for this subprogram has a dummy 'access RACW' argument, -- which serves only for overloading purposes. Func_Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Fnam, Result_Definition => New_Occurrence_Of (RTE (RE_TypeCode), Loc)); -- NOTE: The usage occurrences of RACW_Parameter must refer to the -- entity in the declaration spec, not those of the body spec. Func_Decl := Make_Subprogram_Declaration (Loc, Func_Spec); Insert_After (Declaration_Node (RACW_Type), Func_Decl); Set_Renaming_TSS (RACW_Type, Fnam, TSS_TypeCode); if No (Body_Decls) then return; end if; Func_Body := Make_Subprogram_Body (Loc, Specification => Copy_Specification (Loc, Func_Spec), Declarations => Empty_List, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => New_List ( Make_Simple_Return_Statement (Loc, Expression => Make_Selected_Component (Loc, Prefix => Defining_Identifier (Stub_Elements.RPC_Receiver_Decl), Selector_Name => Name_Obj_TypeCode))))); Append_To (Body_Decls, Func_Body); end Add_RACW_TypeCode; ------------------------------ -- Add_RACW_Write_Attribute -- ------------------------------ procedure Add_RACW_Write_Attribute (RACW_Type : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; Body_Decls : List_Id) is pragma Unreferenced (Stub_Type, Stub_Type_Access); Loc : constant Source_Ptr := Sloc (RACW_Type); Is_RAS : constant Boolean := not Comes_From_Source (RACW_Type); Stub_Elements : constant Stub_Structure := Get_Stub_Elements (RACW_Type); Body_Node : Node_Id; Proc_Decl : Node_Id; Attr_Decl : Node_Id; Statements : constant List_Id := New_List; Pnam : constant Entity_Id := Make_Temporary (Loc, 'R'); function Stream_Parameter return Node_Id; function Object return Node_Id; -- Functions to create occurrences of the formal parameter names ------------ -- Object -- ------------ function Object return Node_Id is begin return Make_Identifier (Loc, Name_V); end Object; ---------------------- -- Stream_Parameter -- ---------------------- function Stream_Parameter return Node_Id is begin return Make_Identifier (Loc, Name_S); end Stream_Parameter; -- Start of processing for Add_RACW_Write_Attribute begin Build_Stream_Procedure (Loc, RACW_Type, Body_Node, Pnam, Statements, Outp => False); Proc_Decl := Make_Subprogram_Declaration (Loc, Copy_Specification (Loc, Specification (Body_Node))); Attr_Decl := Make_Attribute_Definition_Clause (Loc, Name => New_Occurrence_Of (RACW_Type, Loc), Chars => Name_Write, Expression => New_Occurrence_Of ( Defining_Unit_Name (Specification (Proc_Decl)), Loc)); Insert_After (Declaration_Node (RACW_Type), Proc_Decl); Insert_After (Proc_Decl, Attr_Decl); if No (Body_Decls) then return; end if; Append_To (Statements, Pack_Node_Into_Stream_Access (Loc, Stream => Stream_Parameter, Object => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Get_Reference), Loc), Parameter_Associations => New_List ( Unchecked_Convert_To (RTE (RE_Address), Object), Make_String_Literal (Loc, Strval => Fully_Qualified_Name_String (Etype (Designated_Type (RACW_Type)), Append_NUL => False)), Build_Stub_Tag (Loc, RACW_Type), New_Occurrence_Of (Boolean_Literals (Is_RAS), Loc), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Defining_Identifier (Stub_Elements.RPC_Receiver_Decl), Loc), Attribute_Name => Name_Access))), Etyp => RTE (RE_Object_Ref))); Append_To (Body_Decls, Body_Node); end Add_RACW_Write_Attribute; ----------------------- -- Add_RAST_Features -- ----------------------- procedure Add_RAST_Features (Vis_Decl : Node_Id; RAS_Type : Entity_Id) is begin Add_RAS_Access_TSS (Vis_Decl); Add_RAS_From_Any (RAS_Type); Add_RAS_TypeCode (RAS_Type); -- To_Any uses TypeCode, and therefore needs to be generated last Add_RAS_To_Any (RAS_Type); end Add_RAST_Features; ------------------------ -- Add_RAS_Access_TSS -- ------------------------ procedure Add_RAS_Access_TSS (N : Node_Id) is Loc : constant Source_Ptr := Sloc (N); Ras_Type : constant Entity_Id := Defining_Identifier (N); Fat_Type : constant Entity_Id := Equivalent_Type (Ras_Type); -- Ras_Type is the access to subprogram type; Fat_Type is the -- corresponding record type. RACW_Type : constant Entity_Id := Underlying_RACW_Type (Ras_Type); Stub_Elements : constant Stub_Structure := Get_Stub_Elements (RACW_Type); Proc : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Make_TSS_Name (Ras_Type, TSS_RAS_Access)); Proc_Spec : Node_Id; -- Formal parameters Package_Name : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Name_P); -- Target package Subp_Id : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Name_S); -- Target subprogram Asynch_P : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Name_Asynchronous); -- Is the procedure to which the 'Access applies asynchronous? All_Calls_Remote : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Name_All_Calls_Remote); -- True if an All_Calls_Remote pragma applies to the RCI unit -- that contains the subprogram. -- Common local variables Proc_Decls : List_Id; Proc_Statements : List_Id; Subp_Ref : constant Entity_Id := Make_Defining_Identifier (Loc, Name_R); -- Reference that designates the target subprogram (returned -- by Get_RAS_Info). Is_Local : constant Entity_Id := Make_Defining_Identifier (Loc, Name_L); Local_Addr : constant Entity_Id := Make_Defining_Identifier (Loc, Name_A); -- For the call to Get_Local_Address Local_Stub : constant Entity_Id := Make_Temporary (Loc, 'L'); Stub_Ptr : constant Entity_Id := Make_Temporary (Loc, 'S'); -- Additional local variables for the remote case function Set_Field (Field_Name : Name_Id; Value : Node_Id) return Node_Id; -- Construct an assignment that sets the named component in the -- returned record --------------- -- Set_Field -- --------------- function Set_Field (Field_Name : Name_Id; Value : Node_Id) return Node_Id is begin return Make_Assignment_Statement (Loc, Name => Make_Selected_Component (Loc, Prefix => Stub_Ptr, Selector_Name => Field_Name), Expression => Value); end Set_Field; -- Start of processing for Add_RAS_Access_TSS begin Proc_Decls := New_List ( -- Common declarations Make_Object_Declaration (Loc, Defining_Identifier => Subp_Ref, Object_Definition => New_Occurrence_Of (RTE (RE_Object_Ref), Loc)), Make_Object_Declaration (Loc, Defining_Identifier => Is_Local, Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc)), Make_Object_Declaration (Loc, Defining_Identifier => Local_Addr, Object_Definition => New_Occurrence_Of (RTE (RE_Address), Loc)), Make_Object_Declaration (Loc, Defining_Identifier => Local_Stub, Aliased_Present => True, Object_Definition => New_Occurrence_Of (Stub_Elements.Stub_Type, Loc)), Make_Object_Declaration (Loc, Defining_Identifier => Stub_Ptr, Object_Definition => New_Occurrence_Of (Stub_Elements.Stub_Type_Access, Loc), Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Local_Stub, Loc), Attribute_Name => Name_Unchecked_Access))); Set_Etype (Stub_Ptr, Stub_Elements.Stub_Type_Access); -- Build_Get_Unique_RP_Call needs this information -- Get_RAS_Info (Pkg, Subp, R); -- Obtain a reference to the target subprogram Proc_Statements := New_List ( Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Get_RAS_Info), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Package_Name, Loc), New_Occurrence_Of (Subp_Id, Loc), New_Occurrence_Of (Subp_Ref, Loc))), -- Get_Local_Address (R, L, A); -- Determine whether the subprogram is local (L), and if so -- obtain the local address of its proxy (A). Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Get_Local_Address), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Subp_Ref, Loc), New_Occurrence_Of (Is_Local, Loc), New_Occurrence_Of (Local_Addr, Loc)))); -- Note: Here we assume that the Fat_Type is a record containing just -- an access to a proxy or stub object. Append_To (Proc_Statements, -- if L then Make_Implicit_If_Statement (N, Condition => New_Occurrence_Of (Is_Local, Loc), Then_Statements => New_List ( -- if A.Target = null then Make_Implicit_If_Statement (N, Condition => Make_Op_Eq (Loc, Make_Selected_Component (Loc, Prefix => Unchecked_Convert_To (RTE (RE_RAS_Proxy_Type_Access), New_Occurrence_Of (Local_Addr, Loc)), Selector_Name => Make_Identifier (Loc, Name_Target)), Make_Null (Loc)), Then_Statements => New_List ( -- A.Target := Entity_Of (Ref); Make_Assignment_Statement (Loc, Name => Make_Selected_Component (Loc, Prefix => Unchecked_Convert_To (RTE (RE_RAS_Proxy_Type_Access), New_Occurrence_Of (Local_Addr, Loc)), Selector_Name => Make_Identifier (Loc, Name_Target)), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Entity_Of), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Subp_Ref, Loc)))), -- Inc_Usage (A.Target); -- end if; Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Inc_Usage), Loc), Parameter_Associations => New_List ( Make_Selected_Component (Loc, Prefix => Unchecked_Convert_To (RTE (RE_RAS_Proxy_Type_Access), New_Occurrence_Of (Local_Addr, Loc)), Selector_Name => Make_Identifier (Loc, Name_Target)))))), -- if not All_Calls_Remote then -- return Fat_Type!(A); -- end if; Make_Implicit_If_Statement (N, Condition => Make_Op_Not (Loc, Right_Opnd => New_Occurrence_Of (All_Calls_Remote, Loc)), Then_Statements => New_List ( Make_Simple_Return_Statement (Loc, Expression => Unchecked_Convert_To (Fat_Type, New_Occurrence_Of (Local_Addr, Loc)))))))); Append_List_To (Proc_Statements, New_List ( -- Stub.Target := Entity_Of (Ref); Set_Field (Name_Target, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Entity_Of), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Subp_Ref, Loc)))), -- Inc_Usage (Stub.Target); Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Inc_Usage), Loc), Parameter_Associations => New_List ( Make_Selected_Component (Loc, Prefix => Stub_Ptr, Selector_Name => Name_Target))), -- E.4.1(9) A remote call is asynchronous if it is a call to -- a procedure, or a call through a value of an access-to-procedure -- type, to which a pragma Asynchronous applies. -- Parameter Asynch_P is true when the procedure is asynchronous; -- Expression Asynch_T is true when the type is asynchronous. Set_Field (Name_Asynchronous, Make_Or_Else (Loc, Left_Opnd => New_Occurrence_Of (Asynch_P, Loc), Right_Opnd => New_Occurrence_Of (Boolean_Literals (Is_Asynchronous (Ras_Type)), Loc))))); Append_List_To (Proc_Statements, Build_Get_Unique_RP_Call (Loc, Stub_Ptr, Stub_Elements.Stub_Type)); Append_To (Proc_Statements, Make_Simple_Return_Statement (Loc, Expression => Unchecked_Convert_To (Fat_Type, New_Occurrence_Of (Stub_Ptr, Loc)))); Proc_Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Proc, Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Package_Name, Parameter_Type => New_Occurrence_Of (Standard_String, Loc)), Make_Parameter_Specification (Loc, Defining_Identifier => Subp_Id, Parameter_Type => New_Occurrence_Of (Standard_String, Loc)), Make_Parameter_Specification (Loc, Defining_Identifier => Asynch_P, Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc)), Make_Parameter_Specification (Loc, Defining_Identifier => All_Calls_Remote, Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc))), Result_Definition => New_Occurrence_Of (Fat_Type, Loc)); -- Set the kind and return type of the function to prevent -- ambiguities between Ras_Type and Fat_Type in subsequent analysis. Set_Ekind (Proc, E_Function); Set_Etype (Proc, Fat_Type); Discard_Node ( Make_Subprogram_Body (Loc, Specification => Proc_Spec, Declarations => Proc_Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Proc_Statements))); Set_TSS (Fat_Type, Proc); end Add_RAS_Access_TSS; ---------------------- -- Add_RAS_From_Any -- ---------------------- procedure Add_RAS_From_Any (RAS_Type : Entity_Id) is Loc : constant Source_Ptr := Sloc (RAS_Type); Fnam : constant Entity_Id := Make_Defining_Identifier (Loc, Make_TSS_Name (RAS_Type, TSS_From_Any)); Func_Spec : Node_Id; Statements : List_Id; Any_Parameter : constant Entity_Id := Make_Defining_Identifier (Loc, Name_A); begin Statements := New_List ( Make_Simple_Return_Statement (Loc, Expression => Make_Aggregate (Loc, Component_Associations => New_List ( Make_Component_Association (Loc, Choices => New_List (Make_Identifier (Loc, Name_Ras)), Expression => PolyORB_Support.Helpers.Build_From_Any_Call (Underlying_RACW_Type (RAS_Type), New_Occurrence_Of (Any_Parameter, Loc), No_List)))))); Func_Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Fnam, Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Any_Parameter, Parameter_Type => New_Occurrence_Of (RTE (RE_Any), Loc))), Result_Definition => New_Occurrence_Of (RAS_Type, Loc)); Discard_Node ( Make_Subprogram_Body (Loc, Specification => Func_Spec, Declarations => No_List, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Statements))); Set_TSS (RAS_Type, Fnam); end Add_RAS_From_Any; -------------------- -- Add_RAS_To_Any -- -------------------- procedure Add_RAS_To_Any (RAS_Type : Entity_Id) is Loc : constant Source_Ptr := Sloc (RAS_Type); Fnam : constant Entity_Id := Make_Defining_Identifier (Loc, Make_TSS_Name (RAS_Type, TSS_To_Any)); Decls : List_Id; Statements : List_Id; Func_Spec : Node_Id; Any : constant Entity_Id := Make_Temporary (Loc, 'A'); RAS_Parameter : constant Entity_Id := Make_Temporary (Loc, 'R'); RACW_Parameter : constant Node_Id := Make_Selected_Component (Loc, Prefix => RAS_Parameter, Selector_Name => Name_Ras); begin -- Object declarations Set_Etype (RACW_Parameter, Underlying_RACW_Type (RAS_Type)); Decls := New_List ( Make_Object_Declaration (Loc, Defining_Identifier => Any, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc), Expression => PolyORB_Support.Helpers.Build_To_Any_Call (Loc, RACW_Parameter, No_List))); Statements := New_List ( Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Set_TC), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc), PolyORB_Support.Helpers.Build_TypeCode_Call (Loc, RAS_Type, Decls))), Make_Simple_Return_Statement (Loc, Expression => New_Occurrence_Of (Any, Loc))); Func_Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Fnam, Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => RAS_Parameter, Parameter_Type => New_Occurrence_Of (RAS_Type, Loc))), Result_Definition => New_Occurrence_Of (RTE (RE_Any), Loc)); Discard_Node ( Make_Subprogram_Body (Loc, Specification => Func_Spec, Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Statements))); Set_TSS (RAS_Type, Fnam); end Add_RAS_To_Any; ---------------------- -- Add_RAS_TypeCode -- ---------------------- procedure Add_RAS_TypeCode (RAS_Type : Entity_Id) is Loc : constant Source_Ptr := Sloc (RAS_Type); Fnam : constant Entity_Id := Make_Defining_Identifier (Loc, Make_TSS_Name (RAS_Type, TSS_TypeCode)); Func_Spec : Node_Id; Decls : constant List_Id := New_List; Name_String : String_Id; Repo_Id_String : String_Id; begin Func_Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Fnam, Result_Definition => New_Occurrence_Of (RTE (RE_TypeCode), Loc)); PolyORB_Support.Helpers.Build_Name_And_Repository_Id (RAS_Type, Name_Str => Name_String, Repo_Id_Str => Repo_Id_String); Discard_Node ( Make_Subprogram_Body (Loc, Specification => Func_Spec, Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => New_List ( Make_Simple_Return_Statement (Loc, Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Build_Complex_TC), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (RTE (RE_Tk_Objref), Loc), Make_Aggregate (Loc, Expressions => New_List ( Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_TA_Std_String), Loc), Parameter_Associations => New_List ( Make_String_Literal (Loc, Name_String))), Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_TA_Std_String), Loc), Parameter_Associations => New_List ( Make_String_Literal (Loc, Strval => Repo_Id_String)))))))))))); Set_TSS (RAS_Type, Fnam); end Add_RAS_TypeCode; ----------------------------------------- -- Add_Receiving_Stubs_To_Declarations -- ----------------------------------------- procedure Add_Receiving_Stubs_To_Declarations (Pkg_Spec : Node_Id; Decls : List_Id; Stmts : List_Id) is Loc : constant Source_Ptr := Sloc (Pkg_Spec); Pkg_RPC_Receiver : constant Entity_Id := Make_Temporary (Loc, 'H'); Pkg_RPC_Receiver_Object : Node_Id; Pkg_RPC_Receiver_Body : Node_Id; Pkg_RPC_Receiver_Decls : List_Id; Pkg_RPC_Receiver_Statements : List_Id; Pkg_RPC_Receiver_Cases : constant List_Id := New_List; -- A Pkg_RPC_Receiver is built to decode the request Request : Node_Id; -- Request object received from neutral layer Subp_Id : Entity_Id; -- Subprogram identifier as received from the neutral distribution -- core. Subp_Index : Entity_Id; -- Internal index as determined by matching either the method name -- from the request structure, or the local subprogram address (in -- case of a RAS). Is_Local : constant Entity_Id := Make_Temporary (Loc, 'L'); Local_Address : constant Entity_Id := Make_Temporary (Loc, 'A'); -- Address of a local subprogram designated by a reference -- corresponding to a RAS. Dispatch_On_Address : constant List_Id := New_List; Dispatch_On_Name : constant List_Id := New_List; Current_Subp_Number : Int := First_RCI_Subprogram_Id; Subp_Info_Array : constant Entity_Id := Make_Temporary (Loc, 'I'); Subp_Info_List : constant List_Id := New_List; Register_Pkg_Actuals : constant List_Id := New_List; All_Calls_Remote_E : Entity_Id; procedure Append_Stubs_To (RPC_Receiver_Cases : List_Id; Declaration : Node_Id; Stubs : Node_Id; Subp_Number : Int; Subp_Dist_Name : Entity_Id; Subp_Proxy_Addr : Entity_Id); -- Add one case to the specified RPC receiver case list associating -- Subprogram_Number with the subprogram declared by Declaration, for -- which we have receiving stubs in Stubs. Subp_Number is an internal -- subprogram index. Subp_Dist_Name is the string used to call the -- subprogram by name, and Subp_Dist_Addr is the address of the proxy -- object, used in the context of calls through remote -- access-to-subprogram types. procedure Visit_Subprogram (Decl : Node_Id); -- Generate receiving stub for one remote subprogram --------------------- -- Append_Stubs_To -- --------------------- procedure Append_Stubs_To (RPC_Receiver_Cases : List_Id; Declaration : Node_Id; Stubs : Node_Id; Subp_Number : Int; Subp_Dist_Name : Entity_Id; Subp_Proxy_Addr : Entity_Id) is Case_Stmts : List_Id; begin Case_Stmts := New_List ( Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of ( Defining_Entity (Stubs), Loc), Parameter_Associations => New_List (New_Occurrence_Of (Request, Loc)))); if Nkind (Specification (Declaration)) = N_Function_Specification or else not Is_Asynchronous (Defining_Entity (Specification (Declaration))) then Append_To (Case_Stmts, Make_Simple_Return_Statement (Loc)); end if; Append_To (RPC_Receiver_Cases, Make_Case_Statement_Alternative (Loc, Discrete_Choices => New_List (Make_Integer_Literal (Loc, Subp_Number)), Statements => Case_Stmts)); Append_To (Dispatch_On_Name, Make_Elsif_Part (Loc, Condition => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Caseless_String_Eq), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Subp_Id, Loc), New_Occurrence_Of (Subp_Dist_Name, Loc))), Then_Statements => New_List ( Make_Assignment_Statement (Loc, New_Occurrence_Of (Subp_Index, Loc), Make_Integer_Literal (Loc, Subp_Number))))); Append_To (Dispatch_On_Address, Make_Elsif_Part (Loc, Condition => Make_Op_Eq (Loc, Left_Opnd => New_Occurrence_Of (Local_Address, Loc), Right_Opnd => New_Occurrence_Of (Subp_Proxy_Addr, Loc)), Then_Statements => New_List ( Make_Assignment_Statement (Loc, New_Occurrence_Of (Subp_Index, Loc), Make_Integer_Literal (Loc, Subp_Number))))); end Append_Stubs_To; ---------------------- -- Visit_Subprogram -- ---------------------- procedure Visit_Subprogram (Decl : Node_Id) is Loc : constant Source_Ptr := Sloc (Decl); Spec : constant Node_Id := Specification (Decl); Subp_Def : constant Entity_Id := Defining_Unit_Name (Spec); Subp_Val : String_Id; Subp_Dist_Name : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => New_External_Name (Related_Id => Chars (Subp_Def), Suffix => 'D', Suffix_Index => -1)); Current_Stubs : Node_Id; Proxy_Obj_Addr : Entity_Id; begin -- Disable expansion of stubs if serious errors have been -- diagnosed, because otherwise some illegal remote subprogram -- declarations could cause cascaded errors in stubs. if Serious_Errors_Detected /= 0 then return; end if; -- Build receiving stub Current_Stubs := Build_Subprogram_Receiving_Stubs (Vis_Decl => Decl, Asynchronous => Nkind (Spec) = N_Procedure_Specification and then Is_Asynchronous (Subp_Def)); Append_To (Decls, Current_Stubs); Analyze (Current_Stubs); -- Build RAS proxy Add_RAS_Proxy_And_Analyze (Decls, Vis_Decl => Decl, All_Calls_Remote_E => All_Calls_Remote_E, Proxy_Object_Addr => Proxy_Obj_Addr); -- Compute distribution identifier Assign_Subprogram_Identifier (Subp_Def, Current_Subp_Number, Subp_Val); pragma Assert (Current_Subp_Number = Get_Subprogram_Id (Subp_Def)); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Subp_Dist_Name, Constant_Present => True, Object_Definition => New_Occurrence_Of (Standard_String, Loc), Expression => Make_String_Literal (Loc, Subp_Val))); Analyze (Last (Decls)); -- Add subprogram descriptor (RCI_Subp_Info) to the subprograms -- table for this receiver. The aggregate below must be kept -- consistent with the declaration of RCI_Subp_Info in -- System.Partition_Interface. Append_To (Subp_Info_List, Make_Component_Association (Loc, Choices => New_List (Make_Integer_Literal (Loc, Current_Subp_Number)), Expression => Make_Aggregate (Loc, Expressions => New_List ( -- Name => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Subp_Dist_Name, Loc), Attribute_Name => Name_Address), -- Name_Length => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Subp_Dist_Name, Loc), Attribute_Name => Name_Length), -- Addr => New_Occurrence_Of (Proxy_Obj_Addr, Loc))))); Append_Stubs_To (Pkg_RPC_Receiver_Cases, Declaration => Decl, Stubs => Current_Stubs, Subp_Number => Current_Subp_Number, Subp_Dist_Name => Subp_Dist_Name, Subp_Proxy_Addr => Proxy_Obj_Addr); Current_Subp_Number := Current_Subp_Number + 1; end Visit_Subprogram; procedure Visit_Spec is new Build_Package_Stubs (Visit_Subprogram); -- Start of processing for Add_Receiving_Stubs_To_Declarations begin -- Building receiving stubs consist in several operations: -- - a package RPC receiver must be built. This subprogram will get -- a Subprogram_Id from the incoming stream and will dispatch the -- call to the right subprogram; -- - a receiving stub for each subprogram visible in the package -- spec. This stub will read all the parameters from the stream, -- and put the result as well as the exception occurrence in the -- output stream; Build_RPC_Receiver_Body ( RPC_Receiver => Pkg_RPC_Receiver, Request => Request, Subp_Id => Subp_Id, Subp_Index => Subp_Index, Stmts => Pkg_RPC_Receiver_Statements, Decl => Pkg_RPC_Receiver_Body); Pkg_RPC_Receiver_Decls := Declarations (Pkg_RPC_Receiver_Body); -- Extract local address information from the target reference: -- if non-null, that means that this is a reference that denotes -- one particular operation, and hence that the operation name -- must not be taken into account for dispatching. Append_To (Pkg_RPC_Receiver_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Is_Local, Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc))); Append_To (Pkg_RPC_Receiver_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Local_Address, Object_Definition => New_Occurrence_Of (RTE (RE_Address), Loc))); Append_To (Pkg_RPC_Receiver_Statements, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Get_Local_Address), Loc), Parameter_Associations => New_List ( Make_Selected_Component (Loc, Prefix => Request, Selector_Name => Name_Target), New_Occurrence_Of (Is_Local, Loc), New_Occurrence_Of (Local_Address, Loc)))); -- For each subprogram, the receiving stub will be built and a case -- statement will be made on the Subprogram_Id to dispatch to the -- right subprogram. All_Calls_Remote_E := Boolean_Literals ( Has_All_Calls_Remote (Defining_Entity (Pkg_Spec))); Overload_Counter_Table.Reset; Reserve_NamingContext_Methods; Visit_Spec (Pkg_Spec); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Subp_Info_Array, Constant_Present => True, Aliased_Present => True, Object_Definition => Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (RTE (RE_RCI_Subp_Info_Array), Loc), Constraint => Make_Index_Or_Discriminant_Constraint (Loc, New_List ( Make_Range (Loc, Low_Bound => Make_Integer_Literal (Loc, Intval => First_RCI_Subprogram_Id), High_Bound => Make_Integer_Literal (Loc, Intval => First_RCI_Subprogram_Id + List_Length (Subp_Info_List) - 1))))))); if Present (First (Subp_Info_List)) then Set_Expression (Last (Decls), Make_Aggregate (Loc, Component_Associations => Subp_Info_List)); -- Generate the dispatch statement to determine the subprogram id -- of the called subprogram. -- We first test whether the reference that was used to make the -- call was the base RCI reference (in which case Local_Address is -- zero, and the method identifier from the request must be used -- to determine which subprogram is called) or a reference -- identifying one particular subprogram (in which case -- Local_Address is the address of that subprogram, and the -- method name from the request is ignored). The latter occurs -- for the case of a call through a remote access-to-subprogram. -- In each case, cascaded elsifs are used to determine the proper -- subprogram index. Using hash tables might be more efficient. Append_To (Pkg_RPC_Receiver_Statements, Make_Implicit_If_Statement (Pkg_Spec, Condition => Make_Op_Ne (Loc, Left_Opnd => New_Occurrence_Of (Local_Address, Loc), Right_Opnd => New_Occurrence_Of (RTE (RE_Null_Address), Loc)), Then_Statements => New_List ( Make_Implicit_If_Statement (Pkg_Spec, Condition => New_Occurrence_Of (Standard_False, Loc), Then_Statements => New_List ( Make_Null_Statement (Loc)), Elsif_Parts => Dispatch_On_Address)), Else_Statements => New_List ( Make_Implicit_If_Statement (Pkg_Spec, Condition => New_Occurrence_Of (Standard_False, Loc), Then_Statements => New_List (Make_Null_Statement (Loc)), Elsif_Parts => Dispatch_On_Name)))); else -- For a degenerate RCI with no visible subprograms, -- Subp_Info_List has zero length, and the declaration is for an -- empty array, in which case no initialization aggregate must be -- generated. We do not generate a Dispatch_Statement either. -- No initialization provided: remove CONSTANT so that the -- declaration is not an incomplete deferred constant. Set_Constant_Present (Last (Decls), False); end if; -- Analyze Subp_Info_Array declaration Analyze (Last (Decls)); -- If we receive an invalid Subprogram_Id, it is best to do nothing -- rather than raising an exception since we do not want someone -- to crash a remote partition by sending invalid subprogram ids. -- This is consistent with the other parts of the case statement -- since even in presence of incorrect parameters in the stream, -- every exception will be caught and (if the subprogram is not an -- APC) put into the result stream and sent away. Append_To (Pkg_RPC_Receiver_Cases, Make_Case_Statement_Alternative (Loc, Discrete_Choices => New_List (Make_Others_Choice (Loc)), Statements => New_List (Make_Null_Statement (Loc)))); Append_To (Pkg_RPC_Receiver_Statements, Make_Case_Statement (Loc, Expression => New_Occurrence_Of (Subp_Index, Loc), Alternatives => Pkg_RPC_Receiver_Cases)); -- Pkg_RPC_Receiver body is now complete: insert it into the tree and -- analyze it. Append_To (Decls, Pkg_RPC_Receiver_Body); Analyze (Last (Decls)); Pkg_RPC_Receiver_Object := Make_Object_Declaration (Loc, Defining_Identifier => Make_Temporary (Loc, 'R'), Aliased_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Servant), Loc)); Append_To (Decls, Pkg_RPC_Receiver_Object); Analyze (Last (Decls)); -- Name Append_To (Register_Pkg_Actuals, Make_String_Literal (Loc, Strval => Fully_Qualified_Name_String (Defining_Entity (Pkg_Spec), Append_NUL => False))); -- Version Append_To (Register_Pkg_Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Defining_Entity (Pkg_Spec), Loc), Attribute_Name => Name_Version)); -- Handler Append_To (Register_Pkg_Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Pkg_RPC_Receiver, Loc), Attribute_Name => Name_Access)); -- Receiver Append_To (Register_Pkg_Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of ( Defining_Identifier (Pkg_RPC_Receiver_Object), Loc), Attribute_Name => Name_Access)); -- Subp_Info Append_To (Register_Pkg_Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Subp_Info_Array, Loc), Attribute_Name => Name_Address)); -- Subp_Info_Len Append_To (Register_Pkg_Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Subp_Info_Array, Loc), Attribute_Name => Name_Length)); -- Is_All_Calls_Remote Append_To (Register_Pkg_Actuals, New_Occurrence_Of (All_Calls_Remote_E, Loc)); -- Finally call Register_Pkg_Receiving_Stub with the above parameters Append_To (Stmts, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Register_Pkg_Receiving_Stub), Loc), Parameter_Associations => Register_Pkg_Actuals)); Analyze (Last (Stmts)); end Add_Receiving_Stubs_To_Declarations; --------------------------------- -- Build_General_Calling_Stubs -- --------------------------------- procedure Build_General_Calling_Stubs (Decls : List_Id; Statements : List_Id; Target_Object : Node_Id; Subprogram_Id : Node_Id; Asynchronous : Node_Id := Empty; Is_Known_Asynchronous : Boolean := False; Is_Known_Non_Asynchronous : Boolean := False; Is_Function : Boolean; Spec : Node_Id; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Nod : Node_Id) is Loc : constant Source_Ptr := Sloc (Nod); Request : constant Entity_Id := Make_Temporary (Loc, 'R'); -- The request object constructed by these stubs -- Could we use Name_R instead??? (see GLADE client stubs) function Make_Request_RTE_Call (RE : RE_Id; Actuals : List_Id := New_List) return Node_Id; -- Generate a procedure call statement calling RE with the given -- actuals. Request'Access is appended to the list. --------------------------- -- Make_Request_RTE_Call -- --------------------------- function Make_Request_RTE_Call (RE : RE_Id; Actuals : List_Id := New_List) return Node_Id is begin Append_To (Actuals, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Request, Loc), Attribute_Name => Name_Access)); return Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE), Loc), Parameter_Associations => Actuals); end Make_Request_RTE_Call; Arguments : Node_Id; -- Name of the named values list used to transmit parameters -- to the remote package Result : Node_Id; -- Name of the result named value (in non-APC cases) which get the -- result of the remote subprogram. Result_TC : Node_Id; -- Typecode expression for the result of the request (void -- typecode for procedures). Exception_Return_Parameter : Node_Id; -- Name of the parameter which will hold the exception sent by the -- remote subprogram. Current_Parameter : Node_Id; -- Current parameter being handled Ordered_Parameters_List : constant List_Id := Build_Ordered_Parameters_List (Spec); Asynchronous_P : Node_Id; -- A Boolean expression indicating whether this call is asynchronous Asynchronous_Statements : List_Id := No_List; Non_Asynchronous_Statements : List_Id := No_List; -- Statements specifics to the Asynchronous/Non-Asynchronous cases Extra_Formal_Statements : constant List_Id := New_List; -- List of statements for extra formal parameters. It will appear -- after the regular statements for writing out parameters. After_Statements : constant List_Id := New_List; -- Statements to be executed after call returns (to assign IN OUT or -- OUT parameter values). Etyp : Entity_Id; -- The type of the formal parameter being processed Is_Controlling_Formal : Boolean; Is_First_Controlling_Formal : Boolean; First_Controlling_Formal_Seen : Boolean := False; -- Controlling formal parameters of distributed object primitives -- require special handling, and the first such parameter needs even -- more special handling. begin -- ??? document general form of stub subprograms for the PolyORB case Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Request, Aliased_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Request), Loc))); Result := Make_Temporary (Loc, 'R'); if Is_Function then Result_TC := PolyORB_Support.Helpers.Build_TypeCode_Call (Loc, Etype (Result_Definition (Spec)), Decls); else Result_TC := New_Occurrence_Of (RTE (RE_TC_Void), Loc); end if; Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Result, Aliased_Present => False, Object_Definition => New_Occurrence_Of (RTE (RE_NamedValue), Loc), Expression => Make_Aggregate (Loc, Component_Associations => New_List ( Make_Component_Association (Loc, Choices => New_List (Make_Identifier (Loc, Name_Name)), Expression => New_Occurrence_Of (RTE (RE_Result_Name), Loc)), Make_Component_Association (Loc, Choices => New_List ( Make_Identifier (Loc, Name_Argument)), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Create_Any), Loc), Parameter_Associations => New_List (Result_TC))), Make_Component_Association (Loc, Choices => New_List ( Make_Identifier (Loc, Name_Arg_Modes)), Expression => Make_Integer_Literal (Loc, 0)))))); if not Is_Known_Asynchronous then Exception_Return_Parameter := Make_Temporary (Loc, 'E'); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Exception_Return_Parameter, Object_Definition => New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc))); else Exception_Return_Parameter := Empty; end if; -- Initialize and fill in arguments list Arguments := Make_Temporary (Loc, 'A'); Declare_Create_NVList (Loc, Arguments, Decls, Statements); Current_Parameter := First (Ordered_Parameters_List); while Present (Current_Parameter) loop if Is_RACW_Controlling_Formal (Current_Parameter, Stub_Type) then Is_Controlling_Formal := True; Is_First_Controlling_Formal := not First_Controlling_Formal_Seen; First_Controlling_Formal_Seen := True; else Is_Controlling_Formal := False; Is_First_Controlling_Formal := False; end if; if Is_Controlling_Formal then -- For a controlling formal argument, we send its reference Etyp := RACW_Type; else Etyp := Etype (Parameter_Type (Current_Parameter)); end if; -- The first controlling formal parameter is treated specially: -- it is used to set the target object of the call. if not Is_First_Controlling_Formal then declare Constrained : constant Boolean := Is_Constrained (Etyp) or else Is_Elementary_Type (Etyp); Any : constant Entity_Id := Make_Temporary (Loc, 'A'); Actual_Parameter : Node_Id := New_Occurrence_Of ( Defining_Identifier ( Current_Parameter), Loc); Expr : Node_Id; begin if Is_Controlling_Formal then -- For a controlling formal parameter (other than the -- first one), use the corresponding RACW. If the -- parameter is not an anonymous access parameter, that -- involves taking its 'Unrestricted_Access. if Nkind (Parameter_Type (Current_Parameter)) = N_Access_Definition then Actual_Parameter := OK_Convert_To (Etyp, Actual_Parameter); else Actual_Parameter := OK_Convert_To (Etyp, Make_Attribute_Reference (Loc, Prefix => Actual_Parameter, Attribute_Name => Name_Unrestricted_Access)); end if; end if; if In_Present (Current_Parameter) or else not Out_Present (Current_Parameter) or else not Constrained or else Is_Controlling_Formal then -- The parameter has an input value, is constrained at -- runtime by an input value, or is a controlling formal -- parameter (always passed as a reference) other than -- the first one. Expr := PolyORB_Support.Helpers.Build_To_Any_Call (Loc, Actual_Parameter, Decls); else Expr := Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Create_Any), Loc), Parameter_Associations => New_List ( PolyORB_Support.Helpers.Build_TypeCode_Call (Loc, Etyp, Decls))); end if; Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Any, Aliased_Present => False, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc), Expression => Expr)); Append_To (Statements, Add_Parameter_To_NVList (Loc, Parameter => Current_Parameter, NVList => Arguments, Constrained => Constrained, Any => Any)); if Out_Present (Current_Parameter) and then not Is_Controlling_Formal then if Is_Limited_Type (Etyp) then Helpers.Assign_Opaque_From_Any (Loc, Stms => After_Statements, Typ => Etyp, N => New_Occurrence_Of (Any, Loc), Target => Defining_Identifier (Current_Parameter), Constrained => True); else Append_To (After_Statements, Make_Assignment_Statement (Loc, Name => New_Occurrence_Of ( Defining_Identifier (Current_Parameter), Loc), Expression => PolyORB_Support.Helpers.Build_From_Any_Call (Etyp, New_Occurrence_Of (Any, Loc), Decls))); end if; end if; end; end if; -- If the current parameter has a dynamic constrained status, then -- this status is transmitted as well. -- This should be done for accessibility as well ??? if Nkind (Parameter_Type (Current_Parameter)) /= N_Access_Definition and then Need_Extra_Constrained (Current_Parameter) then -- In this block, we do not use the extra formal that has been -- created because it does not exist at the time of expansion -- when building calling stubs for remote access to subprogram -- types. We create an extra variable of this type and push it -- in the stream after the regular parameters. declare Extra_Any_Parameter : constant Entity_Id := Make_Temporary (Loc, 'P'); Parameter_Exp : constant Node_Id := Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of ( Defining_Identifier (Current_Parameter), Loc), Attribute_Name => Name_Constrained); begin Set_Etype (Parameter_Exp, Etype (Standard_Boolean)); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Extra_Any_Parameter, Aliased_Present => False, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc), Expression => PolyORB_Support.Helpers.Build_To_Any_Call (Loc, Parameter_Exp, Decls))); Append_To (Extra_Formal_Statements, Add_Parameter_To_NVList (Loc, Parameter => Extra_Any_Parameter, NVList => Arguments, Constrained => True, Any => Extra_Any_Parameter)); end; end if; Next (Current_Parameter); end loop; -- Append the formal statements list to the statements Append_List_To (Statements, Extra_Formal_Statements); Append_To (Statements, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Request_Setup), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Request, Loc), Target_Object, Subprogram_Id, New_Occurrence_Of (Arguments, Loc), New_Occurrence_Of (Result, Loc), New_Occurrence_Of (RTE (RE_Nil_Exc_List), Loc)))); pragma Assert (not (Is_Known_Non_Asynchronous and Is_Known_Asynchronous)); if Is_Known_Non_Asynchronous or Is_Known_Asynchronous then Asynchronous_P := New_Occurrence_Of (Boolean_Literals (Is_Known_Asynchronous), Loc); else pragma Assert (Present (Asynchronous)); Asynchronous_P := New_Copy_Tree (Asynchronous); -- The expression node Asynchronous will be used to build an 'if' -- statement at the end of Build_General_Calling_Stubs: we need to -- make a copy here. end if; Append_To (Parameter_Associations (Last (Statements)), Make_Indexed_Component (Loc, Prefix => New_Occurrence_Of ( RTE (RE_Asynchronous_P_To_Sync_Scope), Loc), Expressions => New_List (Asynchronous_P))); Append_To (Statements, Make_Request_RTE_Call (RE_Request_Invoke)); -- Asynchronous case if not Is_Known_Non_Asynchronous then Asynchronous_Statements := New_List (Make_Null_Statement (Loc)); end if; -- Non-asynchronous case if not Is_Known_Asynchronous then -- Reraise an exception occurrence from the completed request. -- If the exception occurrence is empty, this is a no-op. Non_Asynchronous_Statements := New_List ( Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Request_Raise_Occurrence), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Request, Loc)))); if Is_Function then -- If this is a function call, read the value and return it Append_To (Non_Asynchronous_Statements, Make_Tag_Check (Loc, Make_Simple_Return_Statement (Loc, PolyORB_Support.Helpers.Build_From_Any_Call (Etype (Result_Definition (Spec)), Make_Selected_Component (Loc, Prefix => Result, Selector_Name => Name_Argument), Decls)))); else -- Case of a procedure: deal with IN OUT and OUT formals Append_List_To (Non_Asynchronous_Statements, After_Statements); end if; end if; if Is_Known_Asynchronous then Append_List_To (Statements, Asynchronous_Statements); elsif Is_Known_Non_Asynchronous then Append_List_To (Statements, Non_Asynchronous_Statements); else pragma Assert (Present (Asynchronous)); Append_To (Statements, Make_Implicit_If_Statement (Nod, Condition => Asynchronous, Then_Statements => Asynchronous_Statements, Else_Statements => Non_Asynchronous_Statements)); end if; end Build_General_Calling_Stubs; ----------------------- -- Build_Stub_Target -- ----------------------- function Build_Stub_Target (Loc : Source_Ptr; Decls : List_Id; RCI_Locator : Entity_Id; Controlling_Parameter : Entity_Id) return RPC_Target is Target_Info : RPC_Target (PCS_Kind => Name_PolyORB_DSA); Target_Reference : constant Entity_Id := Make_Temporary (Loc, 'T'); begin if Present (Controlling_Parameter) then Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Target_Reference, Object_Definition => New_Occurrence_Of (RTE (RE_Object_Ref), Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Make_Ref), Loc), Parameter_Associations => New_List ( Make_Selected_Component (Loc, Prefix => Controlling_Parameter, Selector_Name => Name_Target))))); -- Note: Controlling_Parameter has the same components as -- System.Partition_Interface.RACW_Stub_Type. Target_Info.Object := New_Occurrence_Of (Target_Reference, Loc); else Target_Info.Object := Make_Selected_Component (Loc, Prefix => Make_Identifier (Loc, Chars (RCI_Locator)), Selector_Name => Make_Identifier (Loc, Name_Get_RCI_Package_Ref)); end if; return Target_Info; end Build_Stub_Target; ----------------------------- -- Build_RPC_Receiver_Body -- ----------------------------- procedure Build_RPC_Receiver_Body (RPC_Receiver : Entity_Id; Request : out Entity_Id; Subp_Id : out Entity_Id; Subp_Index : out Entity_Id; Stmts : out List_Id; Decl : out Node_Id) is Loc : constant Source_Ptr := Sloc (RPC_Receiver); RPC_Receiver_Spec : Node_Id; RPC_Receiver_Decls : List_Id; begin Request := Make_Defining_Identifier (Loc, Name_R); RPC_Receiver_Spec := Build_RPC_Receiver_Specification (RPC_Receiver => RPC_Receiver, Request_Parameter => Request); Subp_Id := Make_Defining_Identifier (Loc, Name_P); Subp_Index := Make_Defining_Identifier (Loc, Name_I); RPC_Receiver_Decls := New_List ( Make_Object_Renaming_Declaration (Loc, Defining_Identifier => Subp_Id, Subtype_Mark => New_Occurrence_Of (Standard_String, Loc), Name => Make_Explicit_Dereference (Loc, Prefix => Make_Selected_Component (Loc, Prefix => Request, Selector_Name => Name_Operation))), Make_Object_Declaration (Loc, Defining_Identifier => Subp_Index, Object_Definition => New_Occurrence_Of (RTE (RE_Subprogram_Id), Loc), Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (RTE (RE_Subprogram_Id), Loc), Attribute_Name => Name_Last))); Stmts := New_List; Decl := Make_Subprogram_Body (Loc, Specification => RPC_Receiver_Spec, Declarations => RPC_Receiver_Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)); end Build_RPC_Receiver_Body; -------------------------------------- -- Build_Subprogram_Receiving_Stubs -- -------------------------------------- function Build_Subprogram_Receiving_Stubs (Vis_Decl : Node_Id; Asynchronous : Boolean; Dynamically_Asynchronous : Boolean := False; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Parent_Primitive : Entity_Id := Empty) return Node_Id is Loc : constant Source_Ptr := Sloc (Vis_Decl); Request_Parameter : constant Entity_Id := Make_Temporary (Loc, 'R'); -- Formal parameter for receiving stubs: a descriptor for an incoming -- request. Outer_Decls : constant List_Id := New_List; -- At the outermost level, an NVList and Any's are declared for all -- parameters. The Dynamic_Async flag also needs to be declared there -- to be visible from the exception handling code. Outer_Statements : constant List_Id := New_List; -- Statements that occur prior to the declaration of the actual -- parameter variables. Outer_Extra_Formal_Statements : constant List_Id := New_List; -- Statements concerning extra formal parameters, prior to the -- declaration of the actual parameter variables. Decls : constant List_Id := New_List; -- All the parameters will get declared before calling the real -- subprograms. Also the out parameters will be declared. At this -- level, parameters may be unconstrained. Statements : constant List_Id := New_List; After_Statements : constant List_Id := New_List; -- Statements to be executed after the subprogram call Inner_Decls : List_Id := No_List; -- In case of a function, the inner declarations are needed since -- the result may be unconstrained. Excep_Handlers : List_Id := No_List; Parameter_List : constant List_Id := New_List; -- List of parameters to be passed to the subprogram First_Controlling_Formal_Seen : Boolean := False; Current_Parameter : Node_Id; Ordered_Parameters_List : constant List_Id := Build_Ordered_Parameters_List (Specification (Vis_Decl)); Arguments : constant Entity_Id := Make_Temporary (Loc, 'A'); -- Name of the named values list used to retrieve parameters Subp_Spec : Node_Id; -- Subprogram specification Called_Subprogram : Node_Id; -- The subprogram to call begin if Present (RACW_Type) then Called_Subprogram := New_Occurrence_Of (Parent_Primitive, Loc); else Called_Subprogram := New_Occurrence_Of (Defining_Unit_Name (Specification (Vis_Decl)), Loc); end if; Declare_Create_NVList (Loc, Arguments, Outer_Decls, Outer_Statements); -- Loop through every parameter and get its value from the stream. If -- the parameter is unconstrained, then the parameter is read using -- 'Input at the point of declaration. Current_Parameter := First (Ordered_Parameters_List); while Present (Current_Parameter) loop declare Etyp : Entity_Id; Constrained : Boolean; Any : Entity_Id := Empty; Object : constant Entity_Id := Make_Temporary (Loc, 'P'); Expr : Node_Id := Empty; Is_Controlling_Formal : constant Boolean := Is_RACW_Controlling_Formal (Current_Parameter, Stub_Type); Is_First_Controlling_Formal : Boolean := False; Need_Extra_Constrained : Boolean; -- True when an extra constrained actual is required begin if Is_Controlling_Formal then -- Controlling formals in distributed object primitive -- operations are handled specially: -- - the first controlling formal is used as the -- target of the call; -- - the remaining controlling formals are transmitted -- as RACWs. Etyp := RACW_Type; Is_First_Controlling_Formal := not First_Controlling_Formal_Seen; First_Controlling_Formal_Seen := True; else Etyp := Etype (Parameter_Type (Current_Parameter)); end if; Constrained := Is_Constrained (Etyp) or else Is_Elementary_Type (Etyp); if not Is_First_Controlling_Formal then Any := Make_Temporary (Loc, 'A'); Append_To (Outer_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Any, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Create_Any), Loc), Parameter_Associations => New_List ( PolyORB_Support.Helpers.Build_TypeCode_Call (Loc, Etyp, Outer_Decls))))); Append_To (Outer_Statements, Add_Parameter_To_NVList (Loc, Parameter => Current_Parameter, NVList => Arguments, Constrained => Constrained, Any => Any)); end if; if Is_First_Controlling_Formal then declare Addr : constant Entity_Id := Make_Temporary (Loc, 'A'); Is_Local : constant Entity_Id := Make_Temporary (Loc, 'L'); begin -- Special case: obtain the first controlling formal -- from the target of the remote call, instead of the -- argument list. Append_To (Outer_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Addr, Object_Definition => New_Occurrence_Of (RTE (RE_Address), Loc))); Append_To (Outer_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Is_Local, Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc))); Append_To (Outer_Statements, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Get_Local_Address), Loc), Parameter_Associations => New_List ( Make_Selected_Component (Loc, Prefix => New_Occurrence_Of ( Request_Parameter, Loc), Selector_Name => Make_Identifier (Loc, Name_Target)), New_Occurrence_Of (Is_Local, Loc), New_Occurrence_Of (Addr, Loc)))); Expr := Unchecked_Convert_To (RACW_Type, New_Occurrence_Of (Addr, Loc)); end; elsif In_Present (Current_Parameter) or else not Out_Present (Current_Parameter) or else not Constrained then -- If an input parameter is constrained, then its reading is -- deferred until the beginning of the subprogram body. If -- it is unconstrained, then an expression is built for -- the object declaration and the variable is set using -- 'Input instead of 'Read. if Constrained and then Is_Limited_Type (Etyp) then Helpers.Assign_Opaque_From_Any (Loc, Stms => Statements, Typ => Etyp, N => New_Occurrence_Of (Any, Loc), Target => Object); else Expr := Helpers.Build_From_Any_Call (Etyp, New_Occurrence_Of (Any, Loc), Decls); if Constrained then Append_To (Statements, Make_Assignment_Statement (Loc, Name => New_Occurrence_Of (Object, Loc), Expression => Expr)); Expr := Empty; else -- Expr will be used to initialize (and constrain) the -- parameter when it is declared. null; end if; null; end if; end if; Need_Extra_Constrained := Nkind (Parameter_Type (Current_Parameter)) /= N_Access_Definition and then Ekind (Defining_Identifier (Current_Parameter)) /= E_Void and then Present (Extra_Constrained (Defining_Identifier (Current_Parameter))); -- We may not associate an extra constrained actual to a -- constant object, so if one is needed, declare the actual -- as a variable even if it won't be modified. Build_Actual_Object_Declaration (Object => Object, Etyp => Etyp, Variable => Need_Extra_Constrained or else Out_Present (Current_Parameter), Expr => Expr, Decls => Decls); Set_Etype (Object, Etyp); -- An out parameter may be written back using a 'Write -- attribute instead of a 'Output because it has been -- constrained by the parameter given to the caller. Note that -- OUT controlling arguments in the case of a RACW are not put -- back in the stream because the pointer on them has not -- changed. if Out_Present (Current_Parameter) and then not Is_Controlling_Formal then Append_To (After_Statements, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Move_Any_Value), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc), PolyORB_Support.Helpers.Build_To_Any_Call (Loc, New_Occurrence_Of (Object, Loc), Decls, Constrained => True)))); end if; -- For RACW controlling formals, the Etyp of Object is always -- an RACW, even if the parameter is not of an anonymous access -- type. In such case, we need to dereference it at call time. if Is_Controlling_Formal then if Nkind (Parameter_Type (Current_Parameter)) /= N_Access_Definition then Append_To (Parameter_List, Make_Parameter_Association (Loc, Selector_Name => New_Occurrence_Of (Defining_Identifier (Current_Parameter), Loc), Explicit_Actual_Parameter => Make_Explicit_Dereference (Loc, Prefix => New_Occurrence_Of (Object, Loc)))); else Append_To (Parameter_List, Make_Parameter_Association (Loc, Selector_Name => New_Occurrence_Of (Defining_Identifier (Current_Parameter), Loc), Explicit_Actual_Parameter => New_Occurrence_Of (Object, Loc))); end if; else Append_To (Parameter_List, Make_Parameter_Association (Loc, Selector_Name => New_Occurrence_Of ( Defining_Identifier (Current_Parameter), Loc), Explicit_Actual_Parameter => New_Occurrence_Of (Object, Loc))); end if; -- If the current parameter needs an extra formal, then read it -- from the stream and set the corresponding semantic field in -- the variable. If the kind of the parameter identifier is -- E_Void, then this is a compiler generated parameter that -- doesn't need an extra constrained status. -- The case of Extra_Accessibility should also be handled ??? if Need_Extra_Constrained then declare Extra_Parameter : constant Entity_Id := Extra_Constrained (Defining_Identifier (Current_Parameter)); Extra_Any : constant Entity_Id := Make_Temporary (Loc, 'A'); Formal_Entity : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Chars (Extra_Parameter)); Formal_Type : constant Entity_Id := Etype (Extra_Parameter); begin Append_To (Outer_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Extra_Any, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Create_Any), Loc), Parameter_Associations => New_List ( PolyORB_Support.Helpers.Build_TypeCode_Call (Loc, Formal_Type, Outer_Decls))))); Append_To (Outer_Extra_Formal_Statements, Add_Parameter_To_NVList (Loc, Parameter => Extra_Parameter, NVList => Arguments, Constrained => True, Any => Extra_Any)); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Formal_Entity, Object_Definition => New_Occurrence_Of (Formal_Type, Loc))); Append_To (Statements, Make_Assignment_Statement (Loc, Name => New_Occurrence_Of (Formal_Entity, Loc), Expression => PolyORB_Support.Helpers.Build_From_Any_Call (Formal_Type, New_Occurrence_Of (Extra_Any, Loc), Decls))); Set_Extra_Constrained (Object, Formal_Entity); end; end if; end; Next (Current_Parameter); end loop; -- Extra Formals should go after all the other parameters Append_List_To (Outer_Statements, Outer_Extra_Formal_Statements); Append_To (Outer_Statements, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Request_Arguments), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Request_Parameter, Loc), New_Occurrence_Of (Arguments, Loc)))); if Nkind (Specification (Vis_Decl)) = N_Function_Specification then -- The remote subprogram is a function: Build an inner block to be -- able to hold a potentially unconstrained result in a variable. declare Etyp : constant Entity_Id := Etype (Result_Definition (Specification (Vis_Decl))); Result : constant Node_Id := Make_Temporary (Loc, 'R'); begin Inner_Decls := New_List ( Make_Object_Declaration (Loc, Defining_Identifier => Result, Constant_Present => True, Object_Definition => New_Occurrence_Of (Etyp, Loc), Expression => Make_Function_Call (Loc, Name => Called_Subprogram, Parameter_Associations => Parameter_List))); if Is_Class_Wide_Type (Etyp) then -- For a remote call to a function with a class-wide type, -- check that the returned value satisfies the requirements -- of (RM E.4(18)). Append_To (Inner_Decls, Make_Transportable_Check (Loc, New_Occurrence_Of (Result, Loc))); end if; Set_Etype (Result, Etyp); Append_To (After_Statements, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Set_Result), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Request_Parameter, Loc), PolyORB_Support.Helpers.Build_To_Any_Call (Loc, New_Occurrence_Of (Result, Loc), Decls)))); -- A DSA function does not have out or inout arguments end; Append_To (Statements, Make_Block_Statement (Loc, Declarations => Inner_Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => After_Statements))); else -- The remote subprogram is a procedure. We do not need any inner -- block in this case. No specific processing is required here for -- the dynamically asynchronous case: the indication of whether -- call is asynchronous or not is managed by the Sync_Scope -- attibute of the request, and is handled entirely in the -- protocol layer. Append_To (After_Statements, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Request_Set_Out), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Request_Parameter, Loc)))); Append_To (Statements, Make_Procedure_Call_Statement (Loc, Name => Called_Subprogram, Parameter_Associations => Parameter_List)); Append_List_To (Statements, After_Statements); end if; Subp_Spec := Make_Procedure_Specification (Loc, Defining_Unit_Name => Make_Temporary (Loc, 'F'), Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Request_Parameter, Parameter_Type => New_Occurrence_Of (RTE (RE_Request_Access), Loc)))); -- An exception raised during the execution of an incoming remote -- subprogram call and that needs to be sent back to the caller is -- propagated by the receiving stubs, and will be handled by the -- caller (the distribution runtime). if Asynchronous and then not Dynamically_Asynchronous then -- For an asynchronous procedure, add a null exception handler Excep_Handlers := New_List ( Make_Implicit_Exception_Handler (Loc, Exception_Choices => New_List (Make_Others_Choice (Loc)), Statements => New_List (Make_Null_Statement (Loc)))); else -- In the other cases, if an exception is raised, then the -- exception occurrence is propagated. null; end if; Append_To (Outer_Statements, Make_Block_Statement (Loc, Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Statements))); return Make_Subprogram_Body (Loc, Specification => Subp_Spec, Declarations => Outer_Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Outer_Statements, Exception_Handlers => Excep_Handlers)); end Build_Subprogram_Receiving_Stubs; ------------- -- Helpers -- ------------- package body Helpers is ----------------------- -- Local Subprograms -- ----------------------- function Find_Numeric_Representation (Typ : Entity_Id) return Entity_Id; -- Given a numeric type Typ, return the smallest integer or modular -- type from Interfaces, or the smallest floating point type from -- Standard whose range encompasses that of Typ. function Make_Helper_Function_Name (Loc : Source_Ptr; Typ : Entity_Id; Nam : Name_Id) return Entity_Id; -- Return the name to be assigned for helper subprogram Nam of Typ ------------------------------------------------------------ -- Common subprograms for building various tree fragments -- ------------------------------------------------------------ function Build_Get_Aggregate_Element (Loc : Source_Ptr; Any : Entity_Id; TC : Node_Id; Idx : Node_Id) return Node_Id; -- Build a call to Get_Aggregate_Element on Any for typecode TC, -- returning the Idx'th element. generic Subprogram : Entity_Id; -- Reference location for constructed nodes Arry : Entity_Id; -- For 'Range and Etype Indexes : List_Id; -- For the construction of the innermost element expression with procedure Add_Process_Element (Stmts : List_Id; Any : Entity_Id; Counter : Entity_Id; Datum : Node_Id); procedure Append_Array_Traversal (Stmts : List_Id; Any : Entity_Id; Counter : Entity_Id := Empty; Depth : Pos := 1); -- Build nested loop statements that iterate over the elements of an -- array Arry. The statement(s) built by Add_Process_Element are -- executed for each element; Indexes is the list of indexes to be -- used in the construction of the indexed component that denotes the -- current element. Subprogram is the entity for the subprogram for -- which this iterator is generated. The generated statements are -- appended to Stmts. generic Rec : Entity_Id; -- The record entity being dealt with with procedure Add_Process_Element (Stmts : List_Id; Container : Node_Or_Entity_Id; Counter : in out Int; Rec : Entity_Id; Field : Node_Id); -- Rec is the instance of the record type, or Empty. -- Field is either the N_Defining_Identifier for a component, -- or an N_Variant_Part. procedure Append_Record_Traversal (Stmts : List_Id; Clist : Node_Id; Container : Node_Or_Entity_Id; Counter : in out Int); -- Process component list Clist. Individual fields are passed -- to Field_Processing. Each variant part is also processed. -- Container is the outer Any (for From_Any/To_Any), -- the outer typecode (for TC) to which the operation applies. ----------------------------- -- Append_Record_Traversal -- ----------------------------- procedure Append_Record_Traversal (Stmts : List_Id; Clist : Node_Id; Container : Node_Or_Entity_Id; Counter : in out Int) is CI : List_Id; VP : Node_Id; -- Clist's Component_Items and Variant_Part Item : Node_Id; Def : Entity_Id; begin if No (Clist) then return; end if; CI := Component_Items (Clist); VP := Variant_Part (Clist); Item := First (CI); while Present (Item) loop Def := Defining_Identifier (Item); if not Is_Internal_Name (Chars (Def)) then Add_Process_Element (Stmts, Container, Counter, Rec, Def); end if; Next (Item); end loop; if Present (VP) then Add_Process_Element (Stmts, Container, Counter, Rec, VP); end if; end Append_Record_Traversal; ----------------------------- -- Assign_Opaque_From_Any -- ----------------------------- procedure Assign_Opaque_From_Any (Loc : Source_Ptr; Stms : List_Id; Typ : Entity_Id; N : Node_Id; Target : Entity_Id; Constrained : Boolean := False) is Strm : constant Entity_Id := Make_Temporary (Loc, 'S'); Expr : Node_Id; Read_Call_List : List_Id; -- List on which to place the 'Read attribute reference begin -- Strm : Buffer_Stream_Type; Append_To (Stms, Make_Object_Declaration (Loc, Defining_Identifier => Strm, Aliased_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Buffer_Stream_Type), Loc))); -- Any_To_BS (Strm, A); Append_To (Stms, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Any_To_BS), Loc), Parameter_Associations => New_List ( N, New_Occurrence_Of (Strm, Loc)))); if Transmit_As_Unconstrained (Typ) and then not Constrained then Expr := Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Typ, Loc), Attribute_Name => Name_Input, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Strm, Loc), Attribute_Name => Name_Access))); -- Target := Typ'Input (Strm'Access) if Present (Target) then Append_To (Stms, Make_Assignment_Statement (Loc, Name => New_Occurrence_Of (Target, Loc), Expression => Expr)); -- return Typ'Input (Strm'Access); else Append_To (Stms, Make_Simple_Return_Statement (Loc, Expression => Expr)); end if; else if Present (Target) then Read_Call_List := Stms; Expr := New_Occurrence_Of (Target, Loc); else declare Temp : constant Entity_Id := Make_Temporary (Loc, 'R'); begin Read_Call_List := New_List; Expr := New_Occurrence_Of (Temp, Loc); Append_To (Stms, Make_Block_Statement (Loc, Declarations => New_List ( Make_Object_Declaration (Loc, Defining_Identifier => Temp, Object_Definition => New_Occurrence_Of (Typ, Loc))), Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Read_Call_List))); end; end if; -- Typ'Read (Strm'Access, [Target|Temp]) Append_To (Read_Call_List, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Typ, Loc), Attribute_Name => Name_Read, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Strm, Loc), Attribute_Name => Name_Access), Expr))); if No (Target) then -- return Temp Append_To (Read_Call_List, Make_Simple_Return_Statement (Loc, Expression => New_Copy (Expr))); end if; end if; end Assign_Opaque_From_Any; ------------------------- -- Build_From_Any_Call -- ------------------------- function Build_From_Any_Call (Typ : Entity_Id; N : Node_Id; Decls : List_Id) return Node_Id is Loc : constant Source_Ptr := Sloc (N); U_Type : Entity_Id := Underlying_Type (Typ); Fnam : Entity_Id := Empty; Lib_RE : RE_Id := RE_Null; Result : Node_Id; begin -- First simple case where the From_Any function is present -- in the type's TSS. Fnam := Find_Inherited_TSS (U_Type, TSS_From_Any); -- For the subtype representing a generic actual type, go to the -- actual type. if Is_Generic_Actual_Type (U_Type) then U_Type := Underlying_Type (Base_Type (U_Type)); end if; -- For a standard subtype, go to the base type if Sloc (U_Type) <= Standard_Location then U_Type := Base_Type (U_Type); -- For a user subtype, go to first subtype elsif Comes_From_Source (U_Type) and then Nkind (Declaration_Node (U_Type)) = N_Subtype_Declaration then U_Type := First_Subtype (U_Type); end if; -- Check first for Boolean and Character. These are enumeration -- types, but we treat them specially, since they may require -- special handling in the transfer protocol. However, this -- special handling only applies if they have standard -- representation, otherwise they are treated like any other -- enumeration type. if Present (Fnam) then null; elsif U_Type = Standard_Boolean then Lib_RE := RE_FA_B; elsif U_Type = Standard_Character then Lib_RE := RE_FA_C; elsif U_Type = Standard_Wide_Character then Lib_RE := RE_FA_WC; elsif U_Type = Standard_Wide_Wide_Character then Lib_RE := RE_FA_WWC; -- Floating point types elsif U_Type = Standard_Short_Float then Lib_RE := RE_FA_SF; elsif U_Type = Standard_Float then Lib_RE := RE_FA_F; elsif U_Type = Standard_Long_Float then Lib_RE := RE_FA_LF; elsif U_Type = Standard_Long_Long_Float then Lib_RE := RE_FA_LLF; -- Integer types elsif U_Type = RTE (RE_Integer_8) then Lib_RE := RE_FA_I8; elsif U_Type = RTE (RE_Integer_16) then Lib_RE := RE_FA_I16; elsif U_Type = RTE (RE_Integer_32) then Lib_RE := RE_FA_I32; elsif U_Type = RTE (RE_Integer_64) then Lib_RE := RE_FA_I64; -- Unsigned integer types elsif U_Type = RTE (RE_Unsigned_8) then Lib_RE := RE_FA_U8; elsif U_Type = RTE (RE_Unsigned_16) then Lib_RE := RE_FA_U16; elsif U_Type = RTE (RE_Unsigned_32) then Lib_RE := RE_FA_U32; elsif U_Type = RTE (RE_Unsigned_64) then Lib_RE := RE_FA_U64; elsif Is_RTE (U_Type, RE_Unbounded_String) then Lib_RE := RE_FA_String; -- Special DSA types elsif Is_RTE (U_Type, RE_Any_Container_Ptr) then Lib_RE := RE_FA_A; -- Other (non-primitive) types else declare Decl : Entity_Id; begin Build_From_Any_Function (Loc, U_Type, Decl, Fnam); Append_To (Decls, Decl); end; end if; -- Call the function if Lib_RE /= RE_Null then pragma Assert (No (Fnam)); Fnam := RTE (Lib_RE); end if; Result := Make_Function_Call (Loc, Name => New_Occurrence_Of (Fnam, Loc), Parameter_Associations => New_List (N)); -- We must set the type of Result, so the unchecked conversion -- from the underlying type to the base type is properly done. Set_Etype (Result, U_Type); return Unchecked_Convert_To (Typ, Result); end Build_From_Any_Call; ----------------------------- -- Build_From_Any_Function -- ----------------------------- procedure Build_From_Any_Function (Loc : Source_Ptr; Typ : Entity_Id; Decl : out Node_Id; Fnam : out Entity_Id) is Spec : Node_Id; Decls : constant List_Id := New_List; Stms : constant List_Id := New_List; Any_Parameter : constant Entity_Id := Make_Temporary (Loc, 'A'); Use_Opaque_Representation : Boolean; begin -- For a derived type, we can't go past the base type (to the -- parent type) here, because that would cause the attribute's -- formal parameter to have the wrong type; hence the Base_Type -- check here. if Is_Itype (Typ) and then Typ /= Base_Type (Typ) then Build_From_Any_Function (Loc => Loc, Typ => Etype (Typ), Decl => Decl, Fnam => Fnam); return; end if; Fnam := Make_Helper_Function_Name (Loc, Typ, Name_From_Any); Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Fnam, Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Any_Parameter, Parameter_Type => New_Occurrence_Of (RTE (RE_Any), Loc))), Result_Definition => New_Occurrence_Of (Typ, Loc)); -- The RACW case is taken care of by Exp_Dist.Add_RACW_From_Any pragma Assert (not (Is_Remote_Access_To_Class_Wide_Type (Typ))); Use_Opaque_Representation := False; if Has_Stream_Attribute_Definition (Typ, TSS_Stream_Output, At_Any_Place => True) or else Has_Stream_Attribute_Definition (Typ, TSS_Stream_Write, At_Any_Place => True) then -- If user-defined stream attributes are specified for this -- type, use them and transmit data as an opaque sequence of -- stream elements. Use_Opaque_Representation := True; elsif Is_Derived_Type (Typ) and then not Is_Tagged_Type (Typ) then Append_To (Stms, Make_Simple_Return_Statement (Loc, Expression => OK_Convert_To (Typ, Build_From_Any_Call (Root_Type (Typ), New_Occurrence_Of (Any_Parameter, Loc), Decls)))); elsif Is_Record_Type (Typ) and then not Is_Derived_Type (Typ) and then not Is_Tagged_Type (Typ) then if Nkind (Declaration_Node (Typ)) = N_Subtype_Declaration then Append_To (Stms, Make_Simple_Return_Statement (Loc, Expression => Build_From_Any_Call (Etype (Typ), New_Occurrence_Of (Any_Parameter, Loc), Decls))); else declare Disc : Entity_Id := Empty; Discriminant_Associations : List_Id; Rdef : constant Node_Id := Type_Definition (Declaration_Node (Typ)); Component_Counter : Int := 0; -- The returned object Res : constant Entity_Id := Make_Temporary (Loc, 'R'); Res_Definition : Node_Id := New_Occurrence_Of (Typ, Loc); procedure FA_Rec_Add_Process_Element (Stmts : List_Id; Any : Entity_Id; Counter : in out Int; Rec : Entity_Id; Field : Node_Id); procedure FA_Append_Record_Traversal is new Append_Record_Traversal (Rec => Res, Add_Process_Element => FA_Rec_Add_Process_Element); -------------------------------- -- FA_Rec_Add_Process_Element -- -------------------------------- procedure FA_Rec_Add_Process_Element (Stmts : List_Id; Any : Entity_Id; Counter : in out Int; Rec : Entity_Id; Field : Node_Id) is Ctyp : Entity_Id; begin if Nkind (Field) = N_Defining_Identifier then -- A regular component Ctyp := Etype (Field); Append_To (Stmts, Make_Assignment_Statement (Loc, Name => Make_Selected_Component (Loc, Prefix => New_Occurrence_Of (Rec, Loc), Selector_Name => New_Occurrence_Of (Field, Loc)), Expression => Build_From_Any_Call (Ctyp, Build_Get_Aggregate_Element (Loc, Any => Any, TC => Build_TypeCode_Call (Loc, Ctyp, Decls), Idx => Make_Integer_Literal (Loc, Counter)), Decls))); else -- A variant part declare Variant : Node_Id; Struct_Counter : Int := 0; Block_Decls : constant List_Id := New_List; Block_Stmts : constant List_Id := New_List; VP_Stmts : List_Id; Alt_List : constant List_Id := New_List; Choice_List : List_Id; Struct_Any : constant Entity_Id := Make_Temporary (Loc, 'S'); begin Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Struct_Any, Constant_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Extract_Union_Value), Loc), Parameter_Associations => New_List ( Build_Get_Aggregate_Element (Loc, Any => Any, TC => Make_Function_Call (Loc, Name => New_Occurrence_Of ( RTE (RE_Any_Member_Type), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc), Make_Integer_Literal (Loc, Intval => Counter))), Idx => Make_Integer_Literal (Loc, Intval => Counter)))))); Append_To (Stmts, Make_Block_Statement (Loc, Declarations => Block_Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Block_Stmts))); Append_To (Block_Stmts, Make_Case_Statement (Loc, Expression => Make_Selected_Component (Loc, Prefix => Rec, Selector_Name => Chars (Name (Field))), Alternatives => Alt_List)); Variant := First_Non_Pragma (Variants (Field)); while Present (Variant) loop Choice_List := New_Copy_List_Tree (Discrete_Choices (Variant)); VP_Stmts := New_List; -- Struct_Counter should be reset before -- handling a variant part. Indeed only one -- of the case statement alternatives will be -- executed at run time, so the counter must -- start at 0 for every case statement. Struct_Counter := 0; FA_Append_Record_Traversal ( Stmts => VP_Stmts, Clist => Component_List (Variant), Container => Struct_Any, Counter => Struct_Counter); Append_To (Alt_List, Make_Case_Statement_Alternative (Loc, Discrete_Choices => Choice_List, Statements => VP_Stmts)); Next_Non_Pragma (Variant); end loop; end; end if; Counter := Counter + 1; end FA_Rec_Add_Process_Element; begin -- First all discriminants if Has_Discriminants (Typ) then Discriminant_Associations := New_List; Disc := First_Discriminant (Typ); while Present (Disc) loop declare Disc_Var_Name : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => Chars (Disc)); Disc_Type : constant Entity_Id := Etype (Disc); begin Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Disc_Var_Name, Constant_Present => True, Object_Definition => New_Occurrence_Of (Disc_Type, Loc), Expression => Build_From_Any_Call (Disc_Type, Build_Get_Aggregate_Element (Loc, Any => Any_Parameter, TC => Build_TypeCode_Call (Loc, Disc_Type, Decls), Idx => Make_Integer_Literal (Loc, Intval => Component_Counter)), Decls))); Component_Counter := Component_Counter + 1; Append_To (Discriminant_Associations, Make_Discriminant_Association (Loc, Selector_Names => New_List ( New_Occurrence_Of (Disc, Loc)), Expression => New_Occurrence_Of (Disc_Var_Name, Loc))); end; Next_Discriminant (Disc); end loop; Res_Definition := Make_Subtype_Indication (Loc, Subtype_Mark => Res_Definition, Constraint => Make_Index_Or_Discriminant_Constraint (Loc, Discriminant_Associations)); end if; -- Now we have all the discriminants in variables, we can -- declared a constrained object. Note that we are not -- initializing (non-discriminant) components directly in -- the object declarations, because which fields to -- initialize depends (at run time) on the discriminant -- values. Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Res, Object_Definition => Res_Definition)); -- ... then all components FA_Append_Record_Traversal (Stms, Clist => Component_List (Rdef), Container => Any_Parameter, Counter => Component_Counter); Append_To (Stms, Make_Simple_Return_Statement (Loc, Expression => New_Occurrence_Of (Res, Loc))); end; end if; elsif Is_Array_Type (Typ) then declare Constrained : constant Boolean := Is_Constrained (Typ); procedure FA_Ary_Add_Process_Element (Stmts : List_Id; Any : Entity_Id; Counter : Entity_Id; Datum : Node_Id); -- Assign the current element (as identified by Counter) of -- Any to the variable denoted by name Datum, and advance -- Counter by 1. If Datum is not an Any, a call to From_Any -- for its type is inserted. -------------------------------- -- FA_Ary_Add_Process_Element -- -------------------------------- procedure FA_Ary_Add_Process_Element (Stmts : List_Id; Any : Entity_Id; Counter : Entity_Id; Datum : Node_Id) is Assignment : constant Node_Id := Make_Assignment_Statement (Loc, Name => Datum, Expression => Empty); Element_Any : Node_Id; begin declare Element_TC : Node_Id; begin if Etype (Datum) = RTE (RE_Any) then -- When Datum is an Any the Etype field is not -- sufficient to determine the typecode of Datum -- (which can be a TC_SEQUENCE or TC_ARRAY -- depending on the value of Constrained). -- Therefore we retrieve the typecode which has -- been constructed in Append_Array_Traversal with -- a call to Get_Any_Type. Element_TC := Make_Function_Call (Loc, Name => New_Occurrence_Of ( RTE (RE_Get_Any_Type), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Entity (Datum), Loc))); else -- For non Any Datum we simply construct a typecode -- matching the Etype of the Datum. Element_TC := Build_TypeCode_Call (Loc, Etype (Datum), Decls); end if; Element_Any := Build_Get_Aggregate_Element (Loc, Any => Any, TC => Element_TC, Idx => New_Occurrence_Of (Counter, Loc)); end; -- Note: here we *prepend* statements to Stmts, so -- we must do it in reverse order. Prepend_To (Stmts, Make_Assignment_Statement (Loc, Name => New_Occurrence_Of (Counter, Loc), Expression => Make_Op_Add (Loc, Left_Opnd => New_Occurrence_Of (Counter, Loc), Right_Opnd => Make_Integer_Literal (Loc, 1)))); if Nkind (Datum) /= N_Attribute_Reference then -- We ignore the value of the length of each -- dimension, since the target array has already been -- constrained anyway. if Etype (Datum) /= RTE (RE_Any) then Set_Expression (Assignment, Build_From_Any_Call (Component_Type (Typ), Element_Any, Decls)); else Set_Expression (Assignment, Element_Any); end if; Prepend_To (Stmts, Assignment); end if; end FA_Ary_Add_Process_Element; ------------------------ -- Local Declarations -- ------------------------ Counter : constant Entity_Id := Make_Defining_Identifier (Loc, Name_J); Initial_Counter_Value : Int := 0; Component_TC : constant Entity_Id := Make_Defining_Identifier (Loc, Name_T); Res : constant Entity_Id := Make_Defining_Identifier (Loc, Name_R); procedure Append_From_Any_Array_Iterator is new Append_Array_Traversal ( Subprogram => Fnam, Arry => Res, Indexes => New_List, Add_Process_Element => FA_Ary_Add_Process_Element); Res_Subtype_Indication : Node_Id := New_Occurrence_Of (Typ, Loc); begin if not Constrained then declare Ndim : constant Int := Number_Dimensions (Typ); Lnam : Name_Id; Hnam : Name_Id; Indx : Node_Id := First_Index (Typ); Indt : Entity_Id; Ranges : constant List_Id := New_List; begin for J in 1 .. Ndim loop Lnam := New_External_Name ('L', J); Hnam := New_External_Name ('H', J); -- Note, for empty arrays bounds may be out of -- the range of Etype (Indx). Indt := Base_Type (Etype (Indx)); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Lnam), Constant_Present => True, Object_Definition => New_Occurrence_Of (Indt, Loc), Expression => Build_From_Any_Call (Indt, Build_Get_Aggregate_Element (Loc, Any => Any_Parameter, TC => Build_TypeCode_Call (Loc, Indt, Decls), Idx => Make_Integer_Literal (Loc, J - 1)), Decls))); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Hnam), Constant_Present => True, Object_Definition => New_Occurrence_Of (Indt, Loc), Expression => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Indt, Loc), Attribute_Name => Name_Val, Expressions => New_List ( Make_Op_Subtract (Loc, Left_Opnd => Make_Op_Add (Loc, Left_Opnd => OK_Convert_To (Standard_Long_Integer, Make_Identifier (Loc, Lnam)), Right_Opnd => OK_Convert_To (Standard_Long_Integer, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE ( RE_Get_Nested_Sequence_Length ), Loc), Parameter_Associations => New_List ( New_Occurrence_Of ( Any_Parameter, Loc), Make_Integer_Literal (Loc, Intval => J))))), Right_Opnd => Make_Integer_Literal (Loc, 1)))))); Append_To (Ranges, Make_Range (Loc, Low_Bound => Make_Identifier (Loc, Lnam), High_Bound => Make_Identifier (Loc, Hnam))); Next_Index (Indx); end loop; -- Now we have all the necessary bound information: -- apply the set of range constraints to the -- (unconstrained) nominal subtype of Res. Initial_Counter_Value := Ndim; Res_Subtype_Indication := Make_Subtype_Indication (Loc, Subtype_Mark => Res_Subtype_Indication, Constraint => Make_Index_Or_Discriminant_Constraint (Loc, Constraints => Ranges)); end; end if; Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Res, Object_Definition => Res_Subtype_Indication)); Set_Etype (Res, Typ); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Counter, Object_Definition => New_Occurrence_Of (RTE (RE_Unsigned_32), Loc), Expression => Make_Integer_Literal (Loc, Initial_Counter_Value))); Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Component_TC, Constant_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_TypeCode), Loc), Expression => Build_TypeCode_Call (Loc, Component_Type (Typ), Decls))); Append_From_Any_Array_Iterator (Stms, Any_Parameter, Counter); Append_To (Stms, Make_Simple_Return_Statement (Loc, Expression => New_Occurrence_Of (Res, Loc))); end; elsif Is_Integer_Type (Typ) or else Is_Unsigned_Type (Typ) then Append_To (Stms, Make_Simple_Return_Statement (Loc, Expression => Unchecked_Convert_To (Typ, Build_From_Any_Call (Find_Numeric_Representation (Typ), New_Occurrence_Of (Any_Parameter, Loc), Decls)))); else Use_Opaque_Representation := True; end if; if Use_Opaque_Representation then Assign_Opaque_From_Any (Loc, Stms => Stms, Typ => Typ, N => New_Occurrence_Of (Any_Parameter, Loc), Target => Empty); end if; Decl := Make_Subprogram_Body (Loc, Specification => Spec, Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Stms)); end Build_From_Any_Function; --------------------------------- -- Build_Get_Aggregate_Element -- --------------------------------- function Build_Get_Aggregate_Element (Loc : Source_Ptr; Any : Entity_Id; TC : Node_Id; Idx : Node_Id) return Node_Id is begin return Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Get_Aggregate_Element), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc), TC, Idx)); end Build_Get_Aggregate_Element; ---------------------------------- -- Build_Name_And_Repository_Id -- ---------------------------------- procedure Build_Name_And_Repository_Id (E : Entity_Id; Name_Str : out String_Id; Repo_Id_Str : out String_Id) is begin Name_Str := Fully_Qualified_Name_String (E, Append_NUL => False); Start_String; Store_String_Chars ("DSA:"); Store_String_Chars (Name_Str); Store_String_Chars (":1.0"); Repo_Id_Str := End_String; end Build_Name_And_Repository_Id; ----------------------- -- Build_To_Any_Call -- ----------------------- function Build_To_Any_Call (Loc : Source_Ptr; N : Node_Id; Decls : List_Id; Constrained : Boolean := False) return Node_Id is Typ : Entity_Id := Etype (N); U_Type : Entity_Id; C_Type : Entity_Id; Fnam : Entity_Id := Empty; Lib_RE : RE_Id := RE_Null; begin -- If N is a selected component, then maybe its Etype has not been -- set yet: try to use Etype of the selector_name in that case. if No (Typ) and then Nkind (N) = N_Selected_Component then Typ := Etype (Selector_Name (N)); end if; pragma Assert (Present (Typ)); -- Get full view for private type, completion for incomplete type U_Type := Underlying_Type (Typ); -- First simple case where the To_Any function is present in the -- type's TSS. Fnam := Find_Inherited_TSS (U_Type, TSS_To_Any); -- For the subtype representing a generic actual type, go to the -- actual type. if Is_Generic_Actual_Type (U_Type) then U_Type := Underlying_Type (Base_Type (U_Type)); end if; -- For a standard subtype, go to the base type if Sloc (U_Type) <= Standard_Location then U_Type := Base_Type (U_Type); -- For a user subtype, go to first subtype elsif Comes_From_Source (U_Type) and then Nkind (Declaration_Node (U_Type)) = N_Subtype_Declaration then U_Type := First_Subtype (U_Type); end if; if Present (Fnam) then null; -- Check first for Boolean and Character. These are enumeration -- types, but we treat them specially, since they may require -- special handling in the transfer protocol. However, this -- special handling only applies if they have standard -- representation, otherwise they are treated like any other -- enumeration type. elsif U_Type = Standard_Boolean then Lib_RE := RE_TA_B; elsif U_Type = Standard_Character then Lib_RE := RE_TA_C; elsif U_Type = Standard_Wide_Character then Lib_RE := RE_TA_WC; elsif U_Type = Standard_Wide_Wide_Character then Lib_RE := RE_TA_WWC; -- Floating point types elsif U_Type = Standard_Short_Float then Lib_RE := RE_TA_SF; elsif U_Type = Standard_Float then Lib_RE := RE_TA_F; elsif U_Type = Standard_Long_Float then Lib_RE := RE_TA_LF; elsif U_Type = Standard_Long_Long_Float then Lib_RE := RE_TA_LLF; -- Integer types elsif U_Type = RTE (RE_Integer_8) then Lib_RE := RE_TA_I8; elsif U_Type = RTE (RE_Integer_16) then Lib_RE := RE_TA_I16; elsif U_Type = RTE (RE_Integer_32) then Lib_RE := RE_TA_I32; elsif U_Type = RTE (RE_Integer_64) then Lib_RE := RE_TA_I64; -- Unsigned integer types elsif U_Type = RTE (RE_Unsigned_8) then Lib_RE := RE_TA_U8; elsif U_Type = RTE (RE_Unsigned_16) then Lib_RE := RE_TA_U16; elsif U_Type = RTE (RE_Unsigned_32) then Lib_RE := RE_TA_U32; elsif U_Type = RTE (RE_Unsigned_64) then Lib_RE := RE_TA_U64; elsif Is_RTE (U_Type, RE_Unbounded_String) then Lib_RE := RE_TA_String; -- Special DSA types elsif Is_RTE (U_Type, RE_Any_Container_Ptr) then Lib_RE := RE_TA_A; U_Type := Typ; elsif U_Type = Underlying_Type (RTE (RE_TypeCode)) then -- No corresponding FA_TC ??? Lib_RE := RE_TA_TC; -- Other (non-primitive) types else declare Decl : Entity_Id; begin Build_To_Any_Function (Loc, U_Type, Decl, Fnam); Append_To (Decls, Decl); end; end if; -- Call the function if Lib_RE /= RE_Null then pragma Assert (No (Fnam)); Fnam := RTE (Lib_RE); end if; -- If Fnam is already analyzed, find the proper expected type, -- else we have a newly constructed To_Any function and we know -- that the expected type of its parameter is U_Type. if Ekind (Fnam) = E_Function and then Present (First_Formal (Fnam)) then C_Type := Etype (First_Formal (Fnam)); else C_Type := U_Type; end if; declare Params : constant List_Id := New_List (OK_Convert_To (C_Type, N)); begin if Is_Limited_Type (C_Type) then Append_To (Params, New_Occurrence_Of (Boolean_Literals (Constrained), Loc)); end if; return Make_Function_Call (Loc, Name => New_Occurrence_Of (Fnam, Loc), Parameter_Associations => Params); end; end Build_To_Any_Call; --------------------------- -- Build_To_Any_Function -- --------------------------- procedure Build_To_Any_Function (Loc : Source_Ptr; Typ : Entity_Id; Decl : out Node_Id; Fnam : out Entity_Id) is Spec : Node_Id; Params : List_Id; Decls : List_Id; Stms : List_Id; Expr_Formal : Entity_Id; Cstr_Formal : Entity_Id := Empty; -- initialize to prevent warning Any : Entity_Id; Result_TC : Node_Id; Any_Decl : Node_Id; Use_Opaque_Representation : Boolean; -- When True, use stream attributes and represent type as an -- opaque sequence of bytes. begin -- For a derived type, we can't go past the base type (to the -- parent type) here, because that would cause the attribute's -- formal parameter to have the wrong type; hence the Base_Type -- check here. if Is_Itype (Typ) and then Typ /= Base_Type (Typ) then Build_To_Any_Function (Loc => Loc, Typ => Etype (Typ), Decl => Decl, Fnam => Fnam); return; end if; Decls := New_List; Stms := New_List; Any := Make_Defining_Identifier (Loc, Name_A); Result_TC := Build_TypeCode_Call (Loc, Typ, Decls); Fnam := Make_Helper_Function_Name (Loc, Typ, Name_To_Any); Expr_Formal := Make_Defining_Identifier (Loc, Name_E); Params := New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => Expr_Formal, Parameter_Type => New_Occurrence_Of (Typ, Loc))); Set_Etype (Expr_Formal, Typ); if Is_Limited_Type (Typ) then Cstr_Formal := Make_Defining_Identifier (Loc, Name_C); Append_To (Params, Make_Parameter_Specification (Loc, Defining_Identifier => Cstr_Formal, Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc))); end if; Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Fnam, Parameter_Specifications => Params, Result_Definition => New_Occurrence_Of (RTE (RE_Any), Loc)); Any_Decl := Make_Object_Declaration (Loc, Defining_Identifier => Any, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc)); Use_Opaque_Representation := False; if Has_Stream_Attribute_Definition (Typ, TSS_Stream_Output, At_Any_Place => True) or else Has_Stream_Attribute_Definition (Typ, TSS_Stream_Write, At_Any_Place => True) then -- If user-defined stream attributes are specified for this -- type, use them and transmit data as an opaque sequence of -- stream elements. Use_Opaque_Representation := True; elsif Is_Derived_Type (Typ) and then not Is_Tagged_Type (Typ) then -- Untagged derived type: convert to root type declare Rt_Type : constant Entity_Id := Root_Type (Typ); Expr : constant Node_Id := OK_Convert_To (Rt_Type, New_Occurrence_Of (Expr_Formal, Loc)); begin Set_Expression (Any_Decl, Build_To_Any_Call (Loc, Expr, Decls)); end; elsif Is_Record_Type (Typ) and then not Is_Tagged_Type (Typ) then -- Untagged record type if Nkind (Declaration_Node (Typ)) = N_Subtype_Declaration then declare Rt_Type : constant Entity_Id := Etype (Typ); Expr : constant Node_Id := OK_Convert_To (Rt_Type, New_Occurrence_Of (Expr_Formal, Loc)); begin Set_Expression (Any_Decl, Build_To_Any_Call (Loc, Expr, Decls)); end; -- Comment needed here (and label on declare block ???) else declare Disc : Entity_Id := Empty; Rdef : constant Node_Id := Type_Definition (Declaration_Node (Typ)); Counter : Int := 0; Elements : constant List_Id := New_List; procedure TA_Rec_Add_Process_Element (Stmts : List_Id; Container : Node_Or_Entity_Id; Counter : in out Int; Rec : Entity_Id; Field : Node_Id); -- Processing routine for traversal below procedure TA_Append_Record_Traversal is new Append_Record_Traversal (Rec => Expr_Formal, Add_Process_Element => TA_Rec_Add_Process_Element); -------------------------------- -- TA_Rec_Add_Process_Element -- -------------------------------- procedure TA_Rec_Add_Process_Element (Stmts : List_Id; Container : Node_Or_Entity_Id; Counter : in out Int; Rec : Entity_Id; Field : Node_Id) is Field_Ref : Node_Id; begin if Nkind (Field) = N_Defining_Identifier then -- A regular component Field_Ref := Make_Selected_Component (Loc, Prefix => New_Occurrence_Of (Rec, Loc), Selector_Name => New_Occurrence_Of (Field, Loc)); Set_Etype (Field_Ref, Etype (Field)); Append_To (Stmts, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of ( RTE (RE_Add_Aggregate_Element), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Container, Loc), Build_To_Any_Call (Loc, Field_Ref, Decls)))); else -- A variant part Variant_Part : declare Variant : Node_Id; Struct_Counter : Int := 0; Block_Decls : constant List_Id := New_List; Block_Stmts : constant List_Id := New_List; VP_Stmts : List_Id; Alt_List : constant List_Id := New_List; Choice_List : List_Id; Union_Any : constant Entity_Id := Make_Temporary (Loc, 'V'); Struct_Any : constant Entity_Id := Make_Temporary (Loc, 'S'); function Make_Discriminant_Reference return Node_Id; -- Build reference to the discriminant for this -- variant part. --------------------------------- -- Make_Discriminant_Reference -- --------------------------------- function Make_Discriminant_Reference return Node_Id is Nod : constant Node_Id := Make_Selected_Component (Loc, Prefix => Rec, Selector_Name => Chars (Name (Field))); begin Set_Etype (Nod, Etype (Name (Field))); return Nod; end Make_Discriminant_Reference; -- Start of processing for Variant_Part begin Append_To (Stmts, Make_Block_Statement (Loc, Declarations => Block_Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Block_Stmts))); -- Declare variant part aggregate (Union_Any). -- Knowing the position of this VP in the -- variant record, we can fetch the VP typecode -- from Container. Append_To (Block_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Union_Any, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of ( RTE (RE_Create_Any), Loc), Parameter_Associations => New_List ( Make_Function_Call (Loc, Name => New_Occurrence_Of ( RTE (RE_Any_Member_Type), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Container, Loc), Make_Integer_Literal (Loc, Counter))))))); -- Declare inner struct aggregate (which -- contains the components of this VP). Append_To (Block_Decls, Make_Object_Declaration (Loc, Defining_Identifier => Struct_Any, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of ( RTE (RE_Create_Any), Loc), Parameter_Associations => New_List ( Make_Function_Call (Loc, Name => New_Occurrence_Of ( RTE (RE_Any_Member_Type), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Union_Any, Loc), Make_Integer_Literal (Loc, Uint_1))))))); -- Build case statement Append_To (Block_Stmts, Make_Case_Statement (Loc, Expression => Make_Discriminant_Reference, Alternatives => Alt_List)); Variant := First_Non_Pragma (Variants (Field)); while Present (Variant) loop Choice_List := New_Copy_List_Tree (Discrete_Choices (Variant)); VP_Stmts := New_List; -- Append discriminant val to union aggregate Append_To (VP_Stmts, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of ( RTE (RE_Add_Aggregate_Element), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Union_Any, Loc), Build_To_Any_Call (Loc, Make_Discriminant_Reference, Block_Decls)))); -- Populate inner struct aggregate -- Struct_Counter should be reset before -- handling a variant part. Indeed only one -- of the case statement alternatives will be -- executed at run time, so the counter must -- start at 0 for every case statement. Struct_Counter := 0; TA_Append_Record_Traversal (Stmts => VP_Stmts, Clist => Component_List (Variant), Container => Struct_Any, Counter => Struct_Counter); -- Append inner struct to union aggregate Append_To (VP_Stmts, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Add_Aggregate_Element), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Union_Any, Loc), New_Occurrence_Of (Struct_Any, Loc)))); -- Append union to outer aggregate Append_To (VP_Stmts, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Add_Aggregate_Element), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Container, Loc), New_Occurrence_Of (Union_Any, Loc)))); Append_To (Alt_List, Make_Case_Statement_Alternative (Loc, Discrete_Choices => Choice_List, Statements => VP_Stmts)); Next_Non_Pragma (Variant); end loop; end Variant_Part; end if; Counter := Counter + 1; end TA_Rec_Add_Process_Element; begin -- Records are encoded in a TC_STRUCT aggregate: -- -- Outer aggregate (TC_STRUCT) -- | [discriminant1] -- | [discriminant2] -- | ... -- | -- | [component1] -- | [component2] -- | ... -- A component can be a common component or variant part -- A variant part is encoded as a TC_UNION aggregate: -- -- Variant Part Aggregate (TC_UNION) -- | [discriminant choice for this Variant Part] -- | -- | -- Inner struct (TC_STRUCT) -- | | [component1] -- | | [component2] -- | | ... -- Let's start by building the outer aggregate. First we -- construct Elements array containing all discriminants. if Has_Discriminants (Typ) then Disc := First_Discriminant (Typ); while Present (Disc) loop declare Discriminant : constant Entity_Id := Make_Selected_Component (Loc, Prefix => Expr_Formal, Selector_Name => Chars (Disc)); begin Set_Etype (Discriminant, Etype (Disc)); Append_To (Elements, Make_Component_Association (Loc, Choices => New_List ( Make_Integer_Literal (Loc, Counter)), Expression => Build_To_Any_Call (Loc, Discriminant, Decls))); end; Counter := Counter + 1; Next_Discriminant (Disc); end loop; else -- If there are no discriminants, we declare an empty -- Elements array. declare Dummy_Any : constant Entity_Id := Make_Temporary (Loc, 'A'); begin Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Dummy_Any, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc))); Append_To (Elements, Make_Component_Association (Loc, Choices => New_List ( Make_Range (Loc, Low_Bound => Make_Integer_Literal (Loc, 1), High_Bound => Make_Integer_Literal (Loc, 0))), Expression => New_Occurrence_Of (Dummy_Any, Loc))); end; end if; -- We build the result aggregate with discriminants -- as the first elements. Set_Expression (Any_Decl, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Any_Aggregate_Build), Loc), Parameter_Associations => New_List ( Result_TC, Make_Aggregate (Loc, Component_Associations => Elements)))); Result_TC := Empty; -- Then we append all the components to the result -- aggregate. TA_Append_Record_Traversal (Stms, Clist => Component_List (Rdef), Container => Any, Counter => Counter); end; end if; elsif Is_Array_Type (Typ) then -- Constrained and unconstrained array types declare Constrained : constant Boolean := not Transmit_As_Unconstrained (Typ); procedure TA_Ary_Add_Process_Element (Stmts : List_Id; Any : Entity_Id; Counter : Entity_Id; Datum : Node_Id); -------------------------------- -- TA_Ary_Add_Process_Element -- -------------------------------- procedure TA_Ary_Add_Process_Element (Stmts : List_Id; Any : Entity_Id; Counter : Entity_Id; Datum : Node_Id) is pragma Unreferenced (Counter); Element_Any : Node_Id; begin if Etype (Datum) = RTE (RE_Any) then Element_Any := Datum; else Element_Any := Build_To_Any_Call (Loc, Datum, Decls); end if; Append_To (Stmts, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of ( RTE (RE_Add_Aggregate_Element), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc), Element_Any))); end TA_Ary_Add_Process_Element; procedure Append_To_Any_Array_Iterator is new Append_Array_Traversal ( Subprogram => Fnam, Arry => Expr_Formal, Indexes => New_List, Add_Process_Element => TA_Ary_Add_Process_Element); Index : Node_Id; begin Set_Expression (Any_Decl, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Create_Any), Loc), Parameter_Associations => New_List (Result_TC))); Result_TC := Empty; if not Constrained then Index := First_Index (Typ); for J in 1 .. Number_Dimensions (Typ) loop Append_To (Stms, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Add_Aggregate_Element), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc), Build_To_Any_Call (Loc, OK_Convert_To (Etype (Index), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Expr_Formal, Loc), Attribute_Name => Name_First, Expressions => New_List ( Make_Integer_Literal (Loc, J)))), Decls)))); Next_Index (Index); end loop; end if; Append_To_Any_Array_Iterator (Stms, Any); end; elsif Is_Integer_Type (Typ) or else Is_Unsigned_Type (Typ) then -- Integer types Set_Expression (Any_Decl, Build_To_Any_Call (Loc, OK_Convert_To ( Find_Numeric_Representation (Typ), New_Occurrence_Of (Expr_Formal, Loc)), Decls)); else -- Default case, including tagged types: opaque representation Use_Opaque_Representation := True; end if; if Use_Opaque_Representation then declare Strm : constant Entity_Id := Make_Temporary (Loc, 'S'); -- Stream used to store data representation produced by -- stream attribute. begin -- Generate: -- Strm : aliased Buffer_Stream_Type; Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Strm, Aliased_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Buffer_Stream_Type), Loc))); -- Generate: -- T'Output (Strm'Access, E); -- or -- T'Write (Strm'Access, E); -- depending on whether to transmit as unconstrained. -- For limited types, select at run time depending on -- Constrained parameter. declare function Stream_Call (Attr : Name_Id) return Node_Id; -- Return a call to the named attribute ----------------- -- Stream_Call -- ----------------- function Stream_Call (Attr : Name_Id) return Node_Id is begin return Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Typ, Loc), Attribute_Name => Attr, Expressions => New_List ( Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Strm, Loc), Attribute_Name => Name_Access), New_Occurrence_Of (Expr_Formal, Loc))); end Stream_Call; begin if Is_Limited_Type (Typ) then Append_To (Stms, Make_Implicit_If_Statement (Typ, Condition => New_Occurrence_Of (Cstr_Formal, Loc), Then_Statements => New_List ( Stream_Call (Name_Write)), Else_Statements => New_List ( Stream_Call (Name_Output)))); elsif Transmit_As_Unconstrained (Typ) then Append_To (Stms, Stream_Call (Name_Output)); else Append_To (Stms, Stream_Call (Name_Write)); end if; end; -- Generate: -- BS_To_Any (Strm, A); Append_To (Stms, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_BS_To_Any), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Strm, Loc), New_Occurrence_Of (Any, Loc)))); -- Generate: -- Release_Buffer (Strm); Append_To (Stms, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Release_Buffer), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Strm, Loc)))); end; end if; Append_To (Decls, Any_Decl); if Present (Result_TC) then Append_To (Stms, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Set_TC), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc), Result_TC))); end if; Append_To (Stms, Make_Simple_Return_Statement (Loc, Expression => New_Occurrence_Of (Any, Loc))); Decl := Make_Subprogram_Body (Loc, Specification => Spec, Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Stms)); end Build_To_Any_Function; ------------------------- -- Build_TypeCode_Call -- ------------------------- function Build_TypeCode_Call (Loc : Source_Ptr; Typ : Entity_Id; Decls : List_Id) return Node_Id is U_Type : Entity_Id := Underlying_Type (Typ); -- The full view, if Typ is private; the completion, -- if Typ is incomplete. Fnam : Entity_Id := Empty; Lib_RE : RE_Id := RE_Null; Expr : Node_Id; begin -- Special case System.PolyORB.Interface.Any: its primitives have -- not been set yet, so can't call Find_Inherited_TSS. if Typ = RTE (RE_Any) then Fnam := RTE (RE_TC_A); else -- First simple case where the TypeCode is present -- in the type's TSS. Fnam := Find_Inherited_TSS (U_Type, TSS_TypeCode); end if; -- For the subtype representing a generic actual type, go to the -- actual type. if Is_Generic_Actual_Type (U_Type) then U_Type := Underlying_Type (Base_Type (U_Type)); end if; -- For a standard subtype, go to the base type if Sloc (U_Type) <= Standard_Location then U_Type := Base_Type (U_Type); -- For a user subtype, go to first subtype elsif Comes_From_Source (U_Type) and then Nkind (Declaration_Node (U_Type)) = N_Subtype_Declaration then U_Type := First_Subtype (U_Type); end if; if No (Fnam) then if U_Type = Standard_Boolean then Lib_RE := RE_TC_B; elsif U_Type = Standard_Character then Lib_RE := RE_TC_C; elsif U_Type = Standard_Wide_Character then Lib_RE := RE_TC_WC; elsif U_Type = Standard_Wide_Wide_Character then Lib_RE := RE_TC_WWC; -- Floating point types elsif U_Type = Standard_Short_Float then Lib_RE := RE_TC_SF; elsif U_Type = Standard_Float then Lib_RE := RE_TC_F; elsif U_Type = Standard_Long_Float then Lib_RE := RE_TC_LF; elsif U_Type = Standard_Long_Long_Float then Lib_RE := RE_TC_LLF; -- Integer types (walk back to the base type) elsif U_Type = RTE (RE_Integer_8) then Lib_RE := RE_TC_I8; elsif U_Type = RTE (RE_Integer_16) then Lib_RE := RE_TC_I16; elsif U_Type = RTE (RE_Integer_32) then Lib_RE := RE_TC_I32; elsif U_Type = RTE (RE_Integer_64) then Lib_RE := RE_TC_I64; -- Unsigned integer types elsif U_Type = RTE (RE_Unsigned_8) then Lib_RE := RE_TC_U8; elsif U_Type = RTE (RE_Unsigned_16) then Lib_RE := RE_TC_U16; elsif U_Type = RTE (RE_Unsigned_32) then Lib_RE := RE_TC_U32; elsif U_Type = RTE (RE_Unsigned_64) then Lib_RE := RE_TC_U64; elsif Is_RTE (U_Type, RE_Unbounded_String) then Lib_RE := RE_TC_String; -- Special DSA types elsif Is_RTE (U_Type, RE_Any_Container_Ptr) then Lib_RE := RE_TC_A; -- Other (non-primitive) types else declare Decl : Entity_Id; begin Build_TypeCode_Function (Loc, U_Type, Decl, Fnam); Append_To (Decls, Decl); end; end if; if Lib_RE /= RE_Null then Fnam := RTE (Lib_RE); end if; end if; -- Call the function Expr := Make_Function_Call (Loc, Name => New_Occurrence_Of (Fnam, Loc)); -- Allow Expr to be used as arg to Build_To_Any_Call immediately Set_Etype (Expr, RTE (RE_TypeCode)); return Expr; end Build_TypeCode_Call; ----------------------------- -- Build_TypeCode_Function -- ----------------------------- procedure Build_TypeCode_Function (Loc : Source_Ptr; Typ : Entity_Id; Decl : out Node_Id; Fnam : out Entity_Id) is Spec : Node_Id; Decls : constant List_Id := New_List; Stms : constant List_Id := New_List; TCNam : constant Entity_Id := Make_Helper_Function_Name (Loc, Typ, Name_TypeCode); Parameters : List_Id; procedure Add_String_Parameter (S : String_Id; Parameter_List : List_Id); -- Add a literal for S to Parameters procedure Add_TypeCode_Parameter (TC_Node : Node_Id; Parameter_List : List_Id); -- Add the typecode for Typ to Parameters procedure Add_Long_Parameter (Expr_Node : Node_Id; Parameter_List : List_Id); -- Add a signed long integer expression to Parameters procedure Initialize_Parameter_List (Name_String : String_Id; Repo_Id_String : String_Id; Parameter_List : out List_Id); -- Return a list that contains the first two parameters -- for a parameterized typecode: name and repository id. function Make_Constructed_TypeCode (Kind : Entity_Id; Parameters : List_Id) return Node_Id; -- Call Build_Complex_TC with the given kind and parameters procedure Return_Constructed_TypeCode (Kind : Entity_Id); -- Make a return statement that calls Build_Complex_TC with the -- given typecode kind, and the constructed parameters list. procedure Return_Alias_TypeCode (Base_TypeCode : Node_Id); -- Return a typecode that is a TC_Alias for the given typecode -------------------------- -- Add_String_Parameter -- -------------------------- procedure Add_String_Parameter (S : String_Id; Parameter_List : List_Id) is begin Append_To (Parameter_List, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_TA_Std_String), Loc), Parameter_Associations => New_List ( Make_String_Literal (Loc, S)))); end Add_String_Parameter; ---------------------------- -- Add_TypeCode_Parameter -- ---------------------------- procedure Add_TypeCode_Parameter (TC_Node : Node_Id; Parameter_List : List_Id) is begin Append_To (Parameter_List, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_TA_TC), Loc), Parameter_Associations => New_List (TC_Node))); end Add_TypeCode_Parameter; ------------------------ -- Add_Long_Parameter -- ------------------------ procedure Add_Long_Parameter (Expr_Node : Node_Id; Parameter_List : List_Id) is begin Append_To (Parameter_List, Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_TA_I32), Loc), Parameter_Associations => New_List (Expr_Node))); end Add_Long_Parameter; ------------------------------- -- Initialize_Parameter_List -- ------------------------------- procedure Initialize_Parameter_List (Name_String : String_Id; Repo_Id_String : String_Id; Parameter_List : out List_Id) is begin Parameter_List := New_List; Add_String_Parameter (Name_String, Parameter_List); Add_String_Parameter (Repo_Id_String, Parameter_List); end Initialize_Parameter_List; --------------------------- -- Return_Alias_TypeCode -- --------------------------- procedure Return_Alias_TypeCode (Base_TypeCode : Node_Id) is begin Add_TypeCode_Parameter (Base_TypeCode, Parameters); Return_Constructed_TypeCode (RTE (RE_Tk_Alias)); end Return_Alias_TypeCode; ------------------------------- -- Make_Constructed_TypeCode -- ------------------------------- function Make_Constructed_TypeCode (Kind : Entity_Id; Parameters : List_Id) return Node_Id is Constructed_TC : constant Node_Id := Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Build_Complex_TC), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Kind, Loc), Make_Aggregate (Loc, Expressions => Parameters))); begin Set_Etype (Constructed_TC, RTE (RE_TypeCode)); return Constructed_TC; end Make_Constructed_TypeCode; --------------------------------- -- Return_Constructed_TypeCode -- --------------------------------- procedure Return_Constructed_TypeCode (Kind : Entity_Id) is begin Append_To (Stms, Make_Simple_Return_Statement (Loc, Expression => Make_Constructed_TypeCode (Kind, Parameters))); end Return_Constructed_TypeCode; ------------------ -- Record types -- ------------------ procedure TC_Rec_Add_Process_Element (Params : List_Id; Any : Entity_Id; Counter : in out Int; Rec : Entity_Id; Field : Node_Id); procedure TC_Append_Record_Traversal is new Append_Record_Traversal ( Rec => Empty, Add_Process_Element => TC_Rec_Add_Process_Element); -------------------------------- -- TC_Rec_Add_Process_Element -- -------------------------------- procedure TC_Rec_Add_Process_Element (Params : List_Id; Any : Entity_Id; Counter : in out Int; Rec : Entity_Id; Field : Node_Id) is pragma Unreferenced (Any, Counter, Rec); begin if Nkind (Field) = N_Defining_Identifier then -- A regular component Add_TypeCode_Parameter (Build_TypeCode_Call (Loc, Etype (Field), Decls), Params); Get_Name_String (Chars (Field)); Add_String_Parameter (String_From_Name_Buffer, Params); else -- A variant part Variant_Part : declare Disc_Type : constant Entity_Id := Etype (Name (Field)); Is_Enum : constant Boolean := Is_Enumeration_Type (Disc_Type); Union_TC_Params : List_Id; U_Name : constant Name_Id := New_External_Name (Chars (Typ), 'V', -1); Name_Str : String_Id; Struct_TC_Params : List_Id; Variant : Node_Id; Choice : Node_Id; Default : constant Node_Id := Make_Integer_Literal (Loc, -1); Dummy_Counter : Int := 0; Choice_Index : Int := 0; -- Index of current choice in TypeCode, used to identify -- it as the default choice if it is a "when others". procedure Add_Params_For_Variant_Components; -- Add a struct TypeCode and a corresponding member name -- to the union parameter list. -- Ordering of declarations is a complete mess in this -- area, it is supposed to be types/variables, then -- subprogram specs, then subprogram bodies ??? --------------------------------------- -- Add_Params_For_Variant_Components -- --------------------------------------- procedure Add_Params_For_Variant_Components is S_Name : constant Name_Id := New_External_Name (U_Name, 'S', -1); begin Get_Name_String (S_Name); Name_Str := String_From_Name_Buffer; Initialize_Parameter_List (Name_Str, Name_Str, Struct_TC_Params); -- Build struct parameters TC_Append_Record_Traversal (Struct_TC_Params, Component_List (Variant), Empty, Dummy_Counter); Add_TypeCode_Parameter (Make_Constructed_TypeCode (RTE (RE_Tk_Struct), Struct_TC_Params), Union_TC_Params); Add_String_Parameter (Name_Str, Union_TC_Params); end Add_Params_For_Variant_Components; -- Start of processing for Variant_Part begin Get_Name_String (U_Name); Name_Str := String_From_Name_Buffer; Initialize_Parameter_List (Name_Str, Name_Str, Union_TC_Params); -- Add union in enclosing parameter list Add_TypeCode_Parameter (Make_Constructed_TypeCode (RTE (RE_Tk_Union), Union_TC_Params), Params); Add_String_Parameter (Name_Str, Params); -- Build union parameters Add_TypeCode_Parameter (Build_TypeCode_Call (Loc, Disc_Type, Decls), Union_TC_Params); Add_Long_Parameter (Default, Union_TC_Params); Variant := First_Non_Pragma (Variants (Field)); while Present (Variant) loop Choice := First (Discrete_Choices (Variant)); while Present (Choice) loop case Nkind (Choice) is when N_Range => declare L : constant Uint := Expr_Value (Low_Bound (Choice)); H : constant Uint := Expr_Value (High_Bound (Choice)); J : Uint := L; -- 3.8.1(8) guarantees that the bounds of -- this range are static. Expr : Node_Id; begin while J <= H loop if Is_Enum then Expr := Get_Enum_Lit_From_Pos (Disc_Type, J, Loc); else Expr := Make_Integer_Literal (Loc, J); end if; Set_Etype (Expr, Disc_Type); Append_To (Union_TC_Params, Build_To_Any_Call (Loc, Expr, Decls)); Add_Params_For_Variant_Components; J := J + Uint_1; end loop; Choice_Index := Choice_Index + UI_To_Int (H - L) + 1; end; when N_Others_Choice => -- This variant has a default choice. We must -- therefore set the default parameter to the -- current choice index. This parameter is by -- construction the 4th in Union_TC_Params. Replace (Pick (Union_TC_Params, 4), Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_TA_I32), Loc), Parameter_Associations => New_List ( Make_Integer_Literal (Loc, Intval => Choice_Index)))); -- Add a placeholder member label for the -- default case, which must have the -- discriminant type. declare Exp : constant Node_Id := Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Disc_Type, Loc), Attribute_Name => Name_First); begin Set_Etype (Exp, Disc_Type); Append_To (Union_TC_Params, Build_To_Any_Call (Loc, Exp, Decls)); end; Add_Params_For_Variant_Components; Choice_Index := Choice_Index + 1; -- Case of an explicit choice when others => declare Exp : constant Node_Id := New_Copy_Tree (Choice); begin Append_To (Union_TC_Params, Build_To_Any_Call (Loc, Exp, Decls)); end; Add_Params_For_Variant_Components; Choice_Index := Choice_Index + 1; end case; Next (Choice); end loop; Next_Non_Pragma (Variant); end loop; end Variant_Part; end if; end TC_Rec_Add_Process_Element; Type_Name_Str : String_Id; Type_Repo_Id_Str : String_Id; -- Start of processing for Build_TypeCode_Function begin -- For a derived type, we can't go past the base type (to the -- parent type) here, because that would cause the attribute's -- formal parameter to have the wrong type; hence the Base_Type -- check here. if Is_Itype (Typ) and then Typ /= Base_Type (Typ) then Build_TypeCode_Function (Loc => Loc, Typ => Etype (Typ), Decl => Decl, Fnam => Fnam); return; end if; Fnam := TCNam; Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Fnam, Parameter_Specifications => Empty_List, Result_Definition => New_Occurrence_Of (RTE (RE_TypeCode), Loc)); Build_Name_And_Repository_Id (Typ, Name_Str => Type_Name_Str, Repo_Id_Str => Type_Repo_Id_Str); Initialize_Parameter_List (Type_Name_Str, Type_Repo_Id_Str, Parameters); if Has_Stream_Attribute_Definition (Typ, TSS_Stream_Output, At_Any_Place => True) or else Has_Stream_Attribute_Definition (Typ, TSS_Stream_Write, At_Any_Place => True) then -- If user-defined stream attributes are specified for this -- type, use them and transmit data as an opaque sequence of -- stream elements. Return_Alias_TypeCode (New_Occurrence_Of (RTE (RE_TC_Opaque), Loc)); elsif Is_Derived_Type (Typ) and then not Is_Tagged_Type (Typ) then Return_Alias_TypeCode ( Build_TypeCode_Call (Loc, Etype (Typ), Decls)); elsif Is_Integer_Type (Typ) or else Is_Unsigned_Type (Typ) then Return_Alias_TypeCode ( Build_TypeCode_Call (Loc, Find_Numeric_Representation (Typ), Decls)); elsif Is_Record_Type (Typ) and then not Is_Tagged_Type (Typ) then -- Record typecodes are encoded as follows: -- -- TC_STRUCT -- | -- | [Name] -- | [Repository Id] -- -- Then for each discriminant: -- -- | [Discriminant Type Code] -- | [Discriminant Name] -- | ... -- -- Then for each component: -- -- | [Component Type Code] -- | [Component Name] -- | ... -- -- Variants components type codes are encoded as follows: -- -- TC_UNION -- | -- | [Name] -- | [Repository Id] -- | [Discriminant Type Code] -- | [Index of Default Variant Part or -1 for no default] -- -- Then for each Variant Part : -- -- | [VP Label] -- | -- | -- TC_STRUCT -- | | [Variant Part Name] -- | | [Variant Part Repository Id] -- | | -- | Then for each VP component: -- | | [VP component Typecode] -- | | [VP component Name] -- | | ... -- | -- -- | -- | [VP Name] if Nkind (Declaration_Node (Typ)) = N_Subtype_Declaration then Return_Alias_TypeCode (Build_TypeCode_Call (Loc, Etype (Typ), Decls)); else declare Disc : Entity_Id := Empty; Rdef : constant Node_Id := Type_Definition (Declaration_Node (Typ)); Dummy_Counter : Int := 0; begin -- Construct the discriminants typecodes if Has_Discriminants (Typ) then Disc := First_Discriminant (Typ); end if; while Present (Disc) loop Add_TypeCode_Parameter ( Build_TypeCode_Call (Loc, Etype (Disc), Decls), Parameters); Get_Name_String (Chars (Disc)); Add_String_Parameter ( String_From_Name_Buffer, Parameters); Next_Discriminant (Disc); end loop; -- then the components typecodes TC_Append_Record_Traversal (Parameters, Component_List (Rdef), Empty, Dummy_Counter); Return_Constructed_TypeCode (RTE (RE_Tk_Struct)); end; end if; elsif Is_Array_Type (Typ) then declare Ndim : constant Pos := Number_Dimensions (Typ); Inner_TypeCode : Node_Id; Constrained : constant Boolean := Is_Constrained (Typ); Indx : Node_Id := First_Index (Typ); begin Inner_TypeCode := Build_TypeCode_Call (Loc, Component_Type (Typ), Decls); for J in 1 .. Ndim loop if Constrained then Inner_TypeCode := Make_Constructed_TypeCode (RTE (RE_Tk_Array), New_List ( Build_To_Any_Call (Loc, OK_Convert_To (RTE (RE_Unsigned_32), Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Typ, Loc), Attribute_Name => Name_Length, Expressions => New_List ( Make_Integer_Literal (Loc, Intval => Ndim - J + 1)))), Decls), Build_To_Any_Call (Loc, Inner_TypeCode, Decls))); else -- Unconstrained case: add low bound for each -- dimension. Add_TypeCode_Parameter (Build_TypeCode_Call (Loc, Etype (Indx), Decls), Parameters); Get_Name_String (New_External_Name ('L', J)); Add_String_Parameter ( String_From_Name_Buffer, Parameters); Next_Index (Indx); Inner_TypeCode := Make_Constructed_TypeCode (RTE (RE_Tk_Sequence), New_List ( Build_To_Any_Call (Loc, OK_Convert_To (RTE (RE_Unsigned_32), Make_Integer_Literal (Loc, 0)), Decls), Build_To_Any_Call (Loc, Inner_TypeCode, Decls))); end if; end loop; if Constrained then Return_Alias_TypeCode (Inner_TypeCode); else Add_TypeCode_Parameter (Inner_TypeCode, Parameters); Start_String; Store_String_Char ('V'); Add_String_Parameter (End_String, Parameters); Return_Constructed_TypeCode (RTE (RE_Tk_Struct)); end if; end; else -- Default: type is represented as an opaque sequence of bytes Return_Alias_TypeCode (New_Occurrence_Of (RTE (RE_TC_Opaque), Loc)); end if; Decl := Make_Subprogram_Body (Loc, Specification => Spec, Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Stms)); end Build_TypeCode_Function; --------------------------------- -- Find_Numeric_Representation -- --------------------------------- function Find_Numeric_Representation (Typ : Entity_Id) return Entity_Id is FST : constant Entity_Id := First_Subtype (Typ); P_Size : constant Uint := Esize (FST); begin -- Special case: for Stream_Element_Offset and Storage_Offset, -- always force transmission as a 64-bit value. if Is_RTE (FST, RE_Stream_Element_Offset) or else Is_RTE (FST, RE_Storage_Offset) then return RTE (RE_Unsigned_64); end if; if Is_Unsigned_Type (Typ) then if P_Size <= 8 then return RTE (RE_Unsigned_8); elsif P_Size <= 16 then return RTE (RE_Unsigned_16); elsif P_Size <= 32 then return RTE (RE_Unsigned_32); else return RTE (RE_Unsigned_64); end if; elsif Is_Integer_Type (Typ) then if P_Size <= 8 then return RTE (RE_Integer_8); elsif P_Size <= Standard_Short_Integer_Size then return RTE (RE_Integer_16); elsif P_Size <= Standard_Integer_Size then return RTE (RE_Integer_32); else return RTE (RE_Integer_64); end if; elsif Is_Floating_Point_Type (Typ) then if P_Size <= Standard_Short_Float_Size then return Standard_Short_Float; elsif P_Size <= Standard_Float_Size then return Standard_Float; elsif P_Size <= Standard_Long_Float_Size then return Standard_Long_Float; else return Standard_Long_Long_Float; end if; else raise Program_Error; end if; -- TBD: fixed point types??? -- TBverified numeric types with a biased representation??? end Find_Numeric_Representation; --------------------------- -- Append_Array_Traversal -- --------------------------- procedure Append_Array_Traversal (Stmts : List_Id; Any : Entity_Id; Counter : Entity_Id := Empty; Depth : Pos := 1) is Loc : constant Source_Ptr := Sloc (Subprogram); Typ : constant Entity_Id := Etype (Arry); Constrained : constant Boolean := Is_Constrained (Typ); Ndim : constant Pos := Number_Dimensions (Typ); Inner_Any, Inner_Counter : Entity_Id; Loop_Stm : Node_Id; Inner_Stmts : constant List_Id := New_List; begin if Depth > Ndim then -- Processing for one element of an array declare Element_Expr : constant Node_Id := Make_Indexed_Component (Loc, New_Occurrence_Of (Arry, Loc), Indexes); begin Set_Etype (Element_Expr, Component_Type (Typ)); Add_Process_Element (Stmts, Any => Any, Counter => Counter, Datum => Element_Expr); end; return; end if; Append_To (Indexes, Make_Identifier (Loc, New_External_Name ('L', Depth))); if not Constrained or else Depth > 1 then Inner_Any := Make_Defining_Identifier (Loc, New_External_Name ('A', Depth)); Set_Etype (Inner_Any, RTE (RE_Any)); else Inner_Any := Empty; end if; if Present (Counter) then Inner_Counter := Make_Defining_Identifier (Loc, New_External_Name ('J', Depth)); else Inner_Counter := Empty; end if; declare Loop_Any : Node_Id := Inner_Any; begin -- For the first dimension of a constrained array, we add -- elements directly in the corresponding Any; there is no -- intervening inner Any. if No (Loop_Any) then Loop_Any := Any; end if; Append_Array_Traversal (Inner_Stmts, Any => Loop_Any, Counter => Inner_Counter, Depth => Depth + 1); end; Loop_Stm := Make_Implicit_Loop_Statement (Subprogram, Iteration_Scheme => Make_Iteration_Scheme (Loc, Loop_Parameter_Specification => Make_Loop_Parameter_Specification (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Chars => New_External_Name ('L', Depth)), Discrete_Subtype_Definition => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Arry, Loc), Attribute_Name => Name_Range, Expressions => New_List ( Make_Integer_Literal (Loc, Depth))))), Statements => Inner_Stmts); declare Decls : constant List_Id := New_List; Dimen_Stmts : constant List_Id := New_List; Length_Node : Node_Id; Inner_Any_TypeCode : constant Entity_Id := Make_Defining_Identifier (Loc, New_External_Name ('T', Depth)); Inner_Any_TypeCode_Expr : Node_Id; begin if Depth = 1 then if Constrained then Inner_Any_TypeCode_Expr := Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Get_TC), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc))); else Inner_Any_TypeCode_Expr := Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Any_Member_Type), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Any, Loc), Make_Integer_Literal (Loc, Ndim))); end if; else Inner_Any_TypeCode_Expr := Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Content_Type), Loc), Parameter_Associations => New_List ( Make_Identifier (Loc, Chars => New_External_Name ('T', Depth - 1)))); end if; Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Inner_Any_TypeCode, Constant_Present => True, Object_Definition => New_Occurrence_Of ( RTE (RE_TypeCode), Loc), Expression => Inner_Any_TypeCode_Expr)); if Present (Inner_Any) then Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Inner_Any, Object_Definition => New_Occurrence_Of (RTE (RE_Any), Loc), Expression => Make_Function_Call (Loc, Name => New_Occurrence_Of ( RTE (RE_Create_Any), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Inner_Any_TypeCode, Loc))))); end if; if Present (Inner_Counter) then Append_To (Decls, Make_Object_Declaration (Loc, Defining_Identifier => Inner_Counter, Object_Definition => New_Occurrence_Of (RTE (RE_Unsigned_32), Loc), Expression => Make_Integer_Literal (Loc, 0))); end if; if not Constrained then Length_Node := Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Arry, Loc), Attribute_Name => Name_Length, Expressions => New_List (Make_Integer_Literal (Loc, Depth))); Set_Etype (Length_Node, RTE (RE_Unsigned_32)); Add_Process_Element (Dimen_Stmts, Datum => Length_Node, Any => Inner_Any, Counter => Inner_Counter); end if; -- Loop_Stm does appropriate processing for each element -- of Inner_Any. Append_To (Dimen_Stmts, Loop_Stm); -- Link outer and inner any if Present (Inner_Any) then Add_Process_Element (Dimen_Stmts, Any => Any, Counter => Counter, Datum => New_Occurrence_Of (Inner_Any, Loc)); end if; Append_To (Stmts, Make_Block_Statement (Loc, Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => Dimen_Stmts))); end; end Append_Array_Traversal; ------------------------------- -- Make_Helper_Function_Name -- ------------------------------- function Make_Helper_Function_Name (Loc : Source_Ptr; Typ : Entity_Id; Nam : Name_Id) return Entity_Id is begin declare Serial : Nat := 0; -- For tagged types that aren't frozen yet, generate the helper -- under its canonical name so that it matches the primitive -- spec. For all other cases, we use a serialized name so that -- multiple generations of the same procedure do not clash. begin if Is_Tagged_Type (Typ) and then not Is_Frozen (Typ) then null; else Serial := Increment_Serial_Number; end if; -- Use prefixed underscore to avoid potential clash with user -- identifier (we use attribute names for Nam). return Make_Defining_Identifier (Loc, Chars => New_External_Name (Related_Id => Nam, Suffix => ' ', Suffix_Index => Serial, Prefix => '_')); end; end Make_Helper_Function_Name; end Helpers; ----------------------------------- -- Reserve_NamingContext_Methods -- ----------------------------------- procedure Reserve_NamingContext_Methods is Str_Resolve : constant String := "resolve"; begin Name_Buffer (1 .. Str_Resolve'Length) := Str_Resolve; Name_Len := Str_Resolve'Length; Overload_Counter_Table.Set (Name_Find, 1); end Reserve_NamingContext_Methods; ----------------------- -- RPC_Receiver_Decl -- ----------------------- function RPC_Receiver_Decl (RACW_Type : Entity_Id) return Node_Id is Loc : constant Source_Ptr := Sloc (RACW_Type); begin return Make_Object_Declaration (Loc, Defining_Identifier => Make_Temporary (Loc, 'R'), Aliased_Present => True, Object_Definition => New_Occurrence_Of (RTE (RE_Servant), Loc)); end RPC_Receiver_Decl; end PolyORB_Support; ------------------------------- -- RACW_Type_Is_Asynchronous -- ------------------------------- procedure RACW_Type_Is_Asynchronous (RACW_Type : Entity_Id) is Asynchronous_Flag : constant Entity_Id := Asynchronous_Flags_Table.Get (RACW_Type); begin Replace (Expression (Parent (Asynchronous_Flag)), New_Occurrence_Of (Standard_True, Sloc (Asynchronous_Flag))); end RACW_Type_Is_Asynchronous; ------------------------- -- RCI_Package_Locator -- ------------------------- function RCI_Package_Locator (Loc : Source_Ptr; Package_Spec : Node_Id) return Node_Id is Inst : Node_Id; Pkg_Name : constant String_Id := Fully_Qualified_Name_String (Defining_Entity (Package_Spec), Append_NUL => False); begin Inst := Make_Package_Instantiation (Loc, Defining_Unit_Name => Make_Temporary (Loc, 'R'), Name => New_Occurrence_Of (RTE (RE_RCI_Locator), Loc), Generic_Associations => New_List ( Make_Generic_Association (Loc, Selector_Name => Make_Identifier (Loc, Name_RCI_Name), Explicit_Generic_Actual_Parameter => Make_String_Literal (Loc, Strval => Pkg_Name)), Make_Generic_Association (Loc, Selector_Name => Make_Identifier (Loc, Name_Version), Explicit_Generic_Actual_Parameter => Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (Defining_Entity (Package_Spec), Loc), Attribute_Name => Name_Version)))); RCI_Locator_Table.Set (Defining_Unit_Name (Package_Spec), Defining_Unit_Name (Inst)); return Inst; end RCI_Package_Locator; ----------------------------------------------- -- Remote_Types_Tagged_Full_View_Encountered -- ----------------------------------------------- procedure Remote_Types_Tagged_Full_View_Encountered (Full_View : Entity_Id) is Stub_Elements : constant Stub_Structure := Stubs_Table.Get (Full_View); begin -- For an RACW encountered before the freeze point of its designated -- type, the stub type is generated at the point of the RACW declaration -- but the primitives are generated only once the designated type is -- frozen. That freeze can occur in another scope, for example when the -- RACW is declared in a nested package. In that case we need to -- reestablish the stub type's scope prior to generating its primitive -- operations. if Stub_Elements /= Empty_Stub_Structure then declare Saved_Scope : constant Entity_Id := Current_Scope; Stubs_Scope : constant Entity_Id := Scope (Stub_Elements.Stub_Type); begin if Current_Scope /= Stubs_Scope then Push_Scope (Stubs_Scope); end if; Add_RACW_Primitive_Declarations_And_Bodies (Full_View, Stub_Elements.RPC_Receiver_Decl, Stub_Elements.Body_Decls); if Current_Scope /= Saved_Scope then Pop_Scope; end if; end; end if; end Remote_Types_Tagged_Full_View_Encountered; ------------------- -- Scope_Of_Spec -- ------------------- function Scope_Of_Spec (Spec : Node_Id) return Entity_Id is Unit_Name : Node_Id; begin Unit_Name := Defining_Unit_Name (Spec); while Nkind (Unit_Name) /= N_Defining_Identifier loop Unit_Name := Defining_Identifier (Unit_Name); end loop; return Unit_Name; end Scope_Of_Spec; ---------------------- -- Set_Renaming_TSS -- ---------------------- procedure Set_Renaming_TSS (Typ : Entity_Id; Nam : Entity_Id; TSS_Nam : TSS_Name_Type) is Loc : constant Source_Ptr := Sloc (Nam); Spec : constant Node_Id := Parent (Nam); TSS_Node : constant Node_Id := Make_Subprogram_Renaming_Declaration (Loc, Specification => Copy_Specification (Loc, Spec => Spec, New_Name => Make_TSS_Name (Typ, TSS_Nam)), Name => New_Occurrence_Of (Nam, Loc)); Snam : constant Entity_Id := Defining_Unit_Name (Specification (TSS_Node)); begin if Nkind (Spec) = N_Function_Specification then Set_Ekind (Snam, E_Function); Set_Etype (Snam, Entity (Result_Definition (Spec))); else Set_Ekind (Snam, E_Procedure); Set_Etype (Snam, Standard_Void_Type); end if; Set_TSS (Typ, Snam); end Set_Renaming_TSS; ---------------------------------------------- -- Specific_Add_Obj_RPC_Receiver_Completion -- ---------------------------------------------- procedure Specific_Add_Obj_RPC_Receiver_Completion (Loc : Source_Ptr; Decls : List_Id; RPC_Receiver : Entity_Id; Stub_Elements : Stub_Structure) is begin case Get_PCS_Name is when Name_PolyORB_DSA => PolyORB_Support.Add_Obj_RPC_Receiver_Completion (Loc, Decls, RPC_Receiver, Stub_Elements); when others => GARLIC_Support.Add_Obj_RPC_Receiver_Completion (Loc, Decls, RPC_Receiver, Stub_Elements); end case; end Specific_Add_Obj_RPC_Receiver_Completion; -------------------------------- -- Specific_Add_RACW_Features -- -------------------------------- procedure Specific_Add_RACW_Features (RACW_Type : Entity_Id; Desig : Entity_Id; Stub_Type : Entity_Id; Stub_Type_Access : Entity_Id; RPC_Receiver_Decl : Node_Id; Body_Decls : List_Id) is begin case Get_PCS_Name is when Name_PolyORB_DSA => PolyORB_Support.Add_RACW_Features (RACW_Type, Desig, Stub_Type, Stub_Type_Access, RPC_Receiver_Decl, Body_Decls); when others => GARLIC_Support.Add_RACW_Features (RACW_Type, Stub_Type, Stub_Type_Access, RPC_Receiver_Decl, Body_Decls); end case; end Specific_Add_RACW_Features; -------------------------------- -- Specific_Add_RAST_Features -- -------------------------------- procedure Specific_Add_RAST_Features (Vis_Decl : Node_Id; RAS_Type : Entity_Id) is begin case Get_PCS_Name is when Name_PolyORB_DSA => PolyORB_Support.Add_RAST_Features (Vis_Decl, RAS_Type); when others => GARLIC_Support.Add_RAST_Features (Vis_Decl, RAS_Type); end case; end Specific_Add_RAST_Features; -------------------------------------------------- -- Specific_Add_Receiving_Stubs_To_Declarations -- -------------------------------------------------- procedure Specific_Add_Receiving_Stubs_To_Declarations (Pkg_Spec : Node_Id; Decls : List_Id; Stmts : List_Id) is begin case Get_PCS_Name is when Name_PolyORB_DSA => PolyORB_Support.Add_Receiving_Stubs_To_Declarations (Pkg_Spec, Decls, Stmts); when others => GARLIC_Support.Add_Receiving_Stubs_To_Declarations (Pkg_Spec, Decls, Stmts); end case; end Specific_Add_Receiving_Stubs_To_Declarations; ------------------------------------------ -- Specific_Build_General_Calling_Stubs -- ------------------------------------------ procedure Specific_Build_General_Calling_Stubs (Decls : List_Id; Statements : List_Id; Target : RPC_Target; Subprogram_Id : Node_Id; Asynchronous : Node_Id := Empty; Is_Known_Asynchronous : Boolean := False; Is_Known_Non_Asynchronous : Boolean := False; Is_Function : Boolean; Spec : Node_Id; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Nod : Node_Id) is begin case Get_PCS_Name is when Name_PolyORB_DSA => PolyORB_Support.Build_General_Calling_Stubs (Decls, Statements, Target.Object, Subprogram_Id, Asynchronous, Is_Known_Asynchronous, Is_Known_Non_Asynchronous, Is_Function, Spec, Stub_Type, RACW_Type, Nod); when others => GARLIC_Support.Build_General_Calling_Stubs (Decls, Statements, Target.Partition, Target.RPC_Receiver, Subprogram_Id, Asynchronous, Is_Known_Asynchronous, Is_Known_Non_Asynchronous, Is_Function, Spec, Stub_Type, RACW_Type, Nod); end case; end Specific_Build_General_Calling_Stubs; -------------------------------------- -- Specific_Build_RPC_Receiver_Body -- -------------------------------------- procedure Specific_Build_RPC_Receiver_Body (RPC_Receiver : Entity_Id; Request : out Entity_Id; Subp_Id : out Entity_Id; Subp_Index : out Entity_Id; Stmts : out List_Id; Decl : out Node_Id) is begin case Get_PCS_Name is when Name_PolyORB_DSA => PolyORB_Support.Build_RPC_Receiver_Body (RPC_Receiver, Request, Subp_Id, Subp_Index, Stmts, Decl); when others => GARLIC_Support.Build_RPC_Receiver_Body (RPC_Receiver, Request, Subp_Id, Subp_Index, Stmts, Decl); end case; end Specific_Build_RPC_Receiver_Body; -------------------------------- -- Specific_Build_Stub_Target -- -------------------------------- function Specific_Build_Stub_Target (Loc : Source_Ptr; Decls : List_Id; RCI_Locator : Entity_Id; Controlling_Parameter : Entity_Id) return RPC_Target is begin case Get_PCS_Name is when Name_PolyORB_DSA => return PolyORB_Support.Build_Stub_Target (Loc, Decls, RCI_Locator, Controlling_Parameter); when others => return GARLIC_Support.Build_Stub_Target (Loc, Decls, RCI_Locator, Controlling_Parameter); end case; end Specific_Build_Stub_Target; -------------------------------- -- Specific_RPC_Receiver_Decl -- -------------------------------- function Specific_RPC_Receiver_Decl (RACW_Type : Entity_Id) return Node_Id is begin case Get_PCS_Name is when Name_PolyORB_DSA => return PolyORB_Support.RPC_Receiver_Decl (RACW_Type); when others => return GARLIC_Support.RPC_Receiver_Decl (RACW_Type); end case; end Specific_RPC_Receiver_Decl; ----------------------------------------------- -- Specific_Build_Subprogram_Receiving_Stubs -- ----------------------------------------------- function Specific_Build_Subprogram_Receiving_Stubs (Vis_Decl : Node_Id; Asynchronous : Boolean; Dynamically_Asynchronous : Boolean := False; Stub_Type : Entity_Id := Empty; RACW_Type : Entity_Id := Empty; Parent_Primitive : Entity_Id := Empty) return Node_Id is begin case Get_PCS_Name is when Name_PolyORB_DSA => return PolyORB_Support.Build_Subprogram_Receiving_Stubs (Vis_Decl, Asynchronous, Dynamically_Asynchronous, Stub_Type, RACW_Type, Parent_Primitive); when others => return GARLIC_Support.Build_Subprogram_Receiving_Stubs (Vis_Decl, Asynchronous, Dynamically_Asynchronous, Stub_Type, RACW_Type, Parent_Primitive); end case; end Specific_Build_Subprogram_Receiving_Stubs; ------------------------------- -- Transmit_As_Unconstrained -- ------------------------------- function Transmit_As_Unconstrained (Typ : Entity_Id) return Boolean is begin return not (Is_Elementary_Type (Typ) or else Is_Constrained (Typ)) or else (Is_Access_Type (Typ) and then Can_Never_Be_Null (Typ)); end Transmit_As_Unconstrained; -------------------------- -- Underlying_RACW_Type -- -------------------------- function Underlying_RACW_Type (RAS_Typ : Entity_Id) return Entity_Id is Record_Type : Entity_Id; begin if Ekind (RAS_Typ) = E_Record_Type then Record_Type := RAS_Typ; else pragma Assert (Present (Equivalent_Type (RAS_Typ))); Record_Type := Equivalent_Type (RAS_Typ); end if; return Etype (Subtype_Indication (Component_Definition (First (Component_Items (Component_List (Type_Definition (Declaration_Node (Record_Type)))))))); end Underlying_RACW_Type; end Exp_Dist;