2002-04-02 David S. Miller <davem@redhat.com>
[official-gcc.git] / gcc / ada / exp_code.adb
blob138e560495cb8d264aecec49365d8711a729d2d6
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ C O D E --
6 -- --
7 -- B o d y --
8 -- --
9 -- --
10 -- Copyright (C) 1996-2001 Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
22 -- --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
25 -- --
26 ------------------------------------------------------------------------------
28 with Atree; use Atree;
29 with Einfo; use Einfo;
30 with Errout; use Errout;
31 with Fname; use Fname;
32 with Lib; use Lib;
33 with Namet; use Namet;
34 with Nlists; use Nlists;
35 with Nmake; use Nmake;
36 with Opt; use Opt;
37 with Rtsfind; use Rtsfind;
38 with Sem_Eval; use Sem_Eval;
39 with Sem_Util; use Sem_Util;
40 with Sinfo; use Sinfo;
41 with Stringt; use Stringt;
42 with Tbuild; use Tbuild;
44 package body Exp_Code is
46 -----------------------
47 -- Local_Subprograms --
48 -----------------------
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.
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.
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.
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.
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.
74 ----------------------
75 -- Global Variables --
76 ----------------------
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.
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.
88 --------------------
89 -- Asm_Constraint --
90 --------------------
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;
98 --------------------------
99 -- Asm_Input_Constraint --
100 --------------------------
102 -- Note: error checking on Asm_Input attribute done in Sem_Attr
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;
109 ---------------------
110 -- Asm_Input_Value --
111 ---------------------
113 -- Note: error checking on Asm_Input attribute done in Sem_Attr
115 function Asm_Input_Value return Node_Id is
116 begin
117 return Asm_Operand (Current_Input_Operand);
118 end Asm_Input_Value;
120 -----------------
121 -- Asm_Operand --
122 -----------------
124 function Asm_Operand (Operand_Var : Node_Id) return Node_Id is
125 begin
126 if No (Operand_Var) then
127 return Empty;
128 else
129 return Next (First (Expressions (Operand_Var)));
130 end if;
131 end Asm_Operand;
133 ---------------------------
134 -- Asm_Output_Constraint --
135 ---------------------------
137 -- Note: error checking on Asm_Output attribute done in Sem_Attr
139 function Asm_Output_Constraint return Node_Id is
140 begin
141 return Asm_Constraint (Current_Output_Operand);
142 end Asm_Output_Constraint;
144 -------------------------
145 -- Asm_Output_Variable --
146 -------------------------
148 -- Note: error checking on Asm_Output attribute done in Sem_Attr
150 function Asm_Output_Variable return Node_Id is
151 begin
152 return Asm_Operand (Current_Output_Operand);
153 end Asm_Output_Variable;
155 ------------------
156 -- Asm_Template --
157 ------------------
159 function Asm_Template (N : Node_Id) return Node_Id is
160 Call : constant Node_Id := Expression (Expression (N));
161 Temp : constant Node_Id := First_Actual (Call);
163 begin
164 -- Require static expression for template. We also allow a string
165 -- literal (this is useful for Ada 83 mode where string expressions
166 -- are never static).
168 if Is_OK_Static_Expression (Temp)
169 or else (Ada_83 and then Nkind (Temp) = N_String_Literal)
170 then
171 return Get_String_Node (Temp);
173 else
174 Error_Msg_N ("asm template argument is not static", Temp);
175 return Empty;
176 end if;
177 end Asm_Template;
179 ----------------------
180 -- Clobber_Get_Next --
181 ----------------------
183 Clobber_Node : Node_Id;
184 -- String literal node for clobber string. Initialized by Clobber_Setup,
185 -- and not modified by Clobber_Get_Next. Empty if clobber string was in
186 -- error (resulting in no clobber arguments being returned).
188 Clobber_Ptr : Nat;
189 -- Pointer to current character of string. Initialized to 1 by the call
190 -- to Clobber_Setup, and then updated by Clobber_Get_Next.
192 function Clobber_Get_Next return Address is
193 Str : constant String_Id := Strval (Clobber_Node);
194 Len : constant Nat := String_Length (Str);
195 C : Character;
197 begin
198 if No (Clobber_Node) then
199 return Null_Address;
200 end if;
202 -- Skip spaces and commas before next register name
204 loop
205 -- Return null string if no more names
207 if Clobber_Ptr > Len then
208 return Null_Address;
209 end if;
211 C := Get_Character (Get_String_Char (Str, Clobber_Ptr));
212 exit when C /= ',' and then C /= ' ';
213 Clobber_Ptr := Clobber_Ptr + 1;
214 end loop;
216 -- Acquire next register name
218 Name_Len := 0;
219 loop
220 Name_Len := Name_Len + 1;
221 Name_Buffer (Name_Len) := C;
222 Clobber_Ptr := Clobber_Ptr + 1;
223 exit when Clobber_Ptr > Len;
224 C := Get_Character (Get_String_Char (Str, Clobber_Ptr));
225 exit when C = ',' or else C = ' ';
226 end loop;
228 Name_Buffer (Name_Len + 1) := ASCII.NUL;
229 return Name_Buffer'Address;
231 end Clobber_Get_Next;
233 -------------------
234 -- Clobber_Setup --
235 -------------------
237 procedure Clobber_Setup (N : Node_Id) is
238 Call : constant Node_Id := Expression (Expression (N));
239 Clob : constant Node_Id := Next_Actual (
240 Next_Actual (
241 Next_Actual (
242 First_Actual (Call))));
244 begin
245 if not Is_OK_Static_Expression (Clob) then
246 Error_Msg_N ("asm clobber argument is not static", Clob);
247 Clobber_Node := Empty;
249 else
250 Clobber_Node := Get_String_Node (Clob);
251 Clobber_Ptr := 1;
252 end if;
253 end Clobber_Setup;
255 ---------------------
256 -- Expand_Asm_Call --
257 ---------------------
259 procedure Expand_Asm_Call (N : Node_Id) is
260 Loc : constant Source_Ptr := Sloc (N);
262 procedure Check_IO_Operand (N : Node_Id);
263 -- Check for incorrect input or output operand
265 procedure Check_IO_Operand (N : Node_Id) is
266 Err : Node_Id := N;
268 begin
269 -- The only identifier allows is No_xxput_Operands. Since we
270 -- know the type is right, it is sufficient to see if the
271 -- referenced entity is in a runtime routine.
273 if Nkind (N) = N_Identifier
274 and then
275 Is_Predefined_File_Name (Unit_File_Name
276 (Get_Source_Unit (Entity (N))))
277 then
278 return;
280 -- An attribute reference is fine, again the analysis reasonably
281 -- guarantees that the attribute must be subtype'Asm_??put.
283 elsif Nkind (N) = N_Attribute_Reference then
284 return;
286 -- The only other allowed form is an array aggregate in which
287 -- all the entries are positional and are attribute references.
289 elsif Nkind (N) = N_Aggregate then
290 if Present (Component_Associations (N)) then
291 Err := First (Component_Associations (N));
293 elsif Present (Expressions (N)) then
294 Err := First (Expressions (N));
295 while Present (Err) loop
296 exit when Nkind (Err) /= N_Attribute_Reference;
297 Next (Err);
298 end loop;
300 if No (Err) then
301 return;
302 end if;
303 end if;
304 end if;
306 -- If we fall through, Err is pointing to the bad node
308 Error_Msg_N ("Asm operand has wrong form", Err);
309 end Check_IO_Operand;
311 -- Start of processing for Expand_Asm_Call
313 begin
314 -- Check that the input and output operands have the right
315 -- form, as required by the documentation of the Asm feature:
317 -- OUTPUT_OPERAND_LIST ::=
318 -- No_Output_Operands
319 -- | OUTPUT_OPERAND_ATTRIBUTE
320 -- | (OUTPUT_OPERAND_ATTRIBUTE @{,OUTPUT_OPERAND_ATTRIBUTE@})
322 -- OUTPUT_OPERAND_ATTRIBUTE ::=
323 -- SUBTYPE_MARK'Asm_Output (static_string_EXPRESSION, NAME)
325 -- INPUT_OPERAND_LIST ::=
326 -- No_Input_Operands
327 -- | INPUT_OPERAND_ATTRIBUTE
328 -- | (INPUT_OPERAND_ATTRIBUTE @{,INPUT_OPERAND_ATTRIBUTE@})
330 -- INPUT_OPERAND_ATTRIBUTE ::=
331 -- SUBTYPE_MARK'Asm_Input (static_string_EXPRESSION, EXPRESSION)
333 declare
334 Arg_Output : constant Node_Id := Next_Actual (First_Actual (N));
335 Arg_Input : constant Node_Id := Next_Actual (Arg_Output);
337 begin
338 Check_IO_Operand (Arg_Output);
339 Check_IO_Operand (Arg_Input);
340 end;
342 -- If we have the function call case, we are inside a code statement,
343 -- and the tree is already in the necessary form for gigi.
345 if Nkind (N) = N_Function_Call then
346 null;
348 -- For the procedure case, we convert the call into a code statement
350 else
351 pragma Assert (Nkind (N) = N_Procedure_Call_Statement);
353 -- Note: strictly we should change the procedure call to a function
354 -- call in the qualified expression, but since we are not going to
355 -- reanalyze (see below), and the interface subprograms in this
356 -- package don't care, we can leave it as a procedure call.
358 Rewrite (N,
359 Make_Code_Statement (Loc,
360 Expression =>
361 Make_Qualified_Expression (Loc,
362 Subtype_Mark => New_Occurrence_Of (RTE (RE_Asm_Insn), Loc),
363 Expression => Relocate_Node (N))));
365 -- There is no need to reanalyze this node, it is completely analyzed
366 -- already, at least sufficiently for the purposes of the abstract
367 -- procedural interface defined in this package.
369 Set_Analyzed (N);
370 end if;
371 end Expand_Asm_Call;
373 ---------------------
374 -- Get_String_Node --
375 ---------------------
377 function Get_String_Node (S : Node_Id) return Node_Id is
378 begin
379 if Nkind (S) = N_String_Literal then
380 return S;
382 else
383 pragma Assert (Ekind (Entity (S)) = E_Constant);
384 return Get_String_Node (Constant_Value (Entity (S)));
385 end if;
386 end Get_String_Node;
388 ---------------------
389 -- Is_Asm_Volatile --
390 ---------------------
392 function Is_Asm_Volatile (N : Node_Id) return Boolean is
393 Call : constant Node_Id := Expression (Expression (N));
394 Vol : constant Node_Id :=
395 Next_Actual (
396 Next_Actual (
397 Next_Actual (
398 Next_Actual (
399 First_Actual (Call)))));
401 begin
402 if not Is_OK_Static_Expression (Vol) then
403 Error_Msg_N ("asm volatile argument is not static", Vol);
404 return False;
406 else
407 return Is_True (Expr_Value (Vol));
408 end if;
409 end Is_Asm_Volatile;
411 --------------------
412 -- Next_Asm_Input --
413 --------------------
415 procedure Next_Asm_Input is
416 begin
417 Next_Asm_Operand (Current_Input_Operand);
418 end Next_Asm_Input;
420 ----------------------
421 -- Next_Asm_Operand --
422 ----------------------
424 procedure Next_Asm_Operand (Operand_Var : in out Node_Id) is
425 begin
426 pragma Assert (Present (Operand_Var));
428 if Nkind (Parent (Operand_Var)) = N_Aggregate then
429 Operand_Var := Next (Operand_Var);
431 else
432 Operand_Var := Empty;
433 end if;
434 end Next_Asm_Operand;
436 ---------------------
437 -- Next_Asm_Output --
438 ---------------------
440 procedure Next_Asm_Output is
441 begin
442 Next_Asm_Operand (Current_Output_Operand);
443 end Next_Asm_Output;
445 ----------------------
446 -- Setup_Asm_Inputs --
447 ----------------------
449 procedure Setup_Asm_Inputs (N : Node_Id) is
450 Call : constant Node_Id := Expression (Expression (N));
452 begin
453 Setup_Asm_IO_Args
454 (Next_Actual (Next_Actual (First_Actual (Call))),
455 Current_Input_Operand);
456 end Setup_Asm_Inputs;
458 -----------------------
459 -- Setup_Asm_IO_Args --
460 -----------------------
462 procedure Setup_Asm_IO_Args (Arg : Node_Id; Operand_Var : out Node_Id) is
463 begin
464 -- Case of single argument
466 if Nkind (Arg) = N_Attribute_Reference then
467 Operand_Var := Arg;
469 -- Case of list of arguments
471 elsif Nkind (Arg) = N_Aggregate then
472 if Expressions (Arg) = No_List then
473 Operand_Var := Empty;
474 else
475 Operand_Var := First (Expressions (Arg));
476 end if;
478 -- Otherwise must be default (no operands) case
480 else
481 Operand_Var := Empty;
482 end if;
483 end Setup_Asm_IO_Args;
485 -----------------------
486 -- Setup_Asm_Outputs --
487 -----------------------
489 procedure Setup_Asm_Outputs (N : Node_Id) is
490 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;
498 end Exp_Code;