2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / ada / exp_code.adb
blob775a937dd81a7784619c9bc8cac285bb8f90915e
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-2003 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, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, 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 ------------------------------------------------------------------------------
27 with Atree; use Atree;
28 with Einfo; use Einfo;
29 with Errout; use Errout;
30 with Fname; use Fname;
31 with Lib; use Lib;
32 with Namet; use Namet;
33 with Nlists; use Nlists;
34 with Nmake; use Nmake;
35 with Opt; use Opt;
36 with Rtsfind; use Rtsfind;
37 with Sem_Eval; use Sem_Eval;
38 with Sem_Util; use Sem_Util;
39 with Sinfo; use Sinfo;
40 with Stringt; use Stringt;
41 with Tbuild; use Tbuild;
43 package body Exp_Code is
45 -----------------------
46 -- Local_Subprograms --
47 -----------------------
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.
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.
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.
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.
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.
73 ----------------------
74 -- Global Variables --
75 ----------------------
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.
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.
87 --------------------
88 -- Asm_Constraint --
89 --------------------
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;
97 --------------------------
98 -- Asm_Input_Constraint --
99 --------------------------
101 -- Note: error checking on Asm_Input attribute done in Sem_Attr
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;
108 ---------------------
109 -- Asm_Input_Value --
110 ---------------------
112 -- Note: error checking on Asm_Input attribute done in Sem_Attr
114 function Asm_Input_Value return Node_Id is
115 begin
116 return Asm_Operand (Current_Input_Operand);
117 end Asm_Input_Value;
119 -----------------
120 -- Asm_Operand --
121 -----------------
123 function Asm_Operand (Operand_Var : Node_Id) return Node_Id is
124 begin
125 if No (Operand_Var) then
126 return Empty;
127 else
128 return Next (First (Expressions (Operand_Var)));
129 end if;
130 end Asm_Operand;
132 ---------------------------
133 -- Asm_Output_Constraint --
134 ---------------------------
136 -- Note: error checking on Asm_Output attribute done in Sem_Attr
138 function Asm_Output_Constraint return Node_Id is
139 begin
140 return Asm_Constraint (Current_Output_Operand);
141 end Asm_Output_Constraint;
143 -------------------------
144 -- Asm_Output_Variable --
145 -------------------------
147 -- Note: error checking on Asm_Output attribute done in Sem_Attr
149 function Asm_Output_Variable return Node_Id is
150 begin
151 return Asm_Operand (Current_Output_Operand);
152 end Asm_Output_Variable;
154 ------------------
155 -- Asm_Template --
156 ------------------
158 function Asm_Template (N : Node_Id) return Node_Id is
159 Call : constant Node_Id := Expression (Expression (N));
160 Temp : constant Node_Id := First_Actual (Call);
162 begin
163 -- Require static expression for template. We also allow a string
164 -- literal (this is useful for Ada 83 mode where string expressions
165 -- are never static).
167 if Is_OK_Static_Expression (Temp)
168 or else (Ada_83 and then Nkind (Temp) = N_String_Literal)
169 then
170 return Get_String_Node (Temp);
172 else
173 Flag_Non_Static_Expr ("asm template argument is not static!", Temp);
174 return Empty;
175 end if;
176 end Asm_Template;
178 ----------------------
179 -- Clobber_Get_Next --
180 ----------------------
182 Clobber_Node : Node_Id;
183 -- String literal node for clobber string. Initialized by Clobber_Setup,
184 -- and not modified by Clobber_Get_Next. Empty if clobber string was in
185 -- error (resulting in no clobber arguments being returned).
187 Clobber_Ptr : Nat;
188 -- Pointer to current character of string. Initialized to 1 by the call
189 -- to Clobber_Setup, and then updated by Clobber_Get_Next.
191 function Clobber_Get_Next return Address is
192 Str : constant String_Id := Strval (Clobber_Node);
193 Len : constant Nat := String_Length (Str);
194 C : Character;
196 begin
197 if No (Clobber_Node) then
198 return Null_Address;
199 end if;
201 -- Skip spaces and commas before next register name
203 loop
204 -- Return null string if no more names
206 if Clobber_Ptr > Len then
207 return Null_Address;
208 end if;
210 C := Get_Character (Get_String_Char (Str, Clobber_Ptr));
211 exit when C /= ',' and then C /= ' ';
212 Clobber_Ptr := Clobber_Ptr + 1;
213 end loop;
215 -- Acquire next register name
217 Name_Len := 0;
218 loop
219 Name_Len := Name_Len + 1;
220 Name_Buffer (Name_Len) := C;
221 Clobber_Ptr := Clobber_Ptr + 1;
222 exit when Clobber_Ptr > Len;
223 C := Get_Character (Get_String_Char (Str, Clobber_Ptr));
224 exit when C = ',' or else C = ' ';
225 end loop;
227 Name_Buffer (Name_Len + 1) := ASCII.NUL;
228 return Name_Buffer'Address;
230 end Clobber_Get_Next;
232 -------------------
233 -- Clobber_Setup --
234 -------------------
236 procedure Clobber_Setup (N : Node_Id) is
237 Call : constant Node_Id := Expression (Expression (N));
238 Clob : constant Node_Id := Next_Actual (
239 Next_Actual (
240 Next_Actual (
241 First_Actual (Call))));
243 begin
244 if not Is_OK_Static_Expression (Clob) then
245 Flag_Non_Static_Expr ("asm clobber argument is not static!", Clob);
246 Clobber_Node := Empty;
248 else
249 Clobber_Node := Get_String_Node (Clob);
250 Clobber_Ptr := 1;
251 end if;
252 end Clobber_Setup;
254 ---------------------
255 -- Expand_Asm_Call --
256 ---------------------
258 procedure Expand_Asm_Call (N : Node_Id) is
259 Loc : constant Source_Ptr := Sloc (N);
261 procedure Check_IO_Operand (N : Node_Id);
262 -- Check for incorrect input or output operand
264 procedure Check_IO_Operand (N : Node_Id) is
265 Err : Node_Id := N;
267 begin
268 -- The only identifier allows is No_xxput_Operands. Since we
269 -- know the type is right, it is sufficient to see if the
270 -- referenced entity is in a runtime routine.
272 if Is_Entity_Name (N)
273 and then
274 Is_Predefined_File_Name (Unit_File_Name
275 (Get_Source_Unit (Entity (N))))
276 then
277 return;
279 -- An attribute reference is fine, again the analysis reasonably
280 -- guarantees that the attribute must be subtype'Asm_??put.
282 elsif Nkind (N) = N_Attribute_Reference then
283 return;
285 -- The only other allowed form is an array aggregate in which
286 -- all the entries are positional and are attribute references.
288 elsif Nkind (N) = N_Aggregate then
289 if Present (Component_Associations (N)) then
290 Err := First (Component_Associations (N));
292 elsif Present (Expressions (N)) then
293 Err := First (Expressions (N));
294 while Present (Err) loop
295 exit when Nkind (Err) /= N_Attribute_Reference;
296 Next (Err);
297 end loop;
299 if No (Err) then
300 return;
301 end if;
302 end if;
303 end if;
305 -- If we fall through, Err is pointing to the bad node
307 Error_Msg_N ("Asm operand has wrong form", Err);
308 end Check_IO_Operand;
310 -- Start of processing for Expand_Asm_Call
312 begin
313 -- Check that the input and output operands have the right
314 -- form, as required by the documentation of the Asm feature:
316 -- OUTPUT_OPERAND_LIST ::=
317 -- No_Output_Operands
318 -- | OUTPUT_OPERAND_ATTRIBUTE
319 -- | (OUTPUT_OPERAND_ATTRIBUTE @{,OUTPUT_OPERAND_ATTRIBUTE@})
321 -- OUTPUT_OPERAND_ATTRIBUTE ::=
322 -- SUBTYPE_MARK'Asm_Output (static_string_EXPRESSION, NAME)
324 -- INPUT_OPERAND_LIST ::=
325 -- No_Input_Operands
326 -- | INPUT_OPERAND_ATTRIBUTE
327 -- | (INPUT_OPERAND_ATTRIBUTE @{,INPUT_OPERAND_ATTRIBUTE@})
329 -- INPUT_OPERAND_ATTRIBUTE ::=
330 -- SUBTYPE_MARK'Asm_Input (static_string_EXPRESSION, EXPRESSION)
332 declare
333 Arg_Output : constant Node_Id := Next_Actual (First_Actual (N));
334 Arg_Input : constant Node_Id := Next_Actual (Arg_Output);
336 begin
337 Check_IO_Operand (Arg_Output);
338 Check_IO_Operand (Arg_Input);
339 end;
341 -- If we have the function call case, we are inside a code statement,
342 -- and the tree is already in the necessary form for gigi.
344 if Nkind (N) = N_Function_Call then
345 null;
347 -- For the procedure case, we convert the call into a code statement
349 else
350 pragma Assert (Nkind (N) = N_Procedure_Call_Statement);
352 -- Note: strictly we should change the procedure call to a function
353 -- call in the qualified expression, but since we are not going to
354 -- reanalyze (see below), and the interface subprograms in this
355 -- package don't care, we can leave it as a procedure call.
357 Rewrite (N,
358 Make_Code_Statement (Loc,
359 Expression =>
360 Make_Qualified_Expression (Loc,
361 Subtype_Mark => New_Occurrence_Of (RTE (RE_Asm_Insn), Loc),
362 Expression => Relocate_Node (N))));
364 -- There is no need to reanalyze this node, it is completely analyzed
365 -- already, at least sufficiently for the purposes of the abstract
366 -- procedural interface defined in this package.
368 Set_Analyzed (N);
369 end if;
370 end Expand_Asm_Call;
372 ---------------------
373 -- Get_String_Node --
374 ---------------------
376 function Get_String_Node (S : Node_Id) return Node_Id is
377 begin
378 if Nkind (S) = N_String_Literal then
379 return S;
381 else
382 pragma Assert (Ekind (Entity (S)) = E_Constant);
383 return Get_String_Node (Constant_Value (Entity (S)));
384 end if;
385 end Get_String_Node;
387 ---------------------
388 -- Is_Asm_Volatile --
389 ---------------------
391 function Is_Asm_Volatile (N : Node_Id) return Boolean is
392 Call : constant Node_Id := Expression (Expression (N));
393 Vol : constant Node_Id :=
394 Next_Actual (
395 Next_Actual (
396 Next_Actual (
397 Next_Actual (
398 First_Actual (Call)))));
400 begin
401 if not Is_OK_Static_Expression (Vol) then
402 Flag_Non_Static_Expr ("asm volatile argument is not static!", Vol);
403 return False;
405 else
406 return Is_True (Expr_Value (Vol));
407 end if;
408 end Is_Asm_Volatile;
410 --------------------
411 -- Next_Asm_Input --
412 --------------------
414 procedure Next_Asm_Input is
415 begin
416 Next_Asm_Operand (Current_Input_Operand);
417 end Next_Asm_Input;
419 ----------------------
420 -- Next_Asm_Operand --
421 ----------------------
423 procedure Next_Asm_Operand (Operand_Var : in out Node_Id) is
424 begin
425 pragma Assert (Present (Operand_Var));
427 if Nkind (Parent (Operand_Var)) = N_Aggregate then
428 Operand_Var := Next (Operand_Var);
430 else
431 Operand_Var := Empty;
432 end if;
433 end Next_Asm_Operand;
435 ---------------------
436 -- Next_Asm_Output --
437 ---------------------
439 procedure Next_Asm_Output is
440 begin
441 Next_Asm_Operand (Current_Output_Operand);
442 end Next_Asm_Output;
444 ----------------------
445 -- Setup_Asm_Inputs --
446 ----------------------
448 procedure Setup_Asm_Inputs (N : Node_Id) is
449 Call : constant Node_Id := Expression (Expression (N));
451 begin
452 Setup_Asm_IO_Args
453 (Next_Actual (Next_Actual (First_Actual (Call))),
454 Current_Input_Operand);
455 end Setup_Asm_Inputs;
457 -----------------------
458 -- Setup_Asm_IO_Args --
459 -----------------------
461 procedure Setup_Asm_IO_Args (Arg : Node_Id; Operand_Var : out Node_Id) is
462 begin
463 -- Case of single argument
465 if Nkind (Arg) = N_Attribute_Reference then
466 Operand_Var := Arg;
468 -- Case of list of arguments
470 elsif Nkind (Arg) = N_Aggregate then
471 if Expressions (Arg) = No_List then
472 Operand_Var := Empty;
473 else
474 Operand_Var := First (Expressions (Arg));
475 end if;
477 -- Otherwise must be default (no operands) case
479 else
480 Operand_Var := Empty;
481 end if;
482 end Setup_Asm_IO_Args;
484 -----------------------
485 -- Setup_Asm_Outputs --
486 -----------------------
488 procedure Setup_Asm_Outputs (N : Node_Id) is
489 Call : constant Node_Id := Expression (Expression (N));
491 begin
492 Setup_Asm_IO_Args
493 (Next_Actual (First_Actual (Call)),
494 Current_Output_Operand);
495 end Setup_Asm_Outputs;
497 end Exp_Code;