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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [ada/] [exp_code.adb] - Blame information for rev 847

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

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                             E X P _ C O D E                              --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1996-2008, 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 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.          --
20
--                                                                          --
21
-- GNAT was originally developed  by the GNAT team at  New York University. --
22
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
23
--                                                                          --
24
------------------------------------------------------------------------------
25
 
26
with Atree;    use Atree;
27
with Einfo;    use Einfo;
28
with Errout;   use Errout;
29
with Fname;    use Fname;
30
with Lib;      use Lib;
31
with Namet;    use Namet;
32
with Nlists;   use Nlists;
33
with Nmake;    use Nmake;
34
with Opt;      use Opt;
35
with Rtsfind;  use Rtsfind;
36
with Sem_Aux;  use Sem_Aux;
37
with Sem_Eval; use Sem_Eval;
38
with Sem_Util; use Sem_Util;
39
with Sem_Warn; use Sem_Warn;
40
with Sinfo;    use Sinfo;
41
with Stringt;  use Stringt;
42
with Tbuild;   use Tbuild;
43
 
44
package body Exp_Code is
45
 
46
   -----------------------
47
   -- Local_Subprograms --
48
   -----------------------
49
 
50
   function Asm_Constraint (Operand_Var : Node_Id) return Node_Id;
51
   --  Common processing for Asm_Input_Constraint and Asm_Output_Constraint.
52
   --  Obtains the constraint argument from the global operand variable
53
   --  Operand_Var, which must be non-Empty.
54
 
55
   function Asm_Operand (Operand_Var : Node_Id) return Node_Id;
56
   --  Common processing for Asm_Input_Value and Asm_Output_Variable. Obtains
57
   --  the value/variable argument from Operand_Var, the global operand
58
   --  variable. Returns Empty if no operand available.
59
 
60
   function Get_String_Node (S : Node_Id) return Node_Id;
61
   --  Given S, a static expression node of type String, returns the
62
   --  string literal node. This is needed to deal with the use of constants
63
   --  for these expressions, which is perfectly permissible.
64
 
65
   procedure Next_Asm_Operand (Operand_Var : in out Node_Id);
66
   --  Common processing for Next_Asm_Input and Next_Asm_Output, updates
67
   --  the value of the global operand variable Operand_Var appropriately.
68
 
69
   procedure Setup_Asm_IO_Args (Arg : Node_Id; Operand_Var : out Node_Id);
70
   --  Common processing for Setup_Asm_Inputs and Setup_Asm_Outputs. Arg
71
   --  is the actual parameter from the call, and Operand_Var is the global
72
   --  operand variable to be initialized to the first operand.
73
 
74
   ----------------------
75
   -- Global Variables --
76
   ----------------------
77
 
78
   Current_Input_Operand : Node_Id := Empty;
79
   --  Points to current Asm_Input_Operand attribute reference. Initialized
80
   --  by Setup_Asm_Inputs, updated by Next_Asm_Input, and referenced by
81
   --  Asm_Input_Constraint and Asm_Input_Value.
82
 
83
   Current_Output_Operand : Node_Id := Empty;
84
   --  Points to current Asm_Output_Operand attribute reference. Initialized
85
   --  by Setup_Asm_Outputs, updated by Next_Asm_Output, and referenced by
86
   --  Asm_Output_Constraint and Asm_Output_Variable.
87
 
88
   --------------------
89
   -- Asm_Constraint --
90
   --------------------
91
 
92
   function Asm_Constraint (Operand_Var : Node_Id) return Node_Id is
93
   begin
94
      pragma Assert (Present (Operand_Var));
95
      return Get_String_Node (First (Expressions (Operand_Var)));
96
   end Asm_Constraint;
97
 
98
   --------------------------
99
   -- Asm_Input_Constraint --
100
   --------------------------
101
 
102
   --  Note: error checking on Asm_Input attribute done in Sem_Attr
103
 
104
   function Asm_Input_Constraint return Node_Id is
105
   begin
106
      return Get_String_Node (Asm_Constraint (Current_Input_Operand));
107
   end Asm_Input_Constraint;
108
 
109
   ---------------------
110
   -- Asm_Input_Value --
111
   ---------------------
112
 
113
   --  Note: error checking on Asm_Input attribute done in Sem_Attr
114
 
115
   function Asm_Input_Value return Node_Id is
116
   begin
117
      return Asm_Operand (Current_Input_Operand);
118
   end Asm_Input_Value;
119
 
120
   -----------------
121
   -- Asm_Operand --
122
   -----------------
123
 
124
   function Asm_Operand (Operand_Var : Node_Id) return Node_Id is
125
   begin
126
      if No (Operand_Var) then
127
         return Empty;
128
      elsif Error_Posted (Operand_Var) then
129
         return Error;
130
      else
131
         return Next (First (Expressions (Operand_Var)));
132
      end if;
133
   end Asm_Operand;
134
 
135
   ---------------------------
136
   -- Asm_Output_Constraint --
137
   ---------------------------
138
 
139
   --  Note: error checking on Asm_Output attribute done in Sem_Attr
140
 
141
   function Asm_Output_Constraint return Node_Id is
142
   begin
143
      return Asm_Constraint (Current_Output_Operand);
144
   end Asm_Output_Constraint;
145
 
146
   -------------------------
147
   -- Asm_Output_Variable --
148
   -------------------------
149
 
150
   --  Note: error checking on Asm_Output attribute done in Sem_Attr
151
 
152
   function Asm_Output_Variable return Node_Id is
153
   begin
154
      return Asm_Operand (Current_Output_Operand);
155
   end Asm_Output_Variable;
156
 
157
   ------------------
158
   -- Asm_Template --
159
   ------------------
160
 
161
   function Asm_Template (N : Node_Id) return Node_Id is
162
      Call : constant Node_Id := Expression (Expression (N));
163
      Temp : constant Node_Id := First_Actual (Call);
164
 
165
   begin
166
      --  Require static expression for template. We also allow a string
167
      --  literal (this is useful for Ada 83 mode where string expressions
168
      --  are never static).
169
 
170
      if Is_OK_Static_Expression (Temp)
171
        or else (Ada_Version = Ada_83
172
                  and then Nkind (Temp) = N_String_Literal)
173
      then
174
         return Get_String_Node (Temp);
175
 
176
      else
177
         Flag_Non_Static_Expr ("asm template argument is not static!", Temp);
178
         return Empty;
179
      end if;
180
   end Asm_Template;
181
 
182
   ----------------------
183
   -- Clobber_Get_Next --
184
   ----------------------
185
 
186
   Clobber_Node : Node_Id;
187
   --  String literal node for clobber string. Initialized by Clobber_Setup,
188
   --  and not modified by Clobber_Get_Next. Empty if clobber string was in
189
   --  error (resulting in no clobber arguments being returned).
190
 
191
   Clobber_Ptr : Nat;
192
   --  Pointer to current character of string. Initialized to 1 by the call
193
   --  to Clobber_Setup, and then updated by Clobber_Get_Next.
194
 
195
   function Clobber_Get_Next return Address is
196
      Str : constant String_Id := Strval (Clobber_Node);
197
      Len : constant Nat       := String_Length (Str);
198
      C   : Character;
199
 
200
   begin
201
      if No (Clobber_Node) then
202
         return Null_Address;
203
      end if;
204
 
205
      --  Skip spaces and commas before next register name
206
 
207
      loop
208
         --  Return null string if no more names
209
 
210
         if Clobber_Ptr > Len then
211
            return Null_Address;
212
         end if;
213
 
214
         C := Get_Character (Get_String_Char (Str, Clobber_Ptr));
215
         exit when C /= ',' and then C /= ' ';
216
         Clobber_Ptr := Clobber_Ptr + 1;
217
      end loop;
218
 
219
      --  Acquire next register name
220
 
221
      Name_Len := 0;
222
      loop
223
         Add_Char_To_Name_Buffer (C);
224
         Clobber_Ptr := Clobber_Ptr + 1;
225
         exit when Clobber_Ptr > Len;
226
         C := Get_Character (Get_String_Char (Str, Clobber_Ptr));
227
         exit when C = ',' or else C = ' ';
228
      end loop;
229
 
230
      Name_Buffer (Name_Len + 1) := ASCII.NUL;
231
      return Name_Buffer'Address;
232
   end Clobber_Get_Next;
233
 
234
   -------------------
235
   -- Clobber_Setup --
236
   -------------------
237
 
238
   procedure Clobber_Setup (N : Node_Id) is
239
      Call : constant Node_Id := Expression (Expression (N));
240
      Clob : constant Node_Id := Next_Actual (
241
                                   Next_Actual (
242
                                     Next_Actual (
243
                                       First_Actual (Call))));
244
   begin
245
      if not Is_OK_Static_Expression (Clob) then
246
         Flag_Non_Static_Expr ("asm clobber argument is not static!", Clob);
247
         Clobber_Node := Empty;
248
      else
249
         Clobber_Node := Get_String_Node (Clob);
250
         Clobber_Ptr := 1;
251
      end if;
252
   end Clobber_Setup;
253
 
254
   ---------------------
255
   -- Expand_Asm_Call --
256
   ---------------------
257
 
258
   procedure Expand_Asm_Call (N : Node_Id) is
259
      Loc : constant Source_Ptr := Sloc (N);
260
 
261
      procedure Check_IO_Operand (N : Node_Id);
262
      --  Check for incorrect input or output operand
263
 
264
      ----------------------
265
      -- Check_IO_Operand --
266
      ----------------------
267
 
268
      procedure Check_IO_Operand (N : Node_Id) is
269
         Err : Node_Id := N;
270
 
271
      begin
272
         --  The only identifier allowed is No_xxput_Operands. Since we
273
         --  know the type is right, it is sufficient to see if the
274
         --  referenced entity is in a runtime routine.
275
 
276
         if Is_Entity_Name (N)
277
           and then
278
             Is_Predefined_File_Name (Unit_File_Name
279
                                       (Get_Source_Unit (Entity (N))))
280
         then
281
            return;
282
 
283
         --  An attribute reference is fine, again the analysis reasonably
284
         --  guarantees that the attribute must be subtype'Asm_??put.
285
 
286
         elsif Nkind (N) = N_Attribute_Reference then
287
            return;
288
 
289
         --  The only other allowed form is an array aggregate in which
290
         --  all the entries are positional and are attribute references.
291
 
292
         elsif Nkind (N) = N_Aggregate then
293
            if Present (Component_Associations (N)) then
294
               Err := First (Component_Associations (N));
295
 
296
            elsif Present (Expressions (N)) then
297
               Err := First (Expressions (N));
298
               while Present (Err) loop
299
                  exit when Nkind (Err) /= N_Attribute_Reference;
300
                  Next (Err);
301
               end loop;
302
 
303
               if No (Err) then
304
                  return;
305
               end if;
306
            end if;
307
         end if;
308
 
309
         --  If we fall through, Err is pointing to the bad node
310
 
311
         Error_Msg_N ("Asm operand has wrong form", Err);
312
      end Check_IO_Operand;
313
 
314
   --  Start of processing for Expand_Asm_Call
315
 
316
   begin
317
      --  Check that the input and output operands have the right
318
      --  form, as required by the documentation of the Asm feature:
319
 
320
      --  OUTPUT_OPERAND_LIST ::=
321
      --    No_Output_Operands
322
      --  | OUTPUT_OPERAND_ATTRIBUTE
323
      --  | (OUTPUT_OPERAND_ATTRIBUTE @{,OUTPUT_OPERAND_ATTRIBUTE@})
324
 
325
      --  OUTPUT_OPERAND_ATTRIBUTE ::=
326
      --    SUBTYPE_MARK'Asm_Output (static_string_EXPRESSION, NAME)
327
 
328
      --  INPUT_OPERAND_LIST ::=
329
      --    No_Input_Operands
330
      --  | INPUT_OPERAND_ATTRIBUTE
331
      --  | (INPUT_OPERAND_ATTRIBUTE @{,INPUT_OPERAND_ATTRIBUTE@})
332
 
333
      --  INPUT_OPERAND_ATTRIBUTE ::=
334
      --    SUBTYPE_MARK'Asm_Input (static_string_EXPRESSION, EXPRESSION)
335
 
336
      declare
337
         Arg_Output : constant Node_Id := Next_Actual (First_Actual (N));
338
         Arg_Input  : constant Node_Id := Next_Actual (Arg_Output);
339
      begin
340
         Check_IO_Operand (Arg_Output);
341
         Check_IO_Operand (Arg_Input);
342
      end;
343
 
344
      --  If we have the function call case, we are inside a code statement,
345
      --  and the tree is already in the necessary form for gigi.
346
 
347
      if Nkind (N) = N_Function_Call then
348
         null;
349
 
350
      --  For the procedure case, we convert the call into a code statement
351
 
352
      else
353
         pragma Assert (Nkind (N) = N_Procedure_Call_Statement);
354
 
355
         --  Note: strictly we should change the procedure call to a function
356
         --  call in the qualified expression, but since we are not going to
357
         --  reanalyze (see below), and the interface subprograms in this
358
         --  package don't care, we can leave it as a procedure call.
359
 
360
         Rewrite (N,
361
           Make_Code_Statement (Loc,
362
             Expression =>
363
               Make_Qualified_Expression (Loc,
364
                 Subtype_Mark => New_Occurrence_Of (RTE (RE_Asm_Insn), Loc),
365
                 Expression => Relocate_Node (N))));
366
 
367
         --  There is no need to reanalyze this node, it is completely analyzed
368
         --  already, at least sufficiently for the purposes of the abstract
369
         --  procedural interface defined in this package. Furthermore if we
370
         --  let it go through the normal analysis, that would include some
371
         --  inappropriate checks that apply only to explicit code statements
372
         --  in the source, and not to calls to intrinsics.
373
 
374
         Set_Analyzed (N);
375
         Check_Code_Statement (N);
376
      end if;
377
   end Expand_Asm_Call;
378
 
379
   ---------------------
380
   -- Get_String_Node --
381
   ---------------------
382
 
383
   function Get_String_Node (S : Node_Id) return Node_Id is
384
   begin
385
      if Nkind (S) = N_String_Literal then
386
         return S;
387
      else
388
         pragma Assert (Ekind (Entity (S)) = E_Constant);
389
         return Get_String_Node (Constant_Value (Entity (S)));
390
      end if;
391
   end Get_String_Node;
392
 
393
   ---------------------
394
   -- Is_Asm_Volatile --
395
   ---------------------
396
 
397
   function Is_Asm_Volatile (N : Node_Id) return Boolean is
398
      Call : constant Node_Id := Expression (Expression (N));
399
      Vol  : constant Node_Id :=
400
               Next_Actual (
401
                 Next_Actual (
402
                   Next_Actual (
403
                     Next_Actual (
404
                       First_Actual (Call)))));
405
   begin
406
      if not Is_OK_Static_Expression (Vol) then
407
         Flag_Non_Static_Expr ("asm volatile argument is not static!", Vol);
408
         return False;
409
      else
410
         return Is_True (Expr_Value (Vol));
411
      end if;
412
   end Is_Asm_Volatile;
413
 
414
   --------------------
415
   -- Next_Asm_Input --
416
   --------------------
417
 
418
   procedure Next_Asm_Input is
419
   begin
420
      Next_Asm_Operand (Current_Input_Operand);
421
   end Next_Asm_Input;
422
 
423
   ----------------------
424
   -- Next_Asm_Operand --
425
   ----------------------
426
 
427
   procedure Next_Asm_Operand (Operand_Var : in out Node_Id) is
428
   begin
429
      pragma Assert (Present (Operand_Var));
430
 
431
      if Nkind (Parent (Operand_Var)) = N_Aggregate then
432
         Operand_Var := Next (Operand_Var);
433
      else
434
         Operand_Var := Empty;
435
      end if;
436
   end Next_Asm_Operand;
437
 
438
   ---------------------
439
   -- Next_Asm_Output --
440
   ---------------------
441
 
442
   procedure Next_Asm_Output is
443
   begin
444
      Next_Asm_Operand (Current_Output_Operand);
445
   end Next_Asm_Output;
446
 
447
   ----------------------
448
   -- Setup_Asm_Inputs --
449
   ----------------------
450
 
451
   procedure Setup_Asm_Inputs (N : Node_Id) is
452
      Call : constant Node_Id := Expression (Expression (N));
453
   begin
454
      Setup_Asm_IO_Args
455
        (Next_Actual (Next_Actual (First_Actual (Call))),
456
         Current_Input_Operand);
457
   end Setup_Asm_Inputs;
458
 
459
   -----------------------
460
   -- Setup_Asm_IO_Args --
461
   -----------------------
462
 
463
   procedure Setup_Asm_IO_Args (Arg : Node_Id; Operand_Var : out Node_Id) is
464
   begin
465
      --  Case of single argument
466
 
467
      if Nkind (Arg) = N_Attribute_Reference then
468
         Operand_Var := Arg;
469
 
470
      --  Case of list of arguments
471
 
472
      elsif Nkind (Arg) = N_Aggregate then
473
         if Expressions (Arg) = No_List then
474
            Operand_Var := Empty;
475
         else
476
            Operand_Var := First (Expressions (Arg));
477
         end if;
478
 
479
      --  Otherwise must be default (no operands) case
480
 
481
      else
482
         Operand_Var := Empty;
483
      end if;
484
   end Setup_Asm_IO_Args;
485
 
486
   -----------------------
487
   -- Setup_Asm_Outputs --
488
   -----------------------
489
 
490
   procedure Setup_Asm_Outputs (N : Node_Id) is
491
      Call : constant Node_Id := Expression (Expression (N));
492
   begin
493
      Setup_Asm_IO_Args
494
        (Next_Actual (First_Actual (Call)),
495
         Current_Output_Operand);
496
   end Setup_Asm_Outputs;
497
 
498
end Exp_Code;

powered by: WebSVN 2.1.0

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