OSDN Git Service

PR preprocessor/30805:
[pf3gnuchains/gcc-fork.git] / gcc / ada / exp_code.adb
1 ------------------------------------------------------------------------------
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-2007, 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_Eval; use Sem_Eval;
37 with Sem_Util; use Sem_Util;
38 with Sem_Warn; use Sem_Warn;
39 with Sinfo;    use Sinfo;
40 with Stringt;  use Stringt;
41 with Tbuild;   use Tbuild;
42
43 package body Exp_Code is
44
45    -----------------------
46    -- Local_Subprograms --
47    -----------------------
48
49    function Asm_Constraint (Operand_Var : Node_Id) return Node_Id;
50    --  Common processing for Asm_Input_Constraint and Asm_Output_Constraint.
51    --  Obtains the constraint argument from the global operand variable
52    --  Operand_Var, which must be non-Empty.
53
54    function Asm_Operand (Operand_Var : Node_Id) return Node_Id;
55    --  Common processing for Asm_Input_Value and Asm_Output_Variable. Obtains
56    --  the value/variable argument from Operand_Var, the global operand
57    --  variable. Returns Empty if no operand available.
58
59    function Get_String_Node (S : Node_Id) return Node_Id;
60    --  Given S, a static expression node of type String, returns the
61    --  string literal node. This is needed to deal with the use of constants
62    --  for these expressions, which is perfectly permissible.
63
64    procedure Next_Asm_Operand (Operand_Var : in out Node_Id);
65    --  Common processing for Next_Asm_Input and Next_Asm_Output, updates
66    --  the value of the global operand variable Operand_Var appropriately.
67
68    procedure Setup_Asm_IO_Args (Arg : Node_Id; Operand_Var : out Node_Id);
69    --  Common processing for Setup_Asm_Inputs and Setup_Asm_Outputs. Arg
70    --  is the actual parameter from the call, and Operand_Var is the global
71    --  operand variable to be initialized to the first operand.
72
73    ----------------------
74    -- Global Variables --
75    ----------------------
76
77    Current_Input_Operand : Node_Id := Empty;
78    --  Points to current Asm_Input_Operand attribute reference. Initialized
79    --  by Setup_Asm_Inputs, updated by Next_Asm_Input, and referenced by
80    --  Asm_Input_Constraint and Asm_Input_Value.
81
82    Current_Output_Operand : Node_Id := Empty;
83    --  Points to current Asm_Output_Operand attribute reference. Initialized
84    --  by Setup_Asm_Outputs, updated by Next_Asm_Output, and referenced by
85    --  Asm_Output_Constraint and Asm_Output_Variable.
86
87    --------------------
88    -- Asm_Constraint --
89    --------------------
90
91    function Asm_Constraint (Operand_Var : Node_Id) return Node_Id is
92    begin
93       pragma Assert (Present (Operand_Var));
94       return Get_String_Node (First (Expressions (Operand_Var)));
95    end Asm_Constraint;
96
97    --------------------------
98    -- Asm_Input_Constraint --
99    --------------------------
100
101    --  Note: error checking on Asm_Input attribute done in Sem_Attr
102
103    function Asm_Input_Constraint return Node_Id is
104    begin
105       return Get_String_Node (Asm_Constraint (Current_Input_Operand));
106    end Asm_Input_Constraint;
107
108    ---------------------
109    -- Asm_Input_Value --
110    ---------------------
111
112    --  Note: error checking on Asm_Input attribute done in Sem_Attr
113
114    function Asm_Input_Value return Node_Id is
115    begin
116       return Asm_Operand (Current_Input_Operand);
117    end Asm_Input_Value;
118
119    -----------------
120    -- Asm_Operand --
121    -----------------
122
123    function Asm_Operand (Operand_Var : Node_Id) return Node_Id is
124    begin
125       if No (Operand_Var) then
126          return Empty;
127       elsif Error_Posted (Operand_Var) then
128          return Error;
129       else
130          return Next (First (Expressions (Operand_Var)));
131       end if;
132    end Asm_Operand;
133
134    ---------------------------
135    -- Asm_Output_Constraint --
136    ---------------------------
137
138    --  Note: error checking on Asm_Output attribute done in Sem_Attr
139
140    function Asm_Output_Constraint return Node_Id is
141    begin
142       return Asm_Constraint (Current_Output_Operand);
143    end Asm_Output_Constraint;
144
145    -------------------------
146    -- Asm_Output_Variable --
147    -------------------------
148
149    --  Note: error checking on Asm_Output attribute done in Sem_Attr
150
151    function Asm_Output_Variable return Node_Id is
152    begin
153       return Asm_Operand (Current_Output_Operand);
154    end Asm_Output_Variable;
155
156    ------------------
157    -- Asm_Template --
158    ------------------
159
160    function Asm_Template (N : Node_Id) return Node_Id is
161       Call : constant Node_Id := Expression (Expression (N));
162       Temp : constant Node_Id := First_Actual (Call);
163
164    begin
165       --  Require static expression for template. We also allow a string
166       --  literal (this is useful for Ada 83 mode where string expressions
167       --  are never static).
168
169       if Is_OK_Static_Expression (Temp)
170         or else (Ada_Version = Ada_83
171                   and then Nkind (Temp) = N_String_Literal)
172       then
173          return Get_String_Node (Temp);
174
175       else
176          Flag_Non_Static_Expr ("asm template argument is not static!", Temp);
177          return Empty;
178       end if;
179    end Asm_Template;
180
181    ----------------------
182    -- Clobber_Get_Next --
183    ----------------------
184
185    Clobber_Node : Node_Id;
186    --  String literal node for clobber string. Initialized by Clobber_Setup,
187    --  and not modified by Clobber_Get_Next. Empty if clobber string was in
188    --  error (resulting in no clobber arguments being returned).
189
190    Clobber_Ptr : Nat;
191    --  Pointer to current character of string. Initialized to 1 by the call
192    --  to Clobber_Setup, and then updated by Clobber_Get_Next.
193
194    function Clobber_Get_Next return Address is
195       Str : constant String_Id := Strval (Clobber_Node);
196       Len : constant Nat       := String_Length (Str);
197       C   : Character;
198
199    begin
200       if No (Clobber_Node) then
201          return Null_Address;
202       end if;
203
204       --  Skip spaces and commas before next register name
205
206       loop
207          --  Return null string if no more names
208
209          if Clobber_Ptr > Len then
210             return Null_Address;
211          end if;
212
213          C := Get_Character (Get_String_Char (Str, Clobber_Ptr));
214          exit when C /= ',' and then C /= ' ';
215          Clobber_Ptr := Clobber_Ptr + 1;
216       end loop;
217
218       --  Acquire next register name
219
220       Name_Len := 0;
221       loop
222          Name_Len := Name_Len + 1;
223          Name_Buffer (Name_Len) := 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;