OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [ada/] [exp_smem.adb] - Blame information for rev 16

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                             E X P _ S M E M                              --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1998-2005, Free Software Foundation, Inc.         --
10
--                                                                          --
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 2,  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 COPYING.  If not, write --
19
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
20
-- Boston, MA 02110-1301, USA.                                              --
21
--                                                                          --
22
-- GNAT was originally developed  by the GNAT team at  New York University. --
23
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
24
--                                                                          --
25
------------------------------------------------------------------------------
26
 
27
with Atree;    use Atree;
28
with Einfo;    use Einfo;
29
with Exp_Util; use Exp_Util;
30
with Nmake;    use Nmake;
31
with Namet;    use Namet;
32
with Nlists;   use Nlists;
33
with Rtsfind;  use Rtsfind;
34
with Sem;      use Sem;
35
with Sem_Util; use Sem_Util;
36
with Sinfo;    use Sinfo;
37
with Snames;   use Snames;
38
with Stand;    use Stand;
39
with Stringt;  use Stringt;
40
with Tbuild;   use Tbuild;
41
 
42
package body Exp_Smem is
43
 
44
   Insert_Node : Node_Id;
45
   --  Node after which a write call is to be inserted
46
 
47
   -----------------------
48
   -- Local Subprograms --
49
   -----------------------
50
 
51
   procedure Add_Read_Before (N : Node_Id);
52
   --  Insert a Shared_Var_ROpen call for variable before node N
53
 
54
   procedure Add_Write_After (N : Node_Id);
55
   --  Insert a Shared_Var_WOpen call for variable after the node
56
   --  Insert_Node, as recorded by On_Lhs_Of_Assigment (where it points
57
   --  to the assignment statement) or Is_Out_Actual (where it points to
58
   --  the procedure call statement).
59
 
60
   procedure Build_Full_Name
61
     (E : in  Entity_Id;
62
      N : out String_Id);
63
   --  Build the fully qualified string name of a shared variable
64
 
65
   function On_Lhs_Of_Assignment (N : Node_Id) return Boolean;
66
   --  Determines if N is on the left hand of the assignment. This means
67
   --  that either it is a simple variable, or it is a record or array
68
   --  variable with a corresponding selected or indexed component on
69
   --  the left side of an assignment. If the result is True, then
70
   --  Insert_Node is set to point to the assignment
71
 
72
   function Is_Out_Actual (N : Node_Id) return Boolean;
73
   --  In a similar manner, this function determines if N appears as an
74
   --  OUT or IN OUT parameter to a procedure call. If the result is
75
   --  True, then Insert_Node is set to point to the assignment.
76
 
77
   ---------------------
78
   -- Add_Read_Before --
79
   ---------------------
80
 
81
   procedure Add_Read_Before (N : Node_Id) is
82
      Loc : constant Source_Ptr := Sloc (N);
83
      Ent : constant Node_Id    := Entity (N);
84
 
85
   begin
86
      if Present (Shared_Var_Read_Proc (Ent)) then
87
         Insert_Action (N,
88
           Make_Procedure_Call_Statement (Loc,
89
             Name =>
90
               New_Occurrence_Of (Shared_Var_Read_Proc (Ent), Loc),
91
             Parameter_Associations => Empty_List));
92
      end if;
93
   end Add_Read_Before;
94
 
95
   -------------------------------
96
   -- Add_Shared_Var_Lock_Procs --
97
   -------------------------------
98
 
99
   procedure Add_Shared_Var_Lock_Procs (N : Node_Id) is
100
      Loc   : constant Source_Ptr := Sloc (N);
101
      Obj   : constant Entity_Id  := Entity (Expression (First_Actual (N)));
102
      Inode : Node_Id;
103
      Vnm   : String_Id;
104
 
105
   begin
106
      --  We have to add Shared_Var_Lock and Shared_Var_Unlock calls around
107
      --  the procedure or function call node. First we locate the right
108
      --  place to do the insertion, which is the call itself in the
109
      --  procedure call case, or else the nearest non subexpression
110
      --  node that contains the function call.
111
 
112
      Inode := N;
113
      while Nkind (Inode) /= N_Procedure_Call_Statement
114
        and then Nkind (Inode) in N_Subexpr
115
      loop
116
         Inode := Parent (Inode);
117
      end loop;
118
 
119
      --  Now insert the Lock and Unlock calls and the read/write calls
120
 
121
      --  Two concerns here. First we are not dealing with the exception
122
      --  case, really we need some kind of cleanup routine to do the
123
      --  Unlock. Second, these lock calls should be inside the protected
124
      --  object processing, not outside, otherwise they can be done at
125
      --  the wrong priority, resulting in dead lock situations ???
126
 
127
      Build_Full_Name (Obj, Vnm);
128
 
129
      --  First insert the Lock call before
130
 
131
      Insert_Before_And_Analyze (Inode,
132
        Make_Procedure_Call_Statement (Loc,
133
          Name => New_Occurrence_Of (RTE (RE_Shared_Var_Lock), Loc),
134
          Parameter_Associations => New_List (
135
            Make_String_Literal (Loc, Vnm))));
136
 
137
      --  Now, right after the Lock, insert a call to read the object
138
 
139
      Insert_Before_And_Analyze (Inode,
140
        Make_Procedure_Call_Statement (Loc,
141
          Name => New_Occurrence_Of (Shared_Var_Read_Proc (Obj), Loc)));
142
 
143
      --  Now insert the Unlock call after
144
 
145
      Insert_After_And_Analyze (Inode,
146
        Make_Procedure_Call_Statement (Loc,
147
          Name => New_Occurrence_Of (RTE (RE_Shared_Var_Unlock), Loc),
148
          Parameter_Associations => New_List (
149
            Make_String_Literal (Loc, Vnm))));
150
 
151
      --  Now for a procedure call, but not a function call, insert the
152
      --  call to write the object just before the unlock.
153
 
154
      if Nkind (N) = N_Procedure_Call_Statement then
155
         Insert_After_And_Analyze (Inode,
156
           Make_Procedure_Call_Statement (Loc,
157
             Name => New_Occurrence_Of (Shared_Var_Assign_Proc (Obj), Loc)));
158
      end if;
159
 
160
   end Add_Shared_Var_Lock_Procs;
161
 
162
   ---------------------
163
   -- Add_Write_After --
164
   ---------------------
165
 
166
   procedure Add_Write_After (N : Node_Id) is
167
      Loc : constant Source_Ptr := Sloc (N);
168
      Ent : constant Node_Id    := Entity (N);
169
 
170
   begin
171
      if Present (Shared_Var_Assign_Proc (Ent)) then
172
         Insert_After_And_Analyze (Insert_Node,
173
           Make_Procedure_Call_Statement (Loc,
174
             Name =>
175
               New_Occurrence_Of (Shared_Var_Assign_Proc (Ent), Loc),
176
             Parameter_Associations => Empty_List));
177
      end if;
178
   end Add_Write_After;
179
 
180
   ---------------------
181
   -- Build_Full_Name --
182
   ---------------------
183
 
184
   procedure Build_Full_Name
185
     (E : in  Entity_Id;
186
      N : out String_Id)
187
   is
188
 
189
      procedure Build_Name (E : Entity_Id);
190
      --  This is a recursive routine used to construct the fully
191
      --  qualified string name of the package corresponding to the
192
      --  shared variable.
193
 
194
      procedure Build_Name (E : Entity_Id) is
195
      begin
196
         if Scope (E) /= Standard_Standard then
197
            Build_Name (Scope (E));
198
            Store_String_Char ('.');
199
         end if;
200
 
201
         Get_Decoded_Name_String (Chars (E));
202
         Store_String_Chars (Name_Buffer (1 .. Name_Len));
203
      end Build_Name;
204
 
205
   begin
206
      Start_String;
207
      Build_Name (E);
208
      N := End_String;
209
   end Build_Full_Name;
210
 
211
   ------------------------------------
212
   -- Expand_Shared_Passive_Variable --
213
   ------------------------------------
214
 
215
   procedure Expand_Shared_Passive_Variable (N : Node_Id) is
216
      Typ : constant Entity_Id := Etype (N);
217
 
218
   begin
219
      --  Nothing to do for protected or limited objects
220
 
221
      if Is_Limited_Type (Typ) or else Is_Concurrent_Type (Typ) then
222
         return;
223
 
224
      --  If we are on the left hand side of an assignment, then we add
225
      --  the write call after the assignment.
226
 
227
      elsif On_Lhs_Of_Assignment (N) then
228
         Add_Write_After (N);
229
 
230
      --  If we are a parameter for an out or in out formal, then put
231
      --  the read before and the write after.
232
 
233
      elsif Is_Out_Actual (N) then
234
         Add_Read_Before (N);
235
         Add_Write_After (N);
236
 
237
      --  All other cases are simple reads
238
 
239
      else
240
         Add_Read_Before (N);
241
      end if;
242
   end Expand_Shared_Passive_Variable;
243
 
244
   -------------------
245
   -- Is_Out_Actual --
246
   -------------------
247
 
248
   function Is_Out_Actual (N : Node_Id) return Boolean is
249
      Parnt  : constant Node_Id := Parent (N);
250
      Formal : Entity_Id;
251
      Call   : Node_Id;
252
      Actual : Node_Id;
253
 
254
   begin
255
      if (Nkind (Parnt) = N_Indexed_Component
256
            or else
257
          Nkind (Parnt) = N_Selected_Component)
258
        and then N = Prefix (Parnt)
259
      then
260
         return Is_Out_Actual (Parnt);
261
 
262
      elsif Nkind (Parnt) = N_Parameter_Association
263
        and then N = Explicit_Actual_Parameter (Parnt)
264
      then
265
         Call := Parent (Parnt);
266
 
267
      elsif Nkind (Parnt) = N_Procedure_Call_Statement then
268
         Call := Parnt;
269
 
270
      else
271
         return False;
272
      end if;
273
 
274
      --  Fall here if we are definitely a parameter
275
 
276
      Actual := First_Actual (Call);
277
      Formal := First_Formal (Entity (Name (Call)));
278
 
279
      loop
280
         if Actual = N then
281
            if Ekind (Formal) /= E_In_Parameter then
282
               Insert_Node := Call;
283
               return True;
284
            else
285
               return False;
286
            end if;
287
 
288
         else
289
            Actual := Next_Actual (Actual);
290
            Formal := Next_Formal (Formal);
291
         end if;
292
      end loop;
293
   end Is_Out_Actual;
294
 
295
   ---------------------------
296
   -- Make_Shared_Var_Procs --
297
   ---------------------------
298
 
299
   procedure Make_Shared_Var_Procs (N : Node_Id) is
300
      Loc : constant Source_Ptr := Sloc (N);
301
      Ent : constant Entity_Id  := Defining_Identifier (N);
302
      Typ : constant Entity_Id  := Etype (Ent);
303
      Vnm : String_Id;
304
      Atr : Node_Id;
305
 
306
      Assign_Proc : constant Entity_Id :=
307
                      Make_Defining_Identifier (Loc,
308
                        Chars => New_External_Name (Chars (Ent), 'A'));
309
 
310
      Read_Proc : constant Entity_Id :=
311
                    Make_Defining_Identifier (Loc,
312
                      Chars => New_External_Name (Chars (Ent), 'R'));
313
 
314
      S : Entity_Id;
315
 
316
   --  Start of processing for Make_Shared_Var_Procs
317
 
318
   begin
319
      Build_Full_Name (Ent, Vnm);
320
 
321
      --  We turn off Shared_Passive during construction and analysis of
322
      --  the assign and read routines, to avoid improper attempts to
323
      --  process the variable references within these procedures.
324
 
325
      Set_Is_Shared_Passive (Ent, False);
326
 
327
      --  Construct assignment routine
328
 
329
      --    procedure VarA is
330
      --       S : Ada.Streams.Stream_IO.Stream_Access;
331
      --    begin
332
      --       S := Shared_Var_WOpen ("pkg.var");
333
      --       typ'Write (S, var);
334
      --       Shared_Var_Close (S);
335
      --    end VarA;
336
 
337
      S   := Make_Defining_Identifier (Loc, Name_uS);
338
 
339
      Atr :=
340
        Make_Attribute_Reference (Loc,
341
          Prefix => New_Occurrence_Of (Typ, Loc),
342
          Attribute_Name => Name_Write,
343
          Expressions => New_List (
344
            New_Reference_To (S, Loc),
345
            New_Occurrence_Of (Ent, Loc)));
346
 
347
      Insert_After_And_Analyze (N,
348
        Make_Subprogram_Body (Loc,
349
          Specification =>
350
            Make_Procedure_Specification (Loc,
351
              Defining_Unit_Name => Assign_Proc),
352
 
353
         --  S : Ada.Streams.Stream_IO.Stream_Access;
354
 
355
          Declarations => New_List (
356
            Make_Object_Declaration (Loc,
357
              Defining_Identifier => S,
358
              Object_Definition =>
359
                New_Occurrence_Of (RTE (RE_Stream_Access), Loc))),
360
 
361
          Handled_Statement_Sequence =>
362
            Make_Handled_Sequence_Of_Statements (Loc,
363
              Statements => New_List (
364
 
365
               --  S := Shared_Var_WOpen ("pkg.var");
366
 
367
                Make_Assignment_Statement (Loc,
368
                  Name => New_Reference_To (S, Loc),
369
                  Expression =>
370
                    Make_Function_Call (Loc,
371
                      Name =>
372
                        New_Occurrence_Of
373
                          (RTE (RE_Shared_Var_WOpen), Loc),
374
                      Parameter_Associations => New_List (
375
                        Make_String_Literal (Loc, Vnm)))),
376
 
377
                Atr,
378
 
379
               --  Shared_Var_Close (S);
380
 
381
                Make_Procedure_Call_Statement (Loc,
382
                  Name =>
383
                    New_Occurrence_Of (RTE (RE_Shared_Var_Close), Loc),
384
                  Parameter_Associations =>
385
                    New_List (New_Reference_To (S, Loc)))))));
386
 
387
      --  Construct read routine
388
 
389
      --    procedure varR is
390
      --       S : Ada.Streams.Stream_IO.Stream_Access;
391
      --    begin
392
      --       S := Shared_Var_ROpen ("pkg.var");
393
      --       if S /= null then
394
      --          typ'Read (S, Var);
395
      --          Shared_Var_Close (S);
396
      --       end if;
397
      --    end varR;
398
 
399
      S   := Make_Defining_Identifier (Loc, Name_uS);
400
 
401
      Atr :=
402
        Make_Attribute_Reference (Loc,
403
          Prefix => New_Occurrence_Of (Typ, Loc),
404
          Attribute_Name => Name_Read,
405
          Expressions => New_List (
406
            New_Reference_To (S, Loc),
407
            New_Occurrence_Of (Ent, Loc)));
408
 
409
      Insert_After_And_Analyze (N,
410
        Make_Subprogram_Body (Loc,
411
          Specification =>
412
            Make_Procedure_Specification (Loc,
413
              Defining_Unit_Name => Read_Proc),
414
 
415
         --  S : Ada.Streams.Stream_IO.Stream_Access;
416
 
417
          Declarations => New_List (
418
            Make_Object_Declaration (Loc,
419
              Defining_Identifier => S,
420
              Object_Definition =>
421
                New_Occurrence_Of (RTE (RE_Stream_Access), Loc))),
422
 
423
          Handled_Statement_Sequence =>
424
            Make_Handled_Sequence_Of_Statements (Loc,
425
              Statements => New_List (
426
 
427
               --  S := Shared_Var_ROpen ("pkg.var");
428
 
429
                Make_Assignment_Statement (Loc,
430
                  Name => New_Reference_To (S, Loc),
431
                  Expression =>
432
                    Make_Function_Call (Loc,
433
                      Name =>
434
                        New_Occurrence_Of
435
                          (RTE (RE_Shared_Var_ROpen), Loc),
436
                      Parameter_Associations => New_List (
437
                        Make_String_Literal (Loc, Vnm)))),
438
 
439
               --  if S /= null then
440
 
441
                Make_Implicit_If_Statement (N,
442
                  Condition =>
443
                    Make_Op_Ne (Loc,
444
                      Left_Opnd  => New_Reference_To (S, Loc),
445
                      Right_Opnd => Make_Null (Loc)),
446
 
447
                   Then_Statements => New_List (
448
 
449
                     --  typ'Read (S, Var);
450
 
451
                     Atr,
452
 
453
                     --  Shared_Var_Close (S);
454
 
455
                     Make_Procedure_Call_Statement (Loc,
456
                       Name =>
457
                         New_Occurrence_Of
458
                           (RTE (RE_Shared_Var_Close), Loc),
459
                       Parameter_Associations =>
460
                         New_List (New_Reference_To (S, Loc)))))))));
461
 
462
      Set_Is_Shared_Passive      (Ent, True);
463
      Set_Shared_Var_Assign_Proc (Ent, Assign_Proc);
464
      Set_Shared_Var_Read_Proc   (Ent, Read_Proc);
465
   end Make_Shared_Var_Procs;
466
 
467
   --------------------------
468
   -- On_Lhs_Of_Assignment --
469
   --------------------------
470
 
471
   function On_Lhs_Of_Assignment (N : Node_Id) return Boolean is
472
      P : constant Node_Id := Parent (N);
473
 
474
   begin
475
      if Nkind (P) = N_Assignment_Statement then
476
         if N = Name (P) then
477
            Insert_Node := P;
478
            return True;
479
         else
480
            return False;
481
         end if;
482
 
483
      elsif (Nkind (P) = N_Indexed_Component
484
               or else
485
             Nkind (P) = N_Selected_Component)
486
        and then N = Prefix (P)
487
      then
488
         return On_Lhs_Of_Assignment (P);
489
 
490
      else
491
         return False;
492
      end if;
493
   end On_Lhs_Of_Assignment;
494
 
495
end Exp_Smem;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.