1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1998-2008, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Atree
; use Atree
;
27 with Einfo
; use Einfo
;
28 with Exp_Util
; use Exp_Util
;
29 with Nmake
; use Nmake
;
30 with Namet
; use Namet
;
31 with Nlists
; use Nlists
;
32 with Rtsfind
; use Rtsfind
;
34 with Sem_Util
; use Sem_Util
;
35 with Sinfo
; use Sinfo
;
36 with Snames
; use Snames
;
37 with Stand
; use Stand
;
38 with Stringt
; use Stringt
;
39 with Tbuild
; use Tbuild
;
41 package body Exp_Smem
is
43 Insert_Node
: Node_Id
;
44 -- Node after which a write call is to be inserted
46 -----------------------
47 -- Local Subprograms --
48 -----------------------
50 procedure Add_Read_Before
(N
: Node_Id
);
51 -- Insert a Shared_Var_ROpen call for variable before node N
53 procedure Add_Write_After
(N
: Node_Id
);
54 -- Insert a Shared_Var_WOpen call for variable after the node
55 -- Insert_Node, as recorded by On_Lhs_Of_Assignment (where it points
56 -- to the assignment statement) or Is_Out_Actual (where it points to
57 -- the procedure call statement).
59 procedure Build_Full_Name
(E
: Entity_Id
; N
: out String_Id
);
60 -- Build the fully qualified string name of a shared variable
62 function On_Lhs_Of_Assignment
(N
: Node_Id
) return Boolean;
63 -- Determines if N is on the left hand of the assignment. This means
64 -- that either it is a simple variable, or it is a record or array
65 -- variable with a corresponding selected or indexed component on
66 -- the left side of an assignment. If the result is True, then
67 -- Insert_Node is set to point to the assignment
69 function Is_Out_Actual
(N
: Node_Id
) return Boolean;
70 -- In a similar manner, this function determines if N appears as an
71 -- OUT or IN OUT parameter to a procedure call. If the result is
72 -- True, then Insert_Node is set to point to the call.
74 function Build_Shared_Var_Proc_Call
77 N
: Name_Id
) return Node_Id
;
78 -- Build a call to support procedure N for shared object E (provided by
79 -- the instance of System.Shared_Storage.Shared_Var_Procs associated to E).
81 --------------------------------
82 -- Build_Shared_Var_Proc_Call --
83 --------------------------------
85 function Build_Shared_Var_Proc_Call
88 N
: Name_Id
) return Node_Id
is
90 return Make_Procedure_Call_Statement
(Loc
,
91 Name
=> Make_Selected_Component
(Loc
,
93 New_Occurrence_Of
(Shared_Var_Procs_Instance
(E
), Loc
),
94 Selector_Name
=> Make_Identifier
(Loc
, Chars
=> N
)));
95 end Build_Shared_Var_Proc_Call
;
101 procedure Add_Read_Before
(N
: Node_Id
) is
102 Loc
: constant Source_Ptr
:= Sloc
(N
);
103 Ent
: constant Node_Id
:= Entity
(N
);
105 if Present
(Shared_Var_Procs_Instance
(Ent
)) then
106 Insert_Action
(N
, Build_Shared_Var_Proc_Call
(Loc
, Ent
, Name_Read
));
110 -------------------------------
111 -- Add_Shared_Var_Lock_Procs --
112 -------------------------------
114 procedure Add_Shared_Var_Lock_Procs
(N
: Node_Id
) is
115 Loc
: constant Source_Ptr
:= Sloc
(N
);
116 Obj
: constant Entity_Id
:= Entity
(Expression
(First_Actual
(N
)));
121 -- We have to add Shared_Var_Lock and Shared_Var_Unlock calls around
122 -- the procedure or function call node. First we locate the right
123 -- place to do the insertion, which is the call itself in the
124 -- procedure call case, or else the nearest non subexpression
125 -- node that contains the function call.
128 while Nkind
(Inode
) /= N_Procedure_Call_Statement
129 and then Nkind
(Inode
) in N_Subexpr
131 Inode
:= Parent
(Inode
);
134 -- Now insert the Lock and Unlock calls and the read/write calls
136 -- Two concerns here. First we are not dealing with the exception
137 -- case, really we need some kind of cleanup routine to do the
138 -- Unlock. Second, these lock calls should be inside the protected
139 -- object processing, not outside, otherwise they can be done at
140 -- the wrong priority, resulting in dead lock situations ???
142 Build_Full_Name
(Obj
, Vnm
);
144 -- First insert the Lock call before
146 Insert_Before_And_Analyze
(Inode
,
147 Make_Procedure_Call_Statement
(Loc
,
148 Name
=> New_Occurrence_Of
(RTE
(RE_Shared_Var_Lock
), Loc
),
149 Parameter_Associations
=> New_List
(
150 Make_String_Literal
(Loc
, Vnm
))));
152 -- Now, right after the Lock, insert a call to read the object
154 Insert_Before_And_Analyze
(Inode
,
155 Build_Shared_Var_Proc_Call
(Loc
, Obj
, Name_Read
));
157 -- Now insert the Unlock call after
159 Insert_After_And_Analyze
(Inode
,
160 Make_Procedure_Call_Statement
(Loc
,
161 Name
=> New_Occurrence_Of
(RTE
(RE_Shared_Var_Unlock
), Loc
),
162 Parameter_Associations
=> New_List
(
163 Make_String_Literal
(Loc
, Vnm
))));
165 -- Now for a procedure call, but not a function call, insert the
166 -- call to write the object just before the unlock.
168 if Nkind
(N
) = N_Procedure_Call_Statement
then
169 Insert_After_And_Analyze
(Inode
,
170 Build_Shared_Var_Proc_Call
(Loc
, Obj
, Name_Write
));
173 end Add_Shared_Var_Lock_Procs
;
175 ---------------------
176 -- Add_Write_After --
177 ---------------------
179 procedure Add_Write_After
(N
: Node_Id
) is
180 Loc
: constant Source_Ptr
:= Sloc
(N
);
181 Ent
: constant Node_Id
:= Entity
(N
);
184 if Present
(Shared_Var_Procs_Instance
(Ent
)) then
185 Insert_After_And_Analyze
(Insert_Node
,
186 Build_Shared_Var_Proc_Call
(Loc
, Ent
, Name_Write
));
190 ---------------------
191 -- Build_Full_Name --
192 ---------------------
194 procedure Build_Full_Name
(E
: Entity_Id
; N
: out String_Id
) is
196 procedure Build_Name
(E
: Entity_Id
);
197 -- This is a recursive routine used to construct the fully qualified
198 -- string name of the package corresponding to the shared variable.
204 procedure Build_Name
(E
: Entity_Id
) is
206 if Scope
(E
) /= Standard_Standard
then
207 Build_Name
(Scope
(E
));
208 Store_String_Char
('.');
211 Get_Decoded_Name_String
(Chars
(E
));
212 Store_String_Chars
(Name_Buffer
(1 .. Name_Len
));
215 -- Start of processing for Build_Full_Name
223 ------------------------------------
224 -- Expand_Shared_Passive_Variable --
225 ------------------------------------
227 procedure Expand_Shared_Passive_Variable
(N
: Node_Id
) is
228 Typ
: constant Entity_Id
:= Etype
(N
);
231 -- Nothing to do for protected or limited objects
233 if Is_Limited_Type
(Typ
) or else Is_Concurrent_Type
(Typ
) then
236 -- If we are on the left hand side of an assignment, then we add
237 -- the write call after the assignment.
239 elsif On_Lhs_Of_Assignment
(N
) then
242 -- If we are a parameter for an out or in out formal, then put
243 -- the read before and the write after.
245 elsif Is_Out_Actual
(N
) then
249 -- All other cases are simple reads
254 end Expand_Shared_Passive_Variable
;
260 function Is_Out_Actual
(N
: Node_Id
) return Boolean is
265 Find_Actual
(N
, Formal
, Call
);
271 if Ekind
(Formal
) = E_Out_Parameter
273 Ekind
(Formal
) = E_In_Out_Parameter
283 ---------------------------
284 -- Make_Shared_Var_Procs --
285 ---------------------------
287 function Make_Shared_Var_Procs
(N
: Node_Id
) return Node_Id
is
288 Loc
: constant Source_Ptr
:= Sloc
(N
);
289 Ent
: constant Entity_Id
:= Defining_Identifier
(N
);
290 Typ
: constant Entity_Id
:= Etype
(Ent
);
293 After
: constant Node_Id
:= Next
(N
);
294 -- Node located right after N originally (after insertion of the SV
295 -- procs this node is right after the last inserted node).
297 SVP_Instance
: constant Entity_Id
:= Make_Defining_Identifier
(Loc
,
298 Chars
=> New_External_Name
(Chars
(Ent
), 'G'));
299 -- Instance of System.Shared_Storage.Shared_Var_Procs associated
302 Instantiation
: Node_Id
;
303 -- Package instantiation node for SVP_Instance
305 -- Start of processing for Make_Shared_Var_Procs
308 Build_Full_Name
(Ent
, Vnm
);
310 -- We turn off Shared_Passive during construction and analysis of
311 -- the generic package instantiation, to avoid improper attempts to
312 -- process the variable references within these instantiation.
314 Set_Is_Shared_Passive
(Ent
, False);
316 -- Construct generic package instantiation
318 -- package varG is new Shared_Var_Procs (Typ, var, "pkg.var");
321 Make_Package_Instantiation
(Loc
,
322 Defining_Unit_Name
=> SVP_Instance
,
324 New_Occurrence_Of
(RTE
(RE_Shared_Var_Procs
), Loc
),
325 Generic_Associations
=> New_List
(
326 Make_Generic_Association
(Loc
, Explicit_Generic_Actual_Parameter
=>
327 New_Occurrence_Of
(Typ
, Loc
)),
328 Make_Generic_Association
(Loc
, Explicit_Generic_Actual_Parameter
=>
329 New_Occurrence_Of
(Ent
, Loc
)),
330 Make_Generic_Association
(Loc
, Explicit_Generic_Actual_Parameter
=>
331 Make_String_Literal
(Loc
, Vnm
))));
333 Insert_After_And_Analyze
(N
, Instantiation
);
335 Set_Is_Shared_Passive
(Ent
, True);
336 Set_Shared_Var_Procs_Instance
337 (Ent
, Defining_Entity
(Instance_Spec
(Instantiation
)));
339 -- Return last node before After
342 Nod
: Node_Id
:= Next
(N
);
345 while Next
(Nod
) /= After
loop
351 end Make_Shared_Var_Procs
;
353 --------------------------
354 -- On_Lhs_Of_Assignment --
355 --------------------------
357 function On_Lhs_Of_Assignment
(N
: Node_Id
) return Boolean is
358 P
: constant Node_Id
:= Parent
(N
);
361 if Nkind
(P
) = N_Assignment_Statement
then
369 elsif (Nkind
(P
) = N_Indexed_Component
371 Nkind
(P
) = N_Selected_Component
)
372 and then N
= Prefix
(P
)
374 return On_Lhs_Of_Assignment
(P
);
379 end On_Lhs_Of_Assignment
;