1 | /* Output variables, constants and external declarations, for GNU compiler. |
---|
2 | Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc. |
---|
3 | |
---|
4 | This file is part of GNU CC. |
---|
5 | |
---|
6 | GNU CC is free software; you can redistribute it and/or modify |
---|
7 | it under the terms of the GNU General Public License as published by |
---|
8 | the Free Software Foundation; either version 2, or (at your option) |
---|
9 | any later version. |
---|
10 | |
---|
11 | GNU CC is distributed in the hope that it will be useful, |
---|
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | GNU General Public License for more details. |
---|
15 | |
---|
16 | You should have received a copy of the GNU General Public License |
---|
17 | along with GNU CC; see the file COPYING. If not, write to |
---|
18 | the Free Software Foundation, 59 Temple Place - Suite 330, |
---|
19 | Boston, MA 02111-1307, USA. */ |
---|
20 | |
---|
21 | |
---|
22 | /* This file handles generation of all the assembler code |
---|
23 | *except* the instructions of a function. |
---|
24 | This includes declarations of variables and their initial values. |
---|
25 | |
---|
26 | We also output the assembler code for constants stored in memory |
---|
27 | and are responsible for combining constants with the same value. */ |
---|
28 | |
---|
29 | #include <stdio.h> |
---|
30 | #include <setjmp.h> |
---|
31 | /* #include <stab.h> */ |
---|
32 | #include "config.h" |
---|
33 | #include "rtl.h" |
---|
34 | #include "tree.h" |
---|
35 | #include "flags.h" |
---|
36 | #include "function.h" |
---|
37 | #include "expr.h" |
---|
38 | #include "output.h" |
---|
39 | #include "hard-reg-set.h" |
---|
40 | #include "regs.h" |
---|
41 | #include "defaults.h" |
---|
42 | #include "real.h" |
---|
43 | #include "bytecode.h" |
---|
44 | |
---|
45 | #include "obstack.h" |
---|
46 | #include "c-pragma.h" |
---|
47 | |
---|
48 | #ifdef XCOFF_DEBUGGING_INFO |
---|
49 | #include "xcoffout.h" |
---|
50 | #endif |
---|
51 | |
---|
52 | #include <ctype.h> |
---|
53 | |
---|
54 | #ifndef ASM_STABS_OP |
---|
55 | #define ASM_STABS_OP ".stabs" |
---|
56 | #endif |
---|
57 | |
---|
58 | /* This macro gets just the user-specified name |
---|
59 | out of the string in a SYMBOL_REF. On most machines, |
---|
60 | we discard the * if any and that's all. */ |
---|
61 | #ifndef STRIP_NAME_ENCODING |
---|
62 | #define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \ |
---|
63 | (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*')) |
---|
64 | #endif |
---|
65 | |
---|
66 | /* File in which assembler code is being written. */ |
---|
67 | |
---|
68 | extern FILE *asm_out_file; |
---|
69 | |
---|
70 | /* The (assembler) name of the first globally-visible object output. */ |
---|
71 | char *first_global_object_name; |
---|
72 | |
---|
73 | extern struct obstack *current_obstack; |
---|
74 | extern struct obstack *saveable_obstack; |
---|
75 | extern struct obstack *rtl_obstack; |
---|
76 | extern struct obstack permanent_obstack; |
---|
77 | #define obstack_chunk_alloc xmalloc |
---|
78 | |
---|
79 | /* Number for making the label on the next |
---|
80 | constant that is stored in memory. */ |
---|
81 | |
---|
82 | int const_labelno; |
---|
83 | |
---|
84 | /* Number for making the label on the next |
---|
85 | static variable internal to a function. */ |
---|
86 | |
---|
87 | int var_labelno; |
---|
88 | |
---|
89 | /* Carry information from ASM_DECLARE_OBJECT_NAME |
---|
90 | to ASM_FINISH_DECLARE_OBJECT. */ |
---|
91 | |
---|
92 | int size_directive_output; |
---|
93 | |
---|
94 | /* The last decl for which assemble_variable was called, |
---|
95 | if it did ASM_DECLARE_OBJECT_NAME. |
---|
96 | If the last call to assemble_variable didn't do that, |
---|
97 | this holds 0. */ |
---|
98 | |
---|
99 | tree last_assemble_variable_decl; |
---|
100 | |
---|
101 | |
---|
102 | #ifdef HANDLE_PRAGMA_WEAK |
---|
103 | /* Any weak symbol declarations waiting to be emitted. */ |
---|
104 | |
---|
105 | struct weak_syms |
---|
106 | { |
---|
107 | struct weak_syms *next; |
---|
108 | char *name; |
---|
109 | char *value; |
---|
110 | }; |
---|
111 | |
---|
112 | static struct weak_syms *weak_decls; |
---|
113 | #endif |
---|
114 | |
---|
115 | /* Nonzero if at least one function definition has been seen. */ |
---|
116 | |
---|
117 | static int function_defined; |
---|
118 | |
---|
119 | struct addr_const; |
---|
120 | struct constant_descriptor; |
---|
121 | struct rtx_const; |
---|
122 | struct pool_constant; |
---|
123 | |
---|
124 | static void bc_make_decl_rtl PROTO((tree, char *, int)); |
---|
125 | static char *strip_reg_name PROTO((char *)); |
---|
126 | static void bc_output_ascii PROTO((FILE *, char *, int)); |
---|
127 | static int contains_pointers_p PROTO((tree)); |
---|
128 | static void decode_addr_const PROTO((tree, struct addr_const *)); |
---|
129 | static int const_hash PROTO((tree)); |
---|
130 | static int compare_constant PROTO((tree, |
---|
131 | struct constant_descriptor *)); |
---|
132 | static char *compare_constant_1 PROTO((tree, char *)); |
---|
133 | static struct constant_descriptor *record_constant PROTO((tree)); |
---|
134 | static void record_constant_1 PROTO((tree)); |
---|
135 | static tree copy_constant PROTO((tree)); |
---|
136 | static void output_constant_def_contents PROTO((tree, int, int)); |
---|
137 | static void decode_rtx_const PROTO((enum machine_mode, rtx, |
---|
138 | struct rtx_const *)); |
---|
139 | static int const_hash_rtx PROTO((enum machine_mode, rtx)); |
---|
140 | static int compare_constant_rtx PROTO((enum machine_mode, rtx, |
---|
141 | struct constant_descriptor *)); |
---|
142 | static struct constant_descriptor *record_constant_rtx PROTO((enum machine_mode, |
---|
143 | rtx)); |
---|
144 | static struct pool_constant *find_pool_constant PROTO((rtx)); |
---|
145 | static int output_addressed_constants PROTO((tree)); |
---|
146 | static void bc_assemble_integer PROTO((tree, int)); |
---|
147 | static void output_constructor PROTO((tree, int)); |
---|
148 | |
---|
149 | #ifdef EXTRA_SECTIONS |
---|
150 | static enum in_section {no_section, in_text, in_data, in_named, EXTRA_SECTIONS} in_section |
---|
151 | = no_section; |
---|
152 | #else |
---|
153 | static enum in_section {no_section, in_text, in_data, in_named} in_section |
---|
154 | = no_section; |
---|
155 | #endif |
---|
156 | |
---|
157 | /* Return a non-zero value if DECL has a section attribute. */ |
---|
158 | #define IN_NAMED_SECTION(DECL) \ |
---|
159 | ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \ |
---|
160 | && DECL_SECTION_NAME (DECL) != NULL_TREE) |
---|
161 | |
---|
162 | /* Text of section name when in_section == in_named. */ |
---|
163 | static char *in_named_name; |
---|
164 | |
---|
165 | /* Define functions like text_section for any extra sections. */ |
---|
166 | #ifdef EXTRA_SECTION_FUNCTIONS |
---|
167 | EXTRA_SECTION_FUNCTIONS |
---|
168 | #endif |
---|
169 | |
---|
170 | /* Tell assembler to switch to text section. */ |
---|
171 | |
---|
172 | void |
---|
173 | text_section () |
---|
174 | { |
---|
175 | if (in_section != in_text) |
---|
176 | { |
---|
177 | if (output_bytecode) |
---|
178 | bc_text (); |
---|
179 | else |
---|
180 | fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP); |
---|
181 | |
---|
182 | in_section = in_text; |
---|
183 | } |
---|
184 | } |
---|
185 | |
---|
186 | /* Tell assembler to switch to data section. */ |
---|
187 | |
---|
188 | void |
---|
189 | data_section () |
---|
190 | { |
---|
191 | if (in_section != in_data) |
---|
192 | { |
---|
193 | if (output_bytecode) |
---|
194 | bc_data (); |
---|
195 | else |
---|
196 | { |
---|
197 | if (flag_shared_data) |
---|
198 | { |
---|
199 | #ifdef SHARED_SECTION_ASM_OP |
---|
200 | fprintf (asm_out_file, "%s\n", SHARED_SECTION_ASM_OP); |
---|
201 | #else |
---|
202 | fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP); |
---|
203 | #endif |
---|
204 | } |
---|
205 | else |
---|
206 | fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP); |
---|
207 | } |
---|
208 | |
---|
209 | in_section = in_data; |
---|
210 | } |
---|
211 | } |
---|
212 | |
---|
213 | /* Tell assembler to switch to read-only data section. This is normally |
---|
214 | the text section. */ |
---|
215 | |
---|
216 | void |
---|
217 | readonly_data_section () |
---|
218 | { |
---|
219 | #ifdef READONLY_DATA_SECTION |
---|
220 | READONLY_DATA_SECTION (); /* Note this can call data_section. */ |
---|
221 | #else |
---|
222 | text_section (); |
---|
223 | #endif |
---|
224 | } |
---|
225 | |
---|
226 | /* Determine if we're in the text section. */ |
---|
227 | |
---|
228 | int |
---|
229 | in_text_section () |
---|
230 | { |
---|
231 | return in_section == in_text; |
---|
232 | } |
---|
233 | |
---|
234 | /* Tell assembler to change to section NAME for DECL. |
---|
235 | If DECL is NULL, just switch to section NAME. |
---|
236 | If NAME is NULL, get the name from DECL. */ |
---|
237 | |
---|
238 | void |
---|
239 | named_section (decl, name) |
---|
240 | tree decl; |
---|
241 | char *name; |
---|
242 | { |
---|
243 | if (decl != NULL_TREE |
---|
244 | && (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)) |
---|
245 | abort (); |
---|
246 | if (name == NULL) |
---|
247 | name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); |
---|
248 | |
---|
249 | if (in_section != in_named || strcmp (name, in_named_name)) |
---|
250 | { |
---|
251 | in_named_name = name; |
---|
252 | in_section = in_named; |
---|
253 | |
---|
254 | #ifdef ASM_OUTPUT_SECTION_NAME |
---|
255 | ASM_OUTPUT_SECTION_NAME (asm_out_file, decl, name); |
---|
256 | #else |
---|
257 | /* Section attributes are not supported if this macro isn't provided - |
---|
258 | some host formats don't support them at all. The front-end should |
---|
259 | already have flagged this as an error. */ |
---|
260 | abort (); |
---|
261 | #endif |
---|
262 | } |
---|
263 | } |
---|
264 | |
---|
265 | /* Switch to the section for function DECL. |
---|
266 | |
---|
267 | If DECL is NULL_TREE, switch to the text section. |
---|
268 | ??? It's not clear that we will ever be passed NULL_TREE, but it's |
---|
269 | safer to handle it. */ |
---|
270 | |
---|
271 | void |
---|
272 | function_section (decl) |
---|
273 | tree decl; |
---|
274 | { |
---|
275 | if (decl != NULL_TREE |
---|
276 | && DECL_SECTION_NAME (decl) != NULL_TREE) |
---|
277 | named_section (decl, (char *) 0); |
---|
278 | else |
---|
279 | text_section (); |
---|
280 | } |
---|
281 | |
---|
282 | /* Create the rtl to represent a function, for a function definition. |
---|
283 | DECL is a FUNCTION_DECL node which describes which function. |
---|
284 | The rtl is stored into DECL. */ |
---|
285 | |
---|
286 | void |
---|
287 | make_function_rtl (decl) |
---|
288 | tree decl; |
---|
289 | { |
---|
290 | char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); |
---|
291 | |
---|
292 | if (output_bytecode) |
---|
293 | { |
---|
294 | if (DECL_RTL (decl) == 0) |
---|
295 | DECL_RTL (decl) = bc_gen_rtx (name, 0, (struct bc_label *) 0); |
---|
296 | |
---|
297 | /* Record that at least one function has been defined. */ |
---|
298 | function_defined = 1; |
---|
299 | return; |
---|
300 | } |
---|
301 | |
---|
302 | /* Rename a nested function to avoid conflicts. */ |
---|
303 | if (decl_function_context (decl) != 0 |
---|
304 | && DECL_INITIAL (decl) != 0 |
---|
305 | && DECL_RTL (decl) == 0) |
---|
306 | { |
---|
307 | char *label; |
---|
308 | |
---|
309 | name = IDENTIFIER_POINTER (DECL_NAME (decl)); |
---|
310 | ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno); |
---|
311 | name = obstack_copy0 (saveable_obstack, label, strlen (label)); |
---|
312 | var_labelno++; |
---|
313 | } |
---|
314 | |
---|
315 | if (DECL_RTL (decl) == 0) |
---|
316 | { |
---|
317 | DECL_RTL (decl) |
---|
318 | = gen_rtx (MEM, DECL_MODE (decl), |
---|
319 | gen_rtx (SYMBOL_REF, Pmode, name)); |
---|
320 | |
---|
321 | /* Optionally set flags or add text to the name to record information |
---|
322 | such as that it is a function name. If the name is changed, the macro |
---|
323 | ASM_OUTPUT_LABELREF will have to know how to strip this information. */ |
---|
324 | #ifdef ENCODE_SECTION_INFO |
---|
325 | ENCODE_SECTION_INFO (decl); |
---|
326 | #endif |
---|
327 | } |
---|
328 | |
---|
329 | /* Record at least one function has been defined. */ |
---|
330 | function_defined = 1; |
---|
331 | } |
---|
332 | |
---|
333 | /* Create the DECL_RTL for a declaration for a static or external |
---|
334 | variable or static or external function. |
---|
335 | ASMSPEC, if not 0, is the string which the user specified |
---|
336 | as the assembler symbol name. |
---|
337 | TOP_LEVEL is nonzero if this is a file-scope variable. |
---|
338 | This is never called for PARM_DECLs. */ |
---|
339 | |
---|
340 | static void |
---|
341 | bc_make_decl_rtl (decl, asmspec, top_level) |
---|
342 | tree decl; |
---|
343 | char *asmspec; |
---|
344 | int top_level; |
---|
345 | { |
---|
346 | register char *name = TREE_STRING_POINTER (DECL_ASSEMBLER_NAME (decl)); |
---|
347 | |
---|
348 | if (DECL_RTL (decl) == 0) |
---|
349 | { |
---|
350 | /* Print an error message for register variables. */ |
---|
351 | if (DECL_REGISTER (decl) && TREE_CODE (decl) == FUNCTION_DECL) |
---|
352 | error ("function declared `register'"); |
---|
353 | else if (DECL_REGISTER (decl)) |
---|
354 | error ("global register variables not supported in the interpreter"); |
---|
355 | |
---|
356 | /* Handle ordinary static variables and functions. */ |
---|
357 | if (DECL_RTL (decl) == 0) |
---|
358 | { |
---|
359 | /* Can't use just the variable's own name for a variable |
---|
360 | whose scope is less than the whole file. |
---|
361 | Concatenate a distinguishing number. */ |
---|
362 | if (!top_level && !DECL_EXTERNAL (decl) && asmspec == 0) |
---|
363 | { |
---|
364 | char *label; |
---|
365 | |
---|
366 | ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno); |
---|
367 | name = obstack_copy0 (saveable_obstack, label, strlen (label)); |
---|
368 | var_labelno++; |
---|
369 | } |
---|
370 | |
---|
371 | DECL_RTL (decl) = bc_gen_rtx (name, 0, (struct bc_label *) 0); |
---|
372 | } |
---|
373 | } |
---|
374 | } |
---|
375 | |
---|
376 | /* Given NAME, a putative register name, discard any customary prefixes. */ |
---|
377 | |
---|
378 | static char * |
---|
379 | strip_reg_name (name) |
---|
380 | char *name; |
---|
381 | { |
---|
382 | #ifdef REGISTER_PREFIX |
---|
383 | if (!strncmp (name, REGISTER_PREFIX, strlen (REGISTER_PREFIX))) |
---|
384 | name += strlen (REGISTER_PREFIX); |
---|
385 | #endif |
---|
386 | if (name[0] == '%' || name[0] == '#') |
---|
387 | name++; |
---|
388 | return name; |
---|
389 | } |
---|
390 | |
---|
391 | /* Decode an `asm' spec for a declaration as a register name. |
---|
392 | Return the register number, or -1 if nothing specified, |
---|
393 | or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized, |
---|
394 | or -3 if ASMSPEC is `cc' and is not recognized, |
---|
395 | or -4 if ASMSPEC is `memory' and is not recognized. |
---|
396 | Accept an exact spelling or a decimal number. |
---|
397 | Prefixes such as % are optional. */ |
---|
398 | |
---|
399 | int |
---|
400 | decode_reg_name (asmspec) |
---|
401 | char *asmspec; |
---|
402 | { |
---|
403 | if (asmspec != 0) |
---|
404 | { |
---|
405 | int i; |
---|
406 | |
---|
407 | /* Get rid of confusing prefixes. */ |
---|
408 | asmspec = strip_reg_name (asmspec); |
---|
409 | |
---|
410 | /* Allow a decimal number as a "register name". */ |
---|
411 | for (i = strlen (asmspec) - 1; i >= 0; i--) |
---|
412 | if (! (asmspec[i] >= '0' && asmspec[i] <= '9')) |
---|
413 | break; |
---|
414 | if (asmspec[0] != 0 && i < 0) |
---|
415 | { |
---|
416 | i = atoi (asmspec); |
---|
417 | if (i < FIRST_PSEUDO_REGISTER && i >= 0) |
---|
418 | return i; |
---|
419 | else |
---|
420 | return -2; |
---|
421 | } |
---|
422 | |
---|
423 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
---|
424 | if (reg_names[i][0] |
---|
425 | && ! strcmp (asmspec, strip_reg_name (reg_names[i]))) |
---|
426 | return i; |
---|
427 | |
---|
428 | #ifdef ADDITIONAL_REGISTER_NAMES |
---|
429 | { |
---|
430 | static struct { char *name; int number; } table[] |
---|
431 | = ADDITIONAL_REGISTER_NAMES; |
---|
432 | |
---|
433 | for (i = 0; i < sizeof (table) / sizeof (table[0]); i++) |
---|
434 | if (! strcmp (asmspec, table[i].name)) |
---|
435 | return table[i].number; |
---|
436 | } |
---|
437 | #endif /* ADDITIONAL_REGISTER_NAMES */ |
---|
438 | |
---|
439 | if (!strcmp (asmspec, "memory")) |
---|
440 | return -4; |
---|
441 | |
---|
442 | if (!strcmp (asmspec, "cc")) |
---|
443 | return -3; |
---|
444 | |
---|
445 | return -2; |
---|
446 | } |
---|
447 | |
---|
448 | return -1; |
---|
449 | } |
---|
450 | |
---|
451 | /* Create the DECL_RTL for a declaration for a static or external variable |
---|
452 | or static or external function. |
---|
453 | ASMSPEC, if not 0, is the string which the user specified |
---|
454 | as the assembler symbol name. |
---|
455 | TOP_LEVEL is nonzero if this is a file-scope variable. |
---|
456 | |
---|
457 | This is never called for PARM_DECL nodes. */ |
---|
458 | |
---|
459 | void |
---|
460 | make_decl_rtl (decl, asmspec, top_level) |
---|
461 | tree decl; |
---|
462 | char *asmspec; |
---|
463 | int top_level; |
---|
464 | { |
---|
465 | register char *name = 0; |
---|
466 | int reg_number; |
---|
467 | |
---|
468 | if (output_bytecode) |
---|
469 | { |
---|
470 | bc_make_decl_rtl (decl, asmspec, top_level); |
---|
471 | return; |
---|
472 | } |
---|
473 | |
---|
474 | reg_number = decode_reg_name (asmspec); |
---|
475 | |
---|
476 | if (DECL_ASSEMBLER_NAME (decl) != NULL_TREE) |
---|
477 | name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); |
---|
478 | |
---|
479 | if (reg_number == -2) |
---|
480 | { |
---|
481 | /* ASMSPEC is given, and not the name of a register. */ |
---|
482 | name = (char *) obstack_alloc (saveable_obstack, |
---|
483 | strlen (asmspec) + 2); |
---|
484 | name[0] = '*'; |
---|
485 | strcpy (&name[1], asmspec); |
---|
486 | } |
---|
487 | |
---|
488 | /* For a duplicate declaration, we can be called twice on the |
---|
489 | same DECL node. Don't discard the RTL already made. */ |
---|
490 | if (DECL_RTL (decl) == 0) |
---|
491 | { |
---|
492 | DECL_RTL (decl) = 0; |
---|
493 | |
---|
494 | /* First detect errors in declaring global registers. */ |
---|
495 | if (DECL_REGISTER (decl) && reg_number == -1) |
---|
496 | error_with_decl (decl, |
---|
497 | "register name not specified for `%s'"); |
---|
498 | else if (DECL_REGISTER (decl) && reg_number < 0) |
---|
499 | error_with_decl (decl, |
---|
500 | "invalid register name for `%s'"); |
---|
501 | else if ((reg_number >= 0 || reg_number == -3) && ! DECL_REGISTER (decl)) |
---|
502 | error_with_decl (decl, |
---|
503 | "register name given for non-register variable `%s'"); |
---|
504 | else if (DECL_REGISTER (decl) && TREE_CODE (decl) == FUNCTION_DECL) |
---|
505 | error ("function declared `register'"); |
---|
506 | else if (DECL_REGISTER (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode) |
---|
507 | error_with_decl (decl, "data type of `%s' isn't suitable for a register"); |
---|
508 | else if (DECL_REGISTER (decl) |
---|
509 | && ! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl)))) |
---|
510 | error_with_decl (decl, "register number for `%s' isn't suitable for the data type"); |
---|
511 | /* Now handle properly declared static register variables. */ |
---|
512 | else if (DECL_REGISTER (decl)) |
---|
513 | { |
---|
514 | int nregs; |
---|
515 | #if 0 /* yylex should print the warning for this */ |
---|
516 | if (pedantic) |
---|
517 | pedwarn ("ANSI C forbids global register variables"); |
---|
518 | #endif |
---|
519 | if (DECL_INITIAL (decl) != 0 && top_level) |
---|
520 | { |
---|
521 | DECL_INITIAL (decl) = 0; |
---|
522 | error ("global register variable has initial value"); |
---|
523 | } |
---|
524 | if (fixed_regs[reg_number] == 0 |
---|
525 | && function_defined && top_level) |
---|
526 | error ("global register variable follows a function definition"); |
---|
527 | if (TREE_THIS_VOLATILE (decl)) |
---|
528 | warning ("volatile register variables don't work as you might wish"); |
---|
529 | |
---|
530 | /* If the user specified one of the eliminables registers here, |
---|
531 | e.g., FRAME_POINTER_REGNUM, we don't want to get this variable |
---|
532 | confused with that register and be eliminated. Although this |
---|
533 | usage is somewhat suspect, we nevertheless use the following |
---|
534 | kludge to avoid setting DECL_RTL to frame_pointer_rtx. */ |
---|
535 | |
---|
536 | DECL_RTL (decl) |
---|
537 | = gen_rtx (REG, DECL_MODE (decl), FIRST_PSEUDO_REGISTER); |
---|
538 | REGNO (DECL_RTL (decl)) = reg_number; |
---|
539 | REG_USERVAR_P (DECL_RTL (decl)) = 1; |
---|
540 | |
---|
541 | if (top_level) |
---|
542 | { |
---|
543 | /* Make this register global, so not usable for anything |
---|
544 | else. */ |
---|
545 | nregs = HARD_REGNO_NREGS (reg_number, DECL_MODE (decl)); |
---|
546 | while (nregs > 0) |
---|
547 | globalize_reg (reg_number + --nregs); |
---|
548 | } |
---|
549 | } |
---|
550 | /* Specifying a section attribute on an uninitialized variable does not |
---|
551 | (and cannot) cause it to be put in the given section. The linker |
---|
552 | can only put initialized objects in specific sections, everything |
---|
553 | else goes in bss for the linker to sort out later (otherwise the |
---|
554 | linker would give a duplicate definition error for each compilation |
---|
555 | unit that behaved thusly). So warn the user. */ |
---|
556 | else if (TREE_CODE (decl) == VAR_DECL |
---|
557 | && DECL_SECTION_NAME (decl) != NULL_TREE |
---|
558 | && DECL_INITIAL (decl) == NULL_TREE |
---|
559 | && DECL_COMMON (decl) |
---|
560 | && ! flag_no_common) |
---|
561 | { |
---|
562 | warning_with_decl (decl, |
---|
563 | "section attribute ignored for uninitialized variable `%s'"); |
---|
564 | /* Remove the section name so subsequent declarations won't see it. |
---|
565 | We are ignoring it, remember. */ |
---|
566 | DECL_SECTION_NAME (decl) = NULL_TREE; |
---|
567 | } |
---|
568 | |
---|
569 | /* Now handle ordinary static variables and functions (in memory). |
---|
570 | Also handle vars declared register invalidly. */ |
---|
571 | if (DECL_RTL (decl) == 0) |
---|
572 | { |
---|
573 | /* Can't use just the variable's own name for a variable |
---|
574 | whose scope is less than the whole file. |
---|
575 | Concatenate a distinguishing number. */ |
---|
576 | if (!top_level && !DECL_EXTERNAL (decl) && asmspec == 0) |
---|
577 | { |
---|
578 | char *label; |
---|
579 | |
---|
580 | ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno); |
---|
581 | name = obstack_copy0 (saveable_obstack, label, strlen (label)); |
---|
582 | var_labelno++; |
---|
583 | } |
---|
584 | |
---|
585 | if (name == 0) |
---|
586 | abort (); |
---|
587 | |
---|
588 | DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), |
---|
589 | gen_rtx (SYMBOL_REF, Pmode, name)); |
---|
590 | |
---|
591 | /* If this variable is to be treated as volatile, show its |
---|
592 | tree node has side effects. If it has side effects, either |
---|
593 | because of this test or from TREE_THIS_VOLATILE also |
---|
594 | being set, show the MEM is volatile. */ |
---|
595 | if (flag_volatile_global && TREE_CODE (decl) == VAR_DECL |
---|
596 | && TREE_PUBLIC (decl)) |
---|
597 | TREE_SIDE_EFFECTS (decl) = 1; |
---|
598 | if (TREE_SIDE_EFFECTS (decl)) |
---|
599 | MEM_VOLATILE_P (DECL_RTL (decl)) = 1; |
---|
600 | |
---|
601 | if (TREE_READONLY (decl)) |
---|
602 | RTX_UNCHANGING_P (DECL_RTL (decl)) = 1; |
---|
603 | MEM_IN_STRUCT_P (DECL_RTL (decl)) |
---|
604 | = AGGREGATE_TYPE_P (TREE_TYPE (decl)); |
---|
605 | |
---|
606 | /* Optionally set flags or add text to the name to record information |
---|
607 | such as that it is a function name. |
---|
608 | If the name is changed, the macro ASM_OUTPUT_LABELREF |
---|
609 | will have to know how to strip this information. */ |
---|
610 | #ifdef ENCODE_SECTION_INFO |
---|
611 | ENCODE_SECTION_INFO (decl); |
---|
612 | #endif |
---|
613 | } |
---|
614 | } |
---|
615 | /* If the old RTL had the wrong mode, fix the mode. */ |
---|
616 | else if (GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl)) |
---|
617 | { |
---|
618 | rtx rtl = DECL_RTL (decl); |
---|
619 | PUT_MODE (rtl, DECL_MODE (decl)); |
---|
620 | } |
---|
621 | } |
---|
622 | |
---|
623 | /* Make the rtl for variable VAR be volatile. |
---|
624 | Use this only for static variables. */ |
---|
625 | |
---|
626 | void |
---|
627 | make_var_volatile (var) |
---|
628 | tree var; |
---|
629 | { |
---|
630 | if (GET_CODE (DECL_RTL (var)) != MEM) |
---|
631 | abort (); |
---|
632 | |
---|
633 | MEM_VOLATILE_P (DECL_RTL (var)) = 1; |
---|
634 | } |
---|
635 | |
---|
636 | /* Output alignment directive to align for constant expression EXP. */ |
---|
637 | |
---|
638 | void |
---|
639 | assemble_constant_align (exp) |
---|
640 | tree exp; |
---|
641 | { |
---|
642 | int align; |
---|
643 | |
---|
644 | /* Align the location counter as required by EXP's data type. */ |
---|
645 | align = TYPE_ALIGN (TREE_TYPE (exp)); |
---|
646 | #ifdef CONSTANT_ALIGNMENT |
---|
647 | align = CONSTANT_ALIGNMENT (exp, align); |
---|
648 | #endif |
---|
649 | |
---|
650 | if (align > BITS_PER_UNIT) |
---|
651 | ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); |
---|
652 | } |
---|
653 | |
---|
654 | /* Output a string of literal assembler code |
---|
655 | for an `asm' keyword used between functions. */ |
---|
656 | |
---|
657 | void |
---|
658 | assemble_asm (string) |
---|
659 | tree string; |
---|
660 | { |
---|
661 | if (output_bytecode) |
---|
662 | { |
---|
663 | error ("asm statements not allowed in interpreter"); |
---|
664 | return; |
---|
665 | } |
---|
666 | |
---|
667 | app_enable (); |
---|
668 | |
---|
669 | if (TREE_CODE (string) == ADDR_EXPR) |
---|
670 | string = TREE_OPERAND (string, 0); |
---|
671 | |
---|
672 | fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string)); |
---|
673 | } |
---|
674 | |
---|
675 | #if 0 /* This should no longer be needed, because |
---|
676 | flag_gnu_linker should be 0 on these systems, |
---|
677 | which should prevent any output |
---|
678 | if ASM_OUTPUT_CONSTRUCTOR and ASM_OUTPUT_DESTRUCTOR are absent. */ |
---|
679 | #if !(defined(DBX_DEBUGGING_INFO) && !defined(FASCIST_ASSEMBLER)) |
---|
680 | #ifndef ASM_OUTPUT_CONSTRUCTOR |
---|
681 | #define ASM_OUTPUT_CONSTRUCTOR(file, name) |
---|
682 | #endif |
---|
683 | #ifndef ASM_OUTPUT_DESTRUCTOR |
---|
684 | #define ASM_OUTPUT_DESTRUCTOR(file, name) |
---|
685 | #endif |
---|
686 | #endif |
---|
687 | #endif /* 0 */ |
---|
688 | |
---|
689 | /* Record an element in the table of global destructors. |
---|
690 | How this is done depends on what sort of assembler and linker |
---|
691 | are in use. |
---|
692 | |
---|
693 | NAME should be the name of a global function to be called |
---|
694 | at exit time. This name is output using assemble_name. */ |
---|
695 | |
---|
696 | void |
---|
697 | assemble_destructor (name) |
---|
698 | char *name; |
---|
699 | { |
---|
700 | #ifdef ASM_OUTPUT_DESTRUCTOR |
---|
701 | ASM_OUTPUT_DESTRUCTOR (asm_out_file, name); |
---|
702 | #else |
---|
703 | if (flag_gnu_linker) |
---|
704 | { |
---|
705 | /* Now tell GNU LD that this is part of the static destructor set. */ |
---|
706 | /* This code works for any machine provided you use GNU as/ld. */ |
---|
707 | fprintf (asm_out_file, "%s \"___DTOR_LIST__\",22,0,0,", ASM_STABS_OP); |
---|
708 | assemble_name (asm_out_file, name); |
---|
709 | fputc ('\n', asm_out_file); |
---|
710 | } |
---|
711 | #endif |
---|
712 | } |
---|
713 | |
---|
714 | /* Likewise for global constructors. */ |
---|
715 | |
---|
716 | void |
---|
717 | assemble_constructor (name) |
---|
718 | char *name; |
---|
719 | { |
---|
720 | #ifdef ASM_OUTPUT_CONSTRUCTOR |
---|
721 | ASM_OUTPUT_CONSTRUCTOR (asm_out_file, name); |
---|
722 | #else |
---|
723 | if (flag_gnu_linker) |
---|
724 | { |
---|
725 | /* Now tell GNU LD that this is part of the static constructor set. */ |
---|
726 | /* This code works for any machine provided you use GNU as/ld. */ |
---|
727 | fprintf (asm_out_file, "%s \"___CTOR_LIST__\",22,0,0,", ASM_STABS_OP); |
---|
728 | assemble_name (asm_out_file, name); |
---|
729 | fputc ('\n', asm_out_file); |
---|
730 | } |
---|
731 | #endif |
---|
732 | } |
---|
733 | |
---|
734 | /* Likewise for entries we want to record for garbage collection. |
---|
735 | Garbage collection is still under development. */ |
---|
736 | |
---|
737 | void |
---|
738 | assemble_gc_entry (name) |
---|
739 | char *name; |
---|
740 | { |
---|
741 | #ifdef ASM_OUTPUT_GC_ENTRY |
---|
742 | ASM_OUTPUT_GC_ENTRY (asm_out_file, name); |
---|
743 | #else |
---|
744 | if (flag_gnu_linker) |
---|
745 | { |
---|
746 | /* Now tell GNU LD that this is part of the static constructor set. */ |
---|
747 | fprintf (asm_out_file, "%s \"___PTR_LIST__\",22,0,0,", ASM_STABS_OP); |
---|
748 | assemble_name (asm_out_file, name); |
---|
749 | fputc ('\n', asm_out_file); |
---|
750 | } |
---|
751 | #endif |
---|
752 | } |
---|
753 | |
---|
754 | /* Output assembler code for the constant pool of a function and associated |
---|
755 | with defining the name of the function. DECL describes the function. |
---|
756 | NAME is the function's name. For the constant pool, we use the current |
---|
757 | constant pool data. */ |
---|
758 | |
---|
759 | void |
---|
760 | assemble_start_function (decl, fnname) |
---|
761 | tree decl; |
---|
762 | char *fnname; |
---|
763 | { |
---|
764 | int align; |
---|
765 | |
---|
766 | /* The following code does not need preprocessing in the assembler. */ |
---|
767 | |
---|
768 | app_disable (); |
---|
769 | |
---|
770 | output_constant_pool (fnname, decl); |
---|
771 | |
---|
772 | function_section (decl); |
---|
773 | |
---|
774 | /* Tell assembler to move to target machine's alignment for functions. */ |
---|
775 | align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); |
---|
776 | if (align > 0) |
---|
777 | { |
---|
778 | if (output_bytecode) |
---|
779 | BC_OUTPUT_ALIGN (asm_out_file, align); |
---|
780 | else |
---|
781 | ASM_OUTPUT_ALIGN (asm_out_file, align); |
---|
782 | } |
---|
783 | |
---|
784 | #ifdef ASM_OUTPUT_FUNCTION_PREFIX |
---|
785 | ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname); |
---|
786 | #endif |
---|
787 | |
---|
788 | #ifdef SDB_DEBUGGING_INFO |
---|
789 | /* Output SDB definition of the function. */ |
---|
790 | if (write_symbols == SDB_DEBUG) |
---|
791 | sdbout_mark_begin_function (); |
---|
792 | #endif |
---|
793 | |
---|
794 | #ifdef DBX_DEBUGGING_INFO |
---|
795 | /* Output DBX definition of the function. */ |
---|
796 | if (write_symbols == DBX_DEBUG) |
---|
797 | dbxout_begin_function (decl); |
---|
798 | #endif |
---|
799 | |
---|
800 | /* Make function name accessible from other files, if appropriate. */ |
---|
801 | |
---|
802 | if (TREE_PUBLIC (decl)) |
---|
803 | { |
---|
804 | if (!first_global_object_name) |
---|
805 | { |
---|
806 | char *p; |
---|
807 | |
---|
808 | STRIP_NAME_ENCODING (p, fnname); |
---|
809 | first_global_object_name = permalloc (strlen (p) + 1); |
---|
810 | strcpy (first_global_object_name, p); |
---|
811 | } |
---|
812 | |
---|
813 | #ifdef ASM_WEAKEN_LABEL |
---|
814 | if (DECL_WEAK (decl)) |
---|
815 | ASM_WEAKEN_LABEL (asm_out_file, fnname); |
---|
816 | else |
---|
817 | #endif |
---|
818 | if (output_bytecode) |
---|
819 | BC_GLOBALIZE_LABEL (asm_out_file, fnname); |
---|
820 | else |
---|
821 | ASM_GLOBALIZE_LABEL (asm_out_file, fnname); |
---|
822 | } |
---|
823 | |
---|
824 | /* Do any machine/system dependent processing of the function name */ |
---|
825 | #ifdef ASM_DECLARE_FUNCTION_NAME |
---|
826 | ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl); |
---|
827 | #else |
---|
828 | /* Standard thing is just output label for the function. */ |
---|
829 | if (output_bytecode) |
---|
830 | BC_OUTPUT_LABEL (asm_out_file, fnname); |
---|
831 | else |
---|
832 | ASM_OUTPUT_LABEL (asm_out_file, fnname); |
---|
833 | #endif /* ASM_DECLARE_FUNCTION_NAME */ |
---|
834 | } |
---|
835 | |
---|
836 | /* Output assembler code associated with defining the size of the |
---|
837 | function. DECL describes the function. NAME is the function's name. */ |
---|
838 | |
---|
839 | void |
---|
840 | assemble_end_function (decl, fnname) |
---|
841 | tree decl; |
---|
842 | char *fnname; |
---|
843 | { |
---|
844 | #ifdef ASM_DECLARE_FUNCTION_SIZE |
---|
845 | ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl); |
---|
846 | #endif |
---|
847 | } |
---|
848 | |
---|
849 | /* Assemble code to leave SIZE bytes of zeros. */ |
---|
850 | |
---|
851 | void |
---|
852 | assemble_zeros (size) |
---|
853 | int size; |
---|
854 | { |
---|
855 | if (output_bytecode) |
---|
856 | { |
---|
857 | bc_emit_const_skip (size); |
---|
858 | return; |
---|
859 | } |
---|
860 | |
---|
861 | #ifdef ASM_NO_SKIP_IN_TEXT |
---|
862 | /* The `space' pseudo in the text section outputs nop insns rather than 0s, |
---|
863 | so we must output 0s explicitly in the text section. */ |
---|
864 | if (ASM_NO_SKIP_IN_TEXT && in_text_section ()) |
---|
865 | { |
---|
866 | int i; |
---|
867 | |
---|
868 | for (i = 0; i < size - 20; i += 20) |
---|
869 | { |
---|
870 | #ifdef ASM_BYTE_OP |
---|
871 | fprintf (asm_out_file, |
---|
872 | "%s 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n", ASM_BYTE_OP); |
---|
873 | #else |
---|
874 | fprintf (asm_out_file, |
---|
875 | "\tbyte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); |
---|
876 | #endif |
---|
877 | } |
---|
878 | if (i < size) |
---|
879 | { |
---|
880 | #ifdef ASM_BYTE_OP |
---|
881 | fprintf (asm_out_file, "%s 0", ASM_BYTE_OP); |
---|
882 | #else |
---|
883 | fprintf (asm_out_file, "\tbyte 0"); |
---|
884 | #endif |
---|
885 | i++; |
---|
886 | for (; i < size; i++) |
---|
887 | fprintf (asm_out_file, ",0"); |
---|
888 | fprintf (asm_out_file, "\n"); |
---|
889 | } |
---|
890 | } |
---|
891 | else |
---|
892 | #endif |
---|
893 | if (size > 0) |
---|
894 | { |
---|
895 | if (output_bytecode) |
---|
896 | BC_OUTPUT_SKIP (asm_out_file, size); |
---|
897 | else |
---|
898 | ASM_OUTPUT_SKIP (asm_out_file, size); |
---|
899 | } |
---|
900 | } |
---|
901 | |
---|
902 | /* Assemble an alignment pseudo op for an ALIGN-bit boundary. */ |
---|
903 | |
---|
904 | void |
---|
905 | assemble_align (align) |
---|
906 | int align; |
---|
907 | { |
---|
908 | if (align > BITS_PER_UNIT) |
---|
909 | ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); |
---|
910 | } |
---|
911 | |
---|
912 | /* Assemble a string constant with the specified C string as contents. */ |
---|
913 | |
---|
914 | void |
---|
915 | assemble_string (p, size) |
---|
916 | char *p; |
---|
917 | int size; |
---|
918 | { |
---|
919 | register int i; |
---|
920 | int pos = 0; |
---|
921 | int maximum = 2000; |
---|
922 | |
---|
923 | if (output_bytecode) |
---|
924 | { |
---|
925 | bc_emit (p, size); |
---|
926 | return; |
---|
927 | } |
---|
928 | |
---|
929 | /* If the string is very long, split it up. */ |
---|
930 | |
---|
931 | while (pos < size) |
---|
932 | { |
---|
933 | int thissize = size - pos; |
---|
934 | if (thissize > maximum) |
---|
935 | thissize = maximum; |
---|
936 | |
---|
937 | if (output_bytecode) |
---|
938 | bc_output_ascii (asm_out_file, p, thissize); |
---|
939 | else |
---|
940 | { |
---|
941 | ASM_OUTPUT_ASCII (asm_out_file, p, thissize); |
---|
942 | } |
---|
943 | |
---|
944 | pos += thissize; |
---|
945 | p += thissize; |
---|
946 | } |
---|
947 | } |
---|
948 | |
---|
949 | static void |
---|
950 | bc_output_ascii (file, p, size) |
---|
951 | FILE *file; |
---|
952 | char *p; |
---|
953 | int size; |
---|
954 | { |
---|
955 | BC_OUTPUT_ASCII (file, p, size); |
---|
956 | } |
---|
957 | |
---|
958 | /* Assemble everything that is needed for a variable or function declaration. |
---|
959 | Not used for automatic variables, and not used for function definitions. |
---|
960 | Should not be called for variables of incomplete structure type. |
---|
961 | |
---|
962 | TOP_LEVEL is nonzero if this variable has file scope. |
---|
963 | AT_END is nonzero if this is the special handling, at end of compilation, |
---|
964 | to define things that have had only tentative definitions. |
---|
965 | DONT_OUTPUT_DATA if nonzero means don't actually output the |
---|
966 | initial value (that will be done by the caller). */ |
---|
967 | |
---|
968 | void |
---|
969 | assemble_variable (decl, top_level, at_end, dont_output_data) |
---|
970 | tree decl; |
---|
971 | int top_level; |
---|
972 | int at_end; |
---|
973 | int dont_output_data; |
---|
974 | { |
---|
975 | register char *name; |
---|
976 | int align; |
---|
977 | tree size_tree; |
---|
978 | int reloc = 0; |
---|
979 | enum in_section saved_in_section; |
---|
980 | |
---|
981 | last_assemble_variable_decl = 0; |
---|
982 | |
---|
983 | if (output_bytecode) |
---|
984 | return; |
---|
985 | |
---|
986 | if (GET_CODE (DECL_RTL (decl)) == REG) |
---|
987 | { |
---|
988 | /* Do output symbol info for global register variables, but do nothing |
---|
989 | else for them. */ |
---|
990 | |
---|
991 | if (TREE_ASM_WRITTEN (decl)) |
---|
992 | return; |
---|
993 | TREE_ASM_WRITTEN (decl) = 1; |
---|
994 | |
---|
995 | if (!output_bytecode) |
---|
996 | { |
---|
997 | #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) |
---|
998 | /* File-scope global variables are output here. */ |
---|
999 | if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) |
---|
1000 | && top_level) |
---|
1001 | dbxout_symbol (decl, 0); |
---|
1002 | #endif |
---|
1003 | #ifdef SDB_DEBUGGING_INFO |
---|
1004 | if (write_symbols == SDB_DEBUG && top_level |
---|
1005 | /* Leave initialized global vars for end of compilation; |
---|
1006 | see comment in compile_file. */ |
---|
1007 | && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0)) |
---|
1008 | sdbout_symbol (decl, 0); |
---|
1009 | #endif |
---|
1010 | } |
---|
1011 | |
---|
1012 | /* Don't output any DWARF debugging information for variables here. |
---|
1013 | In the case of local variables, the information for them is output |
---|
1014 | when we do our recursive traversal of the tree representation for |
---|
1015 | the entire containing function. In the case of file-scope variables, |
---|
1016 | we output information for all of them at the very end of compilation |
---|
1017 | while we are doing our final traversal of the chain of file-scope |
---|
1018 | declarations. */ |
---|
1019 | |
---|
1020 | return; |
---|
1021 | } |
---|
1022 | |
---|
1023 | /* Normally no need to say anything here for external references, |
---|
1024 | since assemble_external is called by the language-specific code |
---|
1025 | when a declaration is first seen. */ |
---|
1026 | |
---|
1027 | if (DECL_EXTERNAL (decl)) |
---|
1028 | return; |
---|
1029 | |
---|
1030 | /* Output no assembler code for a function declaration. |
---|
1031 | Only definitions of functions output anything. */ |
---|
1032 | |
---|
1033 | if (TREE_CODE (decl) == FUNCTION_DECL) |
---|
1034 | return; |
---|
1035 | |
---|
1036 | /* If type was incomplete when the variable was declared, |
---|
1037 | see if it is complete now. */ |
---|
1038 | |
---|
1039 | if (DECL_SIZE (decl) == 0) |
---|
1040 | layout_decl (decl, 0); |
---|
1041 | |
---|
1042 | /* Still incomplete => don't allocate it; treat the tentative defn |
---|
1043 | (which is what it must have been) as an `extern' reference. */ |
---|
1044 | |
---|
1045 | if (!dont_output_data && DECL_SIZE (decl) == 0) |
---|
1046 | { |
---|
1047 | error_with_file_and_line (DECL_SOURCE_FILE (decl), |
---|
1048 | DECL_SOURCE_LINE (decl), |
---|
1049 | "storage size of `%s' isn't known", |
---|
1050 | IDENTIFIER_POINTER (DECL_NAME (decl))); |
---|
1051 | TREE_ASM_WRITTEN (decl) = 1; |
---|
1052 | return; |
---|
1053 | } |
---|
1054 | |
---|
1055 | /* The first declaration of a variable that comes through this function |
---|
1056 | decides whether it is global (in C, has external linkage) |
---|
1057 | or local (in C, has internal linkage). So do nothing more |
---|
1058 | if this function has already run. */ |
---|
1059 | |
---|
1060 | if (TREE_ASM_WRITTEN (decl)) |
---|
1061 | return; |
---|
1062 | |
---|
1063 | TREE_ASM_WRITTEN (decl) = 1; |
---|
1064 | |
---|
1065 | app_disable (); |
---|
1066 | |
---|
1067 | if (! dont_output_data) |
---|
1068 | { |
---|
1069 | if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) |
---|
1070 | goto finish; |
---|
1071 | |
---|
1072 | /* This is better than explicit arithmetic, since it avoids overflow. */ |
---|
1073 | size_tree = size_binop (CEIL_DIV_EXPR, |
---|
1074 | DECL_SIZE (decl), size_int (BITS_PER_UNIT)); |
---|
1075 | |
---|
1076 | if (TREE_INT_CST_HIGH (size_tree) != 0) |
---|
1077 | { |
---|
1078 | error_with_decl (decl, "size of variable `%s' is too large"); |
---|
1079 | goto finish; |
---|
1080 | } |
---|
1081 | } |
---|
1082 | |
---|
1083 | name = XSTR (XEXP (DECL_RTL (decl), 0), 0); |
---|
1084 | |
---|
1085 | /* Handle uninitialized definitions. */ |
---|
1086 | |
---|
1087 | /* ANSI specifies that a tentative definition which is not merged with |
---|
1088 | a non-tentative definition behaves exactly like a definition with an |
---|
1089 | initializer equal to zero. (Section 3.7.2) |
---|
1090 | -fno-common gives strict ANSI behavior. Usually you don't want it. |
---|
1091 | This matters only for variables with external linkage. */ |
---|
1092 | if ((! flag_no_common || ! TREE_PUBLIC (decl)) |
---|
1093 | && DECL_COMMON (decl) |
---|
1094 | && ! dont_output_data |
---|
1095 | && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)) |
---|
1096 | { |
---|
1097 | int size = TREE_INT_CST_LOW (size_tree); |
---|
1098 | int rounded = size; |
---|
1099 | |
---|
1100 | if (TREE_INT_CST_HIGH (size_tree) != 0) |
---|
1101 | error_with_decl (decl, "size of variable `%s' is too large"); |
---|
1102 | /* Don't allocate zero bytes of common, |
---|
1103 | since that means "undefined external" in the linker. */ |
---|
1104 | if (size == 0) rounded = 1; |
---|
1105 | /* Round size up to multiple of BIGGEST_ALIGNMENT bits |
---|
1106 | so that each uninitialized object starts on such a boundary. */ |
---|
1107 | rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; |
---|
1108 | rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) |
---|
1109 | * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); |
---|
1110 | |
---|
1111 | #ifdef DBX_DEBUGGING_INFO |
---|
1112 | /* File-scope global variables are output here. */ |
---|
1113 | if (write_symbols == DBX_DEBUG && top_level) |
---|
1114 | dbxout_symbol (decl, 0); |
---|
1115 | #endif |
---|
1116 | #ifdef SDB_DEBUGGING_INFO |
---|
1117 | if (write_symbols == SDB_DEBUG && top_level |
---|
1118 | /* Leave initialized global vars for end of compilation; |
---|
1119 | see comment in compile_file. */ |
---|
1120 | && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0)) |
---|
1121 | sdbout_symbol (decl, 0); |
---|
1122 | #endif |
---|
1123 | |
---|
1124 | /* Don't output any DWARF debugging information for variables here. |
---|
1125 | In the case of local variables, the information for them is output |
---|
1126 | when we do our recursive traversal of the tree representation for |
---|
1127 | the entire containing function. In the case of file-scope variables, |
---|
1128 | we output information for all of them at the very end of compilation |
---|
1129 | while we are doing our final traversal of the chain of file-scope |
---|
1130 | declarations. */ |
---|
1131 | |
---|
1132 | #if 0 |
---|
1133 | if (flag_shared_data) |
---|
1134 | data_section (); |
---|
1135 | #endif |
---|
1136 | if (TREE_PUBLIC (decl)) |
---|
1137 | { |
---|
1138 | #ifdef ASM_OUTPUT_SHARED_COMMON |
---|
1139 | if (flag_shared_data) |
---|
1140 | ASM_OUTPUT_SHARED_COMMON (asm_out_file, name, size, rounded); |
---|
1141 | else |
---|
1142 | #endif |
---|
1143 | if (output_bytecode) |
---|
1144 | { |
---|
1145 | BC_OUTPUT_COMMON (asm_out_file, name, size, rounded); |
---|
1146 | } |
---|
1147 | else |
---|
1148 | { |
---|
1149 | #ifdef ASM_OUTPUT_ALIGNED_COMMON |
---|
1150 | ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, |
---|
1151 | DECL_ALIGN (decl)); |
---|
1152 | #else |
---|
1153 | ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded); |
---|
1154 | #endif |
---|
1155 | } |
---|
1156 | } |
---|
1157 | else |
---|
1158 | { |
---|
1159 | #ifdef ASM_OUTPUT_SHARED_LOCAL |
---|
1160 | if (flag_shared_data) |
---|
1161 | ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded); |
---|
1162 | else |
---|
1163 | #endif |
---|
1164 | if (output_bytecode) |
---|
1165 | { |
---|
1166 | BC_OUTPUT_LOCAL (asm_out_file, name, size, rounded); |
---|
1167 | } |
---|
1168 | else |
---|
1169 | { |
---|
1170 | #ifdef ASM_OUTPUT_ALIGNED_LOCAL |
---|
1171 | ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, |
---|
1172 | DECL_ALIGN (decl)); |
---|
1173 | #else |
---|
1174 | ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded); |
---|
1175 | #endif |
---|
1176 | } |
---|
1177 | } |
---|
1178 | goto finish; |
---|
1179 | } |
---|
1180 | |
---|
1181 | /* Handle initialized definitions. */ |
---|
1182 | |
---|
1183 | /* First make the assembler name(s) global if appropriate. */ |
---|
1184 | if (TREE_PUBLIC (decl) && DECL_NAME (decl)) |
---|
1185 | { |
---|
1186 | if (!first_global_object_name) |
---|
1187 | { |
---|
1188 | char *p; |
---|
1189 | |
---|
1190 | STRIP_NAME_ENCODING (p, name); |
---|
1191 | first_global_object_name = permalloc (strlen (p) + 1); |
---|
1192 | strcpy (first_global_object_name, p); |
---|
1193 | } |
---|
1194 | |
---|
1195 | #ifdef ASM_WEAKEN_LABEL |
---|
1196 | if (DECL_WEAK (decl)) |
---|
1197 | ASM_WEAKEN_LABEL (asm_out_file, name); |
---|
1198 | else |
---|
1199 | #endif |
---|
1200 | ASM_GLOBALIZE_LABEL (asm_out_file, name); |
---|
1201 | } |
---|
1202 | #if 0 |
---|
1203 | for (d = equivalents; d; d = TREE_CHAIN (d)) |
---|
1204 | { |
---|
1205 | tree e = TREE_VALUE (d); |
---|
1206 | if (TREE_PUBLIC (e) && DECL_NAME (e)) |
---|
1207 | ASM_GLOBALIZE_LABEL (asm_out_file, |
---|
1208 | XSTR (XEXP (DECL_RTL (e), 0), 0)); |
---|
1209 | } |
---|
1210 | #endif |
---|
1211 | |
---|
1212 | /* Output any data that we will need to use the address of. */ |
---|
1213 | if (DECL_INITIAL (decl) == error_mark_node) |
---|
1214 | reloc = contains_pointers_p (TREE_TYPE (decl)); |
---|
1215 | else if (DECL_INITIAL (decl)) |
---|
1216 | reloc = output_addressed_constants (DECL_INITIAL (decl)); |
---|
1217 | |
---|
1218 | /* Switch to the proper section for this data. */ |
---|
1219 | if (IN_NAMED_SECTION (decl)) |
---|
1220 | named_section (decl, NULL); |
---|
1221 | else |
---|
1222 | { |
---|
1223 | /* C++ can have const variables that get initialized from constructors, |
---|
1224 | and thus can not be in a readonly section. We prevent this by |
---|
1225 | verifying that the initial value is constant for objects put in a |
---|
1226 | readonly section. |
---|
1227 | |
---|
1228 | error_mark_node is used by the C front end to indicate that the |
---|
1229 | initializer has not been seen yet. In this case, we assume that |
---|
1230 | the initializer must be constant. */ |
---|
1231 | #ifdef SELECT_SECTION |
---|
1232 | SELECT_SECTION (decl, reloc); |
---|
1233 | #else |
---|
1234 | if (TREE_READONLY (decl) |
---|
1235 | && ! TREE_THIS_VOLATILE (decl) |
---|
1236 | && DECL_INITIAL (decl) |
---|
1237 | && (DECL_INITIAL (decl) == error_mark_node |
---|
1238 | || TREE_CONSTANT (DECL_INITIAL (decl))) |
---|
1239 | && ! (flag_pic && reloc)) |
---|
1240 | readonly_data_section (); |
---|
1241 | else |
---|
1242 | data_section (); |
---|
1243 | #endif |
---|
1244 | } |
---|
1245 | |
---|
1246 | /* dbxout.c needs to know this. */ |
---|
1247 | if (in_text_section ()) |
---|
1248 | DECL_IN_TEXT_SECTION (decl) = 1; |
---|
1249 | |
---|
1250 | /* Record current section so we can restore it if dbxout.c clobbers it. */ |
---|
1251 | saved_in_section = in_section; |
---|
1252 | |
---|
1253 | /* Output the dbx info now that we have chosen the section. */ |
---|
1254 | |
---|
1255 | #ifdef DBX_DEBUGGING_INFO |
---|
1256 | /* File-scope global variables are output here. */ |
---|
1257 | if (write_symbols == DBX_DEBUG && top_level) |
---|
1258 | dbxout_symbol (decl, 0); |
---|
1259 | #endif |
---|
1260 | #ifdef SDB_DEBUGGING_INFO |
---|
1261 | if (write_symbols == SDB_DEBUG && top_level |
---|
1262 | /* Leave initialized global vars for end of compilation; |
---|
1263 | see comment in compile_file. */ |
---|
1264 | && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0)) |
---|
1265 | sdbout_symbol (decl, 0); |
---|
1266 | #endif |
---|
1267 | |
---|
1268 | /* Don't output any DWARF debugging information for variables here. |
---|
1269 | In the case of local variables, the information for them is output |
---|
1270 | when we do our recursive traversal of the tree representation for |
---|
1271 | the entire containing function. In the case of file-scope variables, |
---|
1272 | we output information for all of them at the very end of compilation |
---|
1273 | while we are doing our final traversal of the chain of file-scope |
---|
1274 | declarations. */ |
---|
1275 | |
---|
1276 | /* If the debugging output changed sections, reselect the section |
---|
1277 | that's supposed to be selected. */ |
---|
1278 | if (in_section != saved_in_section) |
---|
1279 | { |
---|
1280 | /* Switch to the proper section for this data. */ |
---|
1281 | #ifdef SELECT_SECTION |
---|
1282 | SELECT_SECTION (decl, reloc); |
---|
1283 | #else |
---|
1284 | if (TREE_READONLY (decl) |
---|
1285 | && ! TREE_THIS_VOLATILE (decl) |
---|
1286 | && DECL_INITIAL (decl) |
---|
1287 | && (DECL_INITIAL (decl) == error_mark_node |
---|
1288 | || TREE_CONSTANT (DECL_INITIAL (decl))) |
---|
1289 | && ! (flag_pic && reloc)) |
---|
1290 | readonly_data_section (); |
---|
1291 | else |
---|
1292 | data_section (); |
---|
1293 | #endif |
---|
1294 | } |
---|
1295 | |
---|
1296 | /* Compute and output the alignment of this data. */ |
---|
1297 | |
---|
1298 | align = DECL_ALIGN (decl); |
---|
1299 | /* In the case for initialing an array whose length isn't specified, |
---|
1300 | where we have not yet been able to do the layout, |
---|
1301 | figure out the proper alignment now. */ |
---|
1302 | if (dont_output_data && DECL_SIZE (decl) == 0 |
---|
1303 | && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) |
---|
1304 | align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl)))); |
---|
1305 | |
---|
1306 | /* Some object file formats have a maximum alignment which they support. |
---|
1307 | In particular, a.out format supports a maximum alignment of 4. */ |
---|
1308 | #ifndef MAX_OFILE_ALIGNMENT |
---|
1309 | #define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT |
---|
1310 | #endif |
---|
1311 | if (align > MAX_OFILE_ALIGNMENT) |
---|
1312 | { |
---|
1313 | warning_with_decl (decl, |
---|
1314 | "alignment of `%s' is greater than maximum object file alignment"); |
---|
1315 | align = MAX_OFILE_ALIGNMENT; |
---|
1316 | } |
---|
1317 | #ifdef DATA_ALIGNMENT |
---|
1318 | /* On some machines, it is good to increase alignment sometimes. */ |
---|
1319 | align = DATA_ALIGNMENT (TREE_TYPE (decl), align); |
---|
1320 | #endif |
---|
1321 | #ifdef CONSTANT_ALIGNMENT |
---|
1322 | if (DECL_INITIAL (decl)) |
---|
1323 | align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align); |
---|
1324 | #endif |
---|
1325 | |
---|
1326 | /* Reset the alignment in case we have made it tighter, so we can benefit |
---|
1327 | from it in get_pointer_alignment. */ |
---|
1328 | DECL_ALIGN (decl) = align; |
---|
1329 | |
---|
1330 | if (align > BITS_PER_UNIT) |
---|
1331 | { |
---|
1332 | if (output_bytecode) |
---|
1333 | BC_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); |
---|
1334 | else |
---|
1335 | ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); |
---|
1336 | } |
---|
1337 | |
---|
1338 | /* Do any machine/system dependent processing of the object. */ |
---|
1339 | #ifdef ASM_DECLARE_OBJECT_NAME |
---|
1340 | last_assemble_variable_decl = decl; |
---|
1341 | ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl); |
---|
1342 | #else |
---|
1343 | /* Standard thing is just output label for the object. */ |
---|
1344 | if (output_bytecode) |
---|
1345 | BC_OUTPUT_LABEL (asm_out_file, name); |
---|
1346 | else |
---|
1347 | ASM_OUTPUT_LABEL (asm_out_file, name); |
---|
1348 | #endif /* ASM_DECLARE_OBJECT_NAME */ |
---|
1349 | |
---|
1350 | if (!dont_output_data) |
---|
1351 | { |
---|
1352 | if (DECL_INITIAL (decl)) |
---|
1353 | /* Output the actual data. */ |
---|
1354 | output_constant (DECL_INITIAL (decl), TREE_INT_CST_LOW (size_tree)); |
---|
1355 | else |
---|
1356 | /* Leave space for it. */ |
---|
1357 | assemble_zeros (TREE_INT_CST_LOW (size_tree)); |
---|
1358 | } |
---|
1359 | |
---|
1360 | finish: |
---|
1361 | #ifdef XCOFF_DEBUGGING_INFO |
---|
1362 | /* Unfortunately, the IBM assembler cannot handle stabx before the actual |
---|
1363 | declaration. When something like ".stabx "aa:S-2",aa,133,0" is emitted |
---|
1364 | and `aa' hasn't been output yet, the assembler generates a stab entry with |
---|
1365 | a value of zero, in addition to creating an unnecessary external entry |
---|
1366 | for `aa'. Hence, we must postpone dbxout_symbol to here at the end. */ |
---|
1367 | |
---|
1368 | /* File-scope global variables are output here. */ |
---|
1369 | if (write_symbols == XCOFF_DEBUG && top_level) |
---|
1370 | { |
---|
1371 | saved_in_section = in_section; |
---|
1372 | |
---|
1373 | dbxout_symbol (decl, 0); |
---|
1374 | |
---|
1375 | if (in_section != saved_in_section) |
---|
1376 | { |
---|
1377 | /* Switch to the proper section for this data. */ |
---|
1378 | #ifdef SELECT_SECTION |
---|
1379 | SELECT_SECTION (decl, reloc); |
---|
1380 | #else |
---|
1381 | if (TREE_READONLY (decl) |
---|
1382 | && ! TREE_THIS_VOLATILE (decl) |
---|
1383 | && DECL_INITIAL (decl) |
---|
1384 | && (DECL_INITIAL (decl) == error_mark_node |
---|
1385 | || TREE_CONSTANT (DECL_INITIAL (decl))) |
---|
1386 | && ! (flag_pic && reloc)) |
---|
1387 | readonly_data_section (); |
---|
1388 | else |
---|
1389 | data_section (); |
---|
1390 | #endif |
---|
1391 | } |
---|
1392 | } |
---|
1393 | #else |
---|
1394 | /* There must be a statement after a label. */ |
---|
1395 | ; |
---|
1396 | #endif |
---|
1397 | } |
---|
1398 | |
---|
1399 | /* Return 1 if type TYPE contains any pointers. */ |
---|
1400 | |
---|
1401 | static int |
---|
1402 | contains_pointers_p (type) |
---|
1403 | tree type; |
---|
1404 | { |
---|
1405 | switch (TREE_CODE (type)) |
---|
1406 | { |
---|
1407 | case POINTER_TYPE: |
---|
1408 | case REFERENCE_TYPE: |
---|
1409 | /* I'm not sure whether OFFSET_TYPE needs this treatment, |
---|
1410 | so I'll play safe and return 1. */ |
---|
1411 | case OFFSET_TYPE: |
---|
1412 | return 1; |
---|
1413 | |
---|
1414 | case RECORD_TYPE: |
---|
1415 | case UNION_TYPE: |
---|
1416 | case QUAL_UNION_TYPE: |
---|
1417 | { |
---|
1418 | tree fields; |
---|
1419 | /* For a type that has fields, see if the fields have pointers. */ |
---|
1420 | for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) |
---|
1421 | if (TREE_CODE (fields) == FIELD_DECL |
---|
1422 | && contains_pointers_p (TREE_TYPE (fields))) |
---|
1423 | return 1; |
---|
1424 | return 0; |
---|
1425 | } |
---|
1426 | |
---|
1427 | case ARRAY_TYPE: |
---|
1428 | /* An array type contains pointers if its element type does. */ |
---|
1429 | return contains_pointers_p (TREE_TYPE (type)); |
---|
1430 | |
---|
1431 | default: |
---|
1432 | return 0; |
---|
1433 | } |
---|
1434 | } |
---|
1435 | |
---|
1436 | /* Output text storage for constructor CONSTR. */ |
---|
1437 | |
---|
1438 | void |
---|
1439 | bc_output_constructor (constr, size) |
---|
1440 | tree constr; |
---|
1441 | int size; |
---|
1442 | { |
---|
1443 | int i; |
---|
1444 | |
---|
1445 | /* Must always be a literal; non-literal constructors are handled |
---|
1446 | differently. */ |
---|
1447 | |
---|
1448 | if (!TREE_CONSTANT (constr)) |
---|
1449 | abort (); |
---|
1450 | |
---|
1451 | /* Always const */ |
---|
1452 | text_section (); |
---|
1453 | |
---|
1454 | /* Align */ |
---|
1455 | for (i = 0; TYPE_ALIGN (constr) >= BITS_PER_UNIT << (i + 1); i++) |
---|
1456 | ; |
---|
1457 | |
---|
1458 | if (i > 0) |
---|
1459 | BC_OUTPUT_ALIGN (asm_out_file, i); |
---|
1460 | |
---|
1461 | /* Output data */ |
---|
1462 | output_constant (constr, size); |
---|
1463 | } |
---|
1464 | |
---|
1465 | /* Create storage for constructor CONSTR. */ |
---|
1466 | |
---|
1467 | void |
---|
1468 | bc_output_data_constructor (constr) |
---|
1469 | tree constr; |
---|
1470 | { |
---|
1471 | int i; |
---|
1472 | |
---|
1473 | /* Put in data section */ |
---|
1474 | data_section (); |
---|
1475 | |
---|
1476 | /* Align */ |
---|
1477 | for (i = 0; TYPE_ALIGN (constr) >= BITS_PER_UNIT << (i + 1); i++); |
---|
1478 | if (i > 0) |
---|
1479 | BC_OUTPUT_ALIGN (asm_out_file, i); |
---|
1480 | |
---|
1481 | /* The constructor is filled in at runtime. */ |
---|
1482 | BC_OUTPUT_SKIP (asm_out_file, int_size_in_bytes (TREE_TYPE (constr))); |
---|
1483 | } |
---|
1484 | |
---|
1485 | /* Output something to declare an external symbol to the assembler. |
---|
1486 | (Most assemblers don't need this, so we normally output nothing.) |
---|
1487 | Do nothing if DECL is not external. */ |
---|
1488 | |
---|
1489 | void |
---|
1490 | assemble_external (decl) |
---|
1491 | tree decl; |
---|
1492 | { |
---|
1493 | if (output_bytecode) |
---|
1494 | return; |
---|
1495 | |
---|
1496 | #ifdef ASM_OUTPUT_EXTERNAL |
---|
1497 | if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd' |
---|
1498 | && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)) |
---|
1499 | { |
---|
1500 | rtx rtl = DECL_RTL (decl); |
---|
1501 | |
---|
1502 | if (GET_CODE (rtl) == MEM && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF |
---|
1503 | && ! SYMBOL_REF_USED (XEXP (rtl, 0))) |
---|
1504 | { |
---|
1505 | /* Some systems do require some output. */ |
---|
1506 | SYMBOL_REF_USED (XEXP (rtl, 0)) = 1; |
---|
1507 | ASM_OUTPUT_EXTERNAL (asm_out_file, decl, XSTR (XEXP (rtl, 0), 0)); |
---|
1508 | } |
---|
1509 | } |
---|
1510 | #endif |
---|
1511 | } |
---|
1512 | |
---|
1513 | /* Similar, for calling a library function FUN. */ |
---|
1514 | |
---|
1515 | void |
---|
1516 | assemble_external_libcall (fun) |
---|
1517 | rtx fun; |
---|
1518 | { |
---|
1519 | #ifdef ASM_OUTPUT_EXTERNAL_LIBCALL |
---|
1520 | if (!output_bytecode) |
---|
1521 | { |
---|
1522 | /* Declare library function name external when first used, if nec. */ |
---|
1523 | if (! SYMBOL_REF_USED (fun)) |
---|
1524 | { |
---|
1525 | SYMBOL_REF_USED (fun) = 1; |
---|
1526 | ASM_OUTPUT_EXTERNAL_LIBCALL (asm_out_file, fun); |
---|
1527 | } |
---|
1528 | } |
---|
1529 | #endif |
---|
1530 | } |
---|
1531 | |
---|
1532 | /* Declare the label NAME global. */ |
---|
1533 | |
---|
1534 | void |
---|
1535 | assemble_global (name) |
---|
1536 | char *name; |
---|
1537 | { |
---|
1538 | ASM_GLOBALIZE_LABEL (asm_out_file, name); |
---|
1539 | } |
---|
1540 | |
---|
1541 | /* Assemble a label named NAME. */ |
---|
1542 | |
---|
1543 | void |
---|
1544 | assemble_label (name) |
---|
1545 | char *name; |
---|
1546 | { |
---|
1547 | if (output_bytecode) |
---|
1548 | BC_OUTPUT_LABEL (asm_out_file, name); |
---|
1549 | else |
---|
1550 | ASM_OUTPUT_LABEL (asm_out_file, name); |
---|
1551 | } |
---|
1552 | |
---|
1553 | /* Output to FILE a reference to the assembler name of a C-level name NAME. |
---|
1554 | If NAME starts with a *, the rest of NAME is output verbatim. |
---|
1555 | Otherwise NAME is transformed in an implementation-defined way |
---|
1556 | (usually by the addition of an underscore). |
---|
1557 | Many macros in the tm file are defined to call this function. */ |
---|
1558 | |
---|
1559 | void |
---|
1560 | assemble_name (file, name) |
---|
1561 | FILE *file; |
---|
1562 | char *name; |
---|
1563 | { |
---|
1564 | char *real_name; |
---|
1565 | int save_warn_id_clash = warn_id_clash; |
---|
1566 | |
---|
1567 | STRIP_NAME_ENCODING (real_name, name); |
---|
1568 | |
---|
1569 | /* Don't warn about an identifier name length clash on this name, since |
---|
1570 | it can be a user symbol suffixed by a number. */ |
---|
1571 | warn_id_clash = 0; |
---|
1572 | TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1; |
---|
1573 | warn_id_clash = save_warn_id_clash; |
---|
1574 | |
---|
1575 | if (name[0] == '*') |
---|
1576 | { |
---|
1577 | if (output_bytecode) |
---|
1578 | bc_emit_labelref (name, 0); |
---|
1579 | else |
---|
1580 | fputs (&name[1], file); |
---|
1581 | } |
---|
1582 | else |
---|
1583 | { |
---|
1584 | if (output_bytecode) |
---|
1585 | BC_OUTPUT_LABELREF (file, name); |
---|
1586 | else |
---|
1587 | ASM_OUTPUT_LABELREF (file, name); |
---|
1588 | } |
---|
1589 | } |
---|
1590 | |
---|
1591 | /* Allocate SIZE bytes writable static space with a gensym name |
---|
1592 | and return an RTX to refer to its address. */ |
---|
1593 | |
---|
1594 | rtx |
---|
1595 | assemble_static_space (size) |
---|
1596 | int size; |
---|
1597 | { |
---|
1598 | char name[12]; |
---|
1599 | char *namestring; |
---|
1600 | rtx x; |
---|
1601 | /* Round size up to multiple of BIGGEST_ALIGNMENT bits |
---|
1602 | so that each uninitialized object starts on such a boundary. */ |
---|
1603 | int rounded = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1) |
---|
1604 | / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) |
---|
1605 | * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); |
---|
1606 | |
---|
1607 | #if 0 |
---|
1608 | if (flag_shared_data) |
---|
1609 | data_section (); |
---|
1610 | #endif |
---|
1611 | |
---|
1612 | ASM_GENERATE_INTERNAL_LABEL (name, "LF", const_labelno); |
---|
1613 | ++const_labelno; |
---|
1614 | |
---|
1615 | namestring = (char *) obstack_alloc (saveable_obstack, |
---|
1616 | strlen (name) + 2); |
---|
1617 | strcpy (namestring, name); |
---|
1618 | |
---|
1619 | if (output_bytecode) |
---|
1620 | x = bc_gen_rtx (namestring, 0, (struct bc_label *) 0); |
---|
1621 | else |
---|
1622 | x = gen_rtx (SYMBOL_REF, Pmode, namestring); |
---|
1623 | |
---|
1624 | if (output_bytecode) |
---|
1625 | { |
---|
1626 | BC_OUTPUT_LOCAL (asm_out_file, name, size, rounded); |
---|
1627 | } |
---|
1628 | else |
---|
1629 | { |
---|
1630 | #ifdef ASM_OUTPUT_ALIGNED_LOCAL |
---|
1631 | ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT); |
---|
1632 | #else |
---|
1633 | ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded); |
---|
1634 | #endif |
---|
1635 | } |
---|
1636 | return x; |
---|
1637 | } |
---|
1638 | |
---|
1639 | /* Assemble the static constant template for function entry trampolines. |
---|
1640 | This is done at most once per compilation. |
---|
1641 | Returns an RTX for the address of the template. */ |
---|
1642 | |
---|
1643 | rtx |
---|
1644 | assemble_trampoline_template () |
---|
1645 | { |
---|
1646 | char label[256]; |
---|
1647 | char *name; |
---|
1648 | int align; |
---|
1649 | |
---|
1650 | /* Shouldn't get here */ |
---|
1651 | if (output_bytecode) |
---|
1652 | abort (); |
---|
1653 | |
---|
1654 | /* By default, put trampoline templates in read-only data section. */ |
---|
1655 | |
---|
1656 | #ifdef TRAMPOLINE_SECTION |
---|
1657 | TRAMPOLINE_SECTION (); |
---|
1658 | #else |
---|
1659 | readonly_data_section (); |
---|
1660 | #endif |
---|
1661 | |
---|
1662 | /* Write the assembler code to define one. */ |
---|
1663 | align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); |
---|
1664 | if (align > 0) |
---|
1665 | ASM_OUTPUT_ALIGN (asm_out_file, align); |
---|
1666 | |
---|
1667 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LTRAMP", 0); |
---|
1668 | TRAMPOLINE_TEMPLATE (asm_out_file); |
---|
1669 | |
---|
1670 | /* Record the rtl to refer to it. */ |
---|
1671 | ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0); |
---|
1672 | name |
---|
1673 | = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label)); |
---|
1674 | return gen_rtx (SYMBOL_REF, Pmode, name); |
---|
1675 | } |
---|
1676 | |
---|
1677 | /* Assemble the integer constant X into an object of SIZE bytes. |
---|
1678 | X must be either a CONST_INT or CONST_DOUBLE. |
---|
1679 | |
---|
1680 | Return 1 if we were able to output the constant, otherwise 0. If FORCE is |
---|
1681 | non-zero, abort if we can't output the constant. */ |
---|
1682 | |
---|
1683 | int |
---|
1684 | assemble_integer (x, size, force) |
---|
1685 | rtx x; |
---|
1686 | int size; |
---|
1687 | int force; |
---|
1688 | { |
---|
1689 | /* First try to use the standard 1, 2, 4, 8, and 16 byte |
---|
1690 | ASM_OUTPUT... macros. */ |
---|
1691 | |
---|
1692 | switch (size) |
---|
1693 | { |
---|
1694 | #ifdef ASM_OUTPUT_CHAR |
---|
1695 | case 1: |
---|
1696 | ASM_OUTPUT_CHAR (asm_out_file, x); |
---|
1697 | return 1; |
---|
1698 | #endif |
---|
1699 | |
---|
1700 | #ifdef ASM_OUTPUT_SHORT |
---|
1701 | case 2: |
---|
1702 | ASM_OUTPUT_SHORT (asm_out_file, x); |
---|
1703 | return 1; |
---|
1704 | #endif |
---|
1705 | |
---|
1706 | #ifdef ASM_OUTPUT_INT |
---|
1707 | case 4: |
---|
1708 | ASM_OUTPUT_INT (asm_out_file, x); |
---|
1709 | return 1; |
---|
1710 | #endif |
---|
1711 | |
---|
1712 | #ifdef ASM_OUTPUT_DOUBLE_INT |
---|
1713 | case 8: |
---|
1714 | ASM_OUTPUT_DOUBLE_INT (asm_out_file, x); |
---|
1715 | return 1; |
---|
1716 | #endif |
---|
1717 | |
---|
1718 | #ifdef ASM_OUTPUT_QUADRUPLE_INT |
---|
1719 | case 16: |
---|
1720 | ASM_OUTPUT_QUADRUPLE_INT (asm_out_file, x); |
---|
1721 | return 1; |
---|
1722 | #endif |
---|
1723 | } |
---|
1724 | |
---|
1725 | /* If we couldn't do it that way, there are two other possibilities: First, |
---|
1726 | if the machine can output an explicit byte and this is a 1 byte constant, |
---|
1727 | we can use ASM_OUTPUT_BYTE. */ |
---|
1728 | |
---|
1729 | #ifdef ASM_OUTPUT_BYTE |
---|
1730 | if (size == 1 && GET_CODE (x) == CONST_INT) |
---|
1731 | { |
---|
1732 | ASM_OUTPUT_BYTE (asm_out_file, INTVAL (x)); |
---|
1733 | return 1; |
---|
1734 | } |
---|
1735 | #endif |
---|
1736 | |
---|
1737 | /* Finally, if SIZE is larger than a single word, try to output the constant |
---|
1738 | one word at a time. */ |
---|
1739 | |
---|
1740 | if (size > UNITS_PER_WORD) |
---|
1741 | { |
---|
1742 | int i; |
---|
1743 | enum machine_mode mode |
---|
1744 | = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); |
---|
1745 | rtx word; |
---|
1746 | |
---|
1747 | for (i = 0; i < size / UNITS_PER_WORD; i++) |
---|
1748 | { |
---|
1749 | word = operand_subword (x, i, 0, mode); |
---|
1750 | |
---|
1751 | if (word == 0) |
---|
1752 | break; |
---|
1753 | |
---|
1754 | if (! assemble_integer (word, UNITS_PER_WORD, 0)) |
---|
1755 | break; |
---|
1756 | } |
---|
1757 | |
---|
1758 | if (i == size / UNITS_PER_WORD) |
---|
1759 | return 1; |
---|
1760 | /* If we output at least one word and then could not finish, |
---|
1761 | there is no valid way to continue. */ |
---|
1762 | if (i > 0) |
---|
1763 | abort (); |
---|
1764 | } |
---|
1765 | |
---|
1766 | if (force) |
---|
1767 | abort (); |
---|
1768 | |
---|
1769 | return 0; |
---|
1770 | } |
---|
1771 | |
---|
1772 | /* Assemble the floating-point constant D into an object of size MODE. */ |
---|
1773 | |
---|
1774 | void |
---|
1775 | assemble_real (d, mode) |
---|
1776 | REAL_VALUE_TYPE d; |
---|
1777 | enum machine_mode mode; |
---|
1778 | { |
---|
1779 | jmp_buf output_constant_handler; |
---|
1780 | |
---|
1781 | if (setjmp (output_constant_handler)) |
---|
1782 | { |
---|
1783 | error ("floating point trap outputting a constant"); |
---|
1784 | #ifdef REAL_IS_NOT_DOUBLE |
---|
1785 | bzero ((char *) &d, sizeof d); |
---|
1786 | d = dconst0; |
---|
1787 | #else |
---|
1788 | d = 0; |
---|
1789 | #endif |
---|
1790 | } |
---|
1791 | |
---|
1792 | set_float_handler (output_constant_handler); |
---|
1793 | |
---|
1794 | switch (mode) |
---|
1795 | { |
---|
1796 | #ifdef ASM_OUTPUT_BYTE_FLOAT |
---|
1797 | case QFmode: |
---|
1798 | ASM_OUTPUT_BYTE_FLOAT (asm_out_file, d); |
---|
1799 | break; |
---|
1800 | #endif |
---|
1801 | #ifdef ASM_OUTPUT_SHORT_FLOAT |
---|
1802 | case HFmode: |
---|
1803 | ASM_OUTPUT_SHORT_FLOAT (asm_out_file, d); |
---|
1804 | break; |
---|
1805 | #endif |
---|
1806 | #ifdef ASM_OUTPUT_THREE_QUARTER_FLOAT |
---|
1807 | case TQFmode: |
---|
1808 | ASM_OUTPUT_THREE_QUARTER_FLOAT (asm_out_file, d); |
---|
1809 | break; |
---|
1810 | #endif |
---|
1811 | #ifdef ASM_OUTPUT_FLOAT |
---|
1812 | case SFmode: |
---|
1813 | ASM_OUTPUT_FLOAT (asm_out_file, d); |
---|
1814 | break; |
---|
1815 | #endif |
---|
1816 | |
---|
1817 | #ifdef ASM_OUTPUT_DOUBLE |
---|
1818 | case DFmode: |
---|
1819 | ASM_OUTPUT_DOUBLE (asm_out_file, d); |
---|
1820 | break; |
---|
1821 | #endif |
---|
1822 | |
---|
1823 | #ifdef ASM_OUTPUT_LONG_DOUBLE |
---|
1824 | case XFmode: |
---|
1825 | case TFmode: |
---|
1826 | ASM_OUTPUT_LONG_DOUBLE (asm_out_file, d); |
---|
1827 | break; |
---|
1828 | #endif |
---|
1829 | |
---|
1830 | default: |
---|
1831 | abort (); |
---|
1832 | } |
---|
1833 | |
---|
1834 | set_float_handler (NULL_PTR); |
---|
1835 | } |
---|
1836 | |
---|
1837 | /* Here we combine duplicate floating constants to make |
---|
1838 | CONST_DOUBLE rtx's, and force those out to memory when necessary. */ |
---|
1839 | |
---|
1840 | /* Chain of all CONST_DOUBLE rtx's constructed for the current function. |
---|
1841 | They are chained through the CONST_DOUBLE_CHAIN. |
---|
1842 | A CONST_DOUBLE rtx has CONST_DOUBLE_MEM != cc0_rtx iff it is on this chain. |
---|
1843 | In that case, CONST_DOUBLE_MEM is either a MEM, |
---|
1844 | or const0_rtx if no MEM has been made for this CONST_DOUBLE yet. |
---|
1845 | |
---|
1846 | (CONST_DOUBLE_MEM is used only for top-level functions. |
---|
1847 | See force_const_mem for explanation.) */ |
---|
1848 | |
---|
1849 | static rtx const_double_chain; |
---|
1850 | |
---|
1851 | /* Return a CONST_DOUBLE or CONST_INT for a value specified as a pair of ints. |
---|
1852 | For an integer, I0 is the low-order word and I1 is the high-order word. |
---|
1853 | For a real number, I0 is the word with the low address |
---|
1854 | and I1 is the word with the high address. */ |
---|
1855 | |
---|
1856 | rtx |
---|
1857 | immed_double_const (i0, i1, mode) |
---|
1858 | HOST_WIDE_INT i0, i1; |
---|
1859 | enum machine_mode mode; |
---|
1860 | { |
---|
1861 | register rtx r; |
---|
1862 | int in_current_obstack; |
---|
1863 | |
---|
1864 | if (GET_MODE_CLASS (mode) == MODE_INT |
---|
1865 | || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) |
---|
1866 | { |
---|
1867 | /* We clear out all bits that don't belong in MODE, unless they and our |
---|
1868 | sign bit are all one. So we get either a reasonable negative value |
---|
1869 | or a reasonable unsigned value for this mode. */ |
---|
1870 | int width = GET_MODE_BITSIZE (mode); |
---|
1871 | if (width < HOST_BITS_PER_WIDE_INT |
---|
1872 | && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1))) |
---|
1873 | != ((HOST_WIDE_INT) (-1) << (width - 1)))) |
---|
1874 | i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0; |
---|
1875 | else if (width == HOST_BITS_PER_WIDE_INT |
---|
1876 | && ! (i1 == ~0 && i0 < 0)) |
---|
1877 | i1 = 0; |
---|
1878 | else if (width > 2 * HOST_BITS_PER_WIDE_INT) |
---|
1879 | /* We cannot represent this value as a constant. */ |
---|
1880 | abort (); |
---|
1881 | |
---|
1882 | /* If this would be an entire word for the target, but is not for |
---|
1883 | the host, then sign-extend on the host so that the number will look |
---|
1884 | the same way on the host that it would on the target. |
---|
1885 | |
---|
1886 | For example, when building a 64 bit alpha hosted 32 bit sparc |
---|
1887 | targeted compiler, then we want the 32 bit unsigned value -1 to be |
---|
1888 | represented as a 64 bit value -1, and not as 0x00000000ffffffff. |
---|
1889 | The later confuses the sparc backend. */ |
---|
1890 | |
---|
1891 | if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width |
---|
1892 | && (i0 & ((HOST_WIDE_INT) 1 << (width - 1)))) |
---|
1893 | i0 |= ((HOST_WIDE_INT) (-1) << width); |
---|
1894 | |
---|
1895 | /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a CONST_INT. |
---|
1896 | |
---|
1897 | ??? Strictly speaking, this is wrong if we create a CONST_INT |
---|
1898 | for a large unsigned constant with the size of MODE being |
---|
1899 | HOST_BITS_PER_WIDE_INT and later try to interpret that constant in a |
---|
1900 | wider mode. In that case we will mis-interpret it as a negative |
---|
1901 | number. |
---|
1902 | |
---|
1903 | Unfortunately, the only alternative is to make a CONST_DOUBLE |
---|
1904 | for any constant in any mode if it is an unsigned constant larger |
---|
1905 | than the maximum signed integer in an int on the host. However, |
---|
1906 | doing this will break everyone that always expects to see a CONST_INT |
---|
1907 | for SImode and smaller. |
---|
1908 | |
---|
1909 | We have always been making CONST_INTs in this case, so nothing new |
---|
1910 | is being broken. */ |
---|
1911 | |
---|
1912 | if (width <= HOST_BITS_PER_WIDE_INT) |
---|
1913 | i1 = (i0 < 0) ? ~0 : 0; |
---|
1914 | |
---|
1915 | /* If this integer fits in one word, return a CONST_INT. */ |
---|
1916 | if ((i1 == 0 && i0 >= 0) |
---|
1917 | || (i1 == ~0 && i0 < 0)) |
---|
1918 | return GEN_INT (i0); |
---|
1919 | |
---|
1920 | /* We use VOIDmode for integers. */ |
---|
1921 | mode = VOIDmode; |
---|
1922 | } |
---|
1923 | |
---|
1924 | /* Search the chain for an existing CONST_DOUBLE with the right value. |
---|
1925 | If one is found, return it. */ |
---|
1926 | |
---|
1927 | for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r)) |
---|
1928 | if (CONST_DOUBLE_LOW (r) == i0 && CONST_DOUBLE_HIGH (r) == i1 |
---|
1929 | && GET_MODE (r) == mode) |
---|
1930 | return r; |
---|
1931 | |
---|
1932 | /* No; make a new one and add it to the chain. |
---|
1933 | |
---|
1934 | We may be called by an optimizer which may be discarding any memory |
---|
1935 | allocated during its processing (such as combine and loop). However, |
---|
1936 | we will be leaving this constant on the chain, so we cannot tolerate |
---|
1937 | freed memory. So switch to saveable_obstack for this allocation |
---|
1938 | and then switch back if we were in current_obstack. */ |
---|
1939 | |
---|
1940 | push_obstacks_nochange (); |
---|
1941 | rtl_in_saveable_obstack (); |
---|
1942 | r = gen_rtx (CONST_DOUBLE, mode, 0, i0, i1); |
---|
1943 | pop_obstacks (); |
---|
1944 | |
---|
1945 | /* Don't touch const_double_chain in nested function; see force_const_mem. |
---|
1946 | Also, don't touch it if not inside any function. */ |
---|
1947 | if (outer_function_chain == 0 && current_function_decl != 0) |
---|
1948 | { |
---|
1949 | CONST_DOUBLE_CHAIN (r) = const_double_chain; |
---|
1950 | const_double_chain = r; |
---|
1951 | } |
---|
1952 | |
---|
1953 | /* Store const0_rtx in mem-slot since this CONST_DOUBLE is on the chain. |
---|
1954 | Actual use of mem-slot is only through force_const_mem. */ |
---|
1955 | |
---|
1956 | CONST_DOUBLE_MEM (r) = const0_rtx; |
---|
1957 | |
---|
1958 | return r; |
---|
1959 | } |
---|
1960 | |
---|
1961 | /* Return a CONST_DOUBLE for a specified `double' value |
---|
1962 | and machine mode. */ |
---|
1963 | |
---|
1964 | rtx |
---|
1965 | immed_real_const_1 (d, mode) |
---|
1966 | REAL_VALUE_TYPE d; |
---|
1967 | enum machine_mode mode; |
---|
1968 | { |
---|
1969 | union real_extract u; |
---|
1970 | register rtx r; |
---|
1971 | int in_current_obstack; |
---|
1972 | |
---|
1973 | /* Get the desired `double' value as a sequence of ints |
---|
1974 | since that is how they are stored in a CONST_DOUBLE. */ |
---|
1975 | |
---|
1976 | u.d = d; |
---|
1977 | |
---|
1978 | /* Detect special cases. */ |
---|
1979 | |
---|
1980 | /* Avoid REAL_VALUES_EQUAL here in order to distinguish minus zero. */ |
---|
1981 | if (!bcmp ((char *) &dconst0, (char *) &d, sizeof d)) |
---|
1982 | return CONST0_RTX (mode); |
---|
1983 | /* Check for NaN first, because some ports (specifically the i386) do not |
---|
1984 | emit correct ieee-fp code by default, and thus will generate a core |
---|
1985 | dump here if we pass a NaN to REAL_VALUES_EQUAL and if REAL_VALUES_EQUAL |
---|
1986 | does a floating point comparison. */ |
---|
1987 | else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d)) |
---|
1988 | return CONST1_RTX (mode); |
---|
1989 | |
---|
1990 | if (sizeof u == 2 * sizeof (HOST_WIDE_INT)) |
---|
1991 | return immed_double_const (u.i[0], u.i[1], mode); |
---|
1992 | |
---|
1993 | /* The rest of this function handles the case where |
---|
1994 | a float value requires more than 2 ints of space. |
---|
1995 | It will be deleted as dead code on machines that don't need it. */ |
---|
1996 | |
---|
1997 | /* Search the chain for an existing CONST_DOUBLE with the right value. |
---|
1998 | If one is found, return it. */ |
---|
1999 | |
---|
2000 | for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r)) |
---|
2001 | if (! bcmp ((char *) &CONST_DOUBLE_LOW (r), (char *) &u, sizeof u) |
---|
2002 | && GET_MODE (r) == mode) |
---|
2003 | return r; |
---|
2004 | |
---|
2005 | /* No; make a new one and add it to the chain. |
---|
2006 | |
---|
2007 | We may be called by an optimizer which may be discarding any memory |
---|
2008 | allocated during its processing (such as combine and loop). However, |
---|
2009 | we will be leaving this constant on the chain, so we cannot tolerate |
---|
2010 | freed memory. So switch to saveable_obstack for this allocation |
---|
2011 | and then switch back if we were in current_obstack. */ |
---|
2012 | |
---|
2013 | push_obstacks_nochange (); |
---|
2014 | rtl_in_saveable_obstack (); |
---|
2015 | r = rtx_alloc (CONST_DOUBLE); |
---|
2016 | PUT_MODE (r, mode); |
---|
2017 | bcopy ((char *) &u, (char *) &CONST_DOUBLE_LOW (r), sizeof u); |
---|
2018 | pop_obstacks (); |
---|
2019 | |
---|
2020 | /* Don't touch const_double_chain in nested function; see force_const_mem. |
---|
2021 | Also, don't touch it if not inside any function. */ |
---|
2022 | if (outer_function_chain == 0 && current_function_decl != 0) |
---|
2023 | { |
---|
2024 | CONST_DOUBLE_CHAIN (r) = const_double_chain; |
---|
2025 | const_double_chain = r; |
---|
2026 | } |
---|
2027 | |
---|
2028 | /* Store const0_rtx in CONST_DOUBLE_MEM since this CONST_DOUBLE is on the |
---|
2029 | chain, but has not been allocated memory. Actual use of CONST_DOUBLE_MEM |
---|
2030 | is only through force_const_mem. */ |
---|
2031 | |
---|
2032 | CONST_DOUBLE_MEM (r) = const0_rtx; |
---|
2033 | |
---|
2034 | return r; |
---|
2035 | } |
---|
2036 | |
---|
2037 | /* Return a CONST_DOUBLE rtx for a value specified by EXP, |
---|
2038 | which must be a REAL_CST tree node. */ |
---|
2039 | |
---|
2040 | rtx |
---|
2041 | immed_real_const (exp) |
---|
2042 | tree exp; |
---|
2043 | { |
---|
2044 | return immed_real_const_1 (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp))); |
---|
2045 | } |
---|
2046 | |
---|
2047 | /* At the end of a function, forget the memory-constants |
---|
2048 | previously made for CONST_DOUBLEs. Mark them as not on real_constant_chain. |
---|
2049 | Also clear out real_constant_chain and clear out all the chain-pointers. */ |
---|
2050 | |
---|
2051 | void |
---|
2052 | clear_const_double_mem () |
---|
2053 | { |
---|
2054 | register rtx r, next; |
---|
2055 | |
---|
2056 | /* Don't touch CONST_DOUBLE_MEM for nested functions. |
---|
2057 | See force_const_mem for explanation. */ |
---|
2058 | if (outer_function_chain != 0) |
---|
2059 | return; |
---|
2060 | |
---|
2061 | for (r = const_double_chain; r; r = next) |
---|
2062 | { |
---|
2063 | next = CONST_DOUBLE_CHAIN (r); |
---|
2064 | CONST_DOUBLE_CHAIN (r) = 0; |
---|
2065 | CONST_DOUBLE_MEM (r) = cc0_rtx; |
---|
2066 | } |
---|
2067 | const_double_chain = 0; |
---|
2068 | } |
---|
2069 | |
---|
2070 | /* Given an expression EXP with a constant value, |
---|
2071 | reduce it to the sum of an assembler symbol and an integer. |
---|
2072 | Store them both in the structure *VALUE. |
---|
2073 | Abort if EXP does not reduce. */ |
---|
2074 | |
---|
2075 | struct addr_const |
---|
2076 | { |
---|
2077 | rtx base; |
---|
2078 | HOST_WIDE_INT offset; |
---|
2079 | }; |
---|
2080 | |
---|
2081 | static void |
---|
2082 | decode_addr_const (exp, value) |
---|
2083 | tree exp; |
---|
2084 | struct addr_const *value; |
---|
2085 | { |
---|
2086 | register tree target = TREE_OPERAND (exp, 0); |
---|
2087 | register int offset = 0; |
---|
2088 | register rtx x; |
---|
2089 | |
---|
2090 | while (1) |
---|
2091 | { |
---|
2092 | if (TREE_CODE (target) == COMPONENT_REF |
---|
2093 | && (TREE_CODE (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1))) |
---|
2094 | == INTEGER_CST)) |
---|
2095 | { |
---|
2096 | offset += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1))) / BITS_PER_UNIT; |
---|
2097 | target = TREE_OPERAND (target, 0); |
---|
2098 | } |
---|
2099 | else if (TREE_CODE (target) == ARRAY_REF) |
---|
2100 | { |
---|
2101 | if (TREE_CODE (TREE_OPERAND (target, 1)) != INTEGER_CST |
---|
2102 | || TREE_CODE (TYPE_SIZE (TREE_TYPE (target))) != INTEGER_CST) |
---|
2103 | abort (); |
---|
2104 | offset += ((TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (target))) |
---|
2105 | * TREE_INT_CST_LOW (TREE_OPERAND (target, 1))) |
---|
2106 | / BITS_PER_UNIT); |
---|
2107 | target = TREE_OPERAND (target, 0); |
---|
2108 | } |
---|
2109 | else |
---|
2110 | break; |
---|
2111 | } |
---|
2112 | |
---|
2113 | switch (TREE_CODE (target)) |
---|
2114 | { |
---|
2115 | case VAR_DECL: |
---|
2116 | case FUNCTION_DECL: |
---|
2117 | x = DECL_RTL (target); |
---|
2118 | break; |
---|
2119 | |
---|
2120 | case LABEL_DECL: |
---|
2121 | if (output_bytecode) |
---|
2122 | /* FIXME: this may not be correct, check it */ |
---|
2123 | x = bc_gen_rtx (TREE_STRING_POINTER (target), 0, (struct bc_label *) 0); |
---|
2124 | else |
---|
2125 | x = gen_rtx (MEM, FUNCTION_MODE, |
---|
2126 | gen_rtx (LABEL_REF, VOIDmode, |
---|
2127 | label_rtx (TREE_OPERAND (exp, 0)))); |
---|
2128 | break; |
---|
2129 | |
---|
2130 | case REAL_CST: |
---|
2131 | case STRING_CST: |
---|
2132 | case COMPLEX_CST: |
---|
2133 | case CONSTRUCTOR: |
---|
2134 | x = TREE_CST_RTL (target); |
---|
2135 | break; |
---|
2136 | |
---|
2137 | default: |
---|
2138 | abort (); |
---|
2139 | } |
---|
2140 | |
---|
2141 | if (!output_bytecode) |
---|
2142 | { |
---|
2143 | if (GET_CODE (x) != MEM) |
---|
2144 | abort (); |
---|
2145 | x = XEXP (x, 0); |
---|
2146 | } |
---|
2147 | |
---|
2148 | value->base = x; |
---|
2149 | value->offset = offset; |
---|
2150 | } |
---|
2151 | |
---|
2152 | /* Uniquize all constants that appear in memory. |
---|
2153 | Each constant in memory thus far output is recorded |
---|
2154 | in `const_hash_table' with a `struct constant_descriptor' |
---|
2155 | that contains a polish representation of the value of |
---|
2156 | the constant. |
---|
2157 | |
---|
2158 | We cannot store the trees in the hash table |
---|
2159 | because the trees may be temporary. */ |
---|
2160 | |
---|
2161 | struct constant_descriptor |
---|
2162 | { |
---|
2163 | struct constant_descriptor *next; |
---|
2164 | char *label; |
---|
2165 | char contents[1]; |
---|
2166 | }; |
---|
2167 | |
---|
2168 | #define HASHBITS 30 |
---|
2169 | #define MAX_HASH_TABLE 1009 |
---|
2170 | static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE]; |
---|
2171 | |
---|
2172 | /* Compute a hash code for a constant expression. */ |
---|
2173 | |
---|
2174 | static int |
---|
2175 | const_hash (exp) |
---|
2176 | tree exp; |
---|
2177 | { |
---|
2178 | register char *p; |
---|
2179 | register int len, hi, i; |
---|
2180 | register enum tree_code code = TREE_CODE (exp); |
---|
2181 | |
---|
2182 | if (code == INTEGER_CST) |
---|
2183 | { |
---|
2184 | p = (char *) &TREE_INT_CST_LOW (exp); |
---|
2185 | len = 2 * sizeof TREE_INT_CST_LOW (exp); |
---|
2186 | } |
---|
2187 | else if (code == REAL_CST) |
---|
2188 | { |
---|
2189 | p = (char *) &TREE_REAL_CST (exp); |
---|
2190 | len = sizeof TREE_REAL_CST (exp); |
---|
2191 | } |
---|
2192 | else if (code == STRING_CST) |
---|
2193 | p = TREE_STRING_POINTER (exp), len = TREE_STRING_LENGTH (exp); |
---|
2194 | else if (code == COMPLEX_CST) |
---|
2195 | return const_hash (TREE_REALPART (exp)) * 5 |
---|
2196 | + const_hash (TREE_IMAGPART (exp)); |
---|
2197 | else if (code == CONSTRUCTOR && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) |
---|
2198 | { |
---|
2199 | len = int_size_in_bytes (TREE_TYPE (exp)); |
---|
2200 | p = (char*) alloca (len); |
---|
2201 | get_set_constructor_bytes (exp, (unsigned char *) p, len); |
---|
2202 | } |
---|
2203 | else if (code == CONSTRUCTOR) |
---|
2204 | { |
---|
2205 | register tree link; |
---|
2206 | |
---|
2207 | /* For record type, include the type in the hashing. |
---|
2208 | We do not do so for array types |
---|
2209 | because (1) the sizes of the elements are sufficient |
---|
2210 | and (2) distinct array types can have the same constructor. |
---|
2211 | Instead, we include the array size because the constructor could |
---|
2212 | be shorter. */ |
---|
2213 | if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) |
---|
2214 | hi = ((HOST_WIDE_INT) TREE_TYPE (exp) & ((1 << HASHBITS) - 1)) |
---|
2215 | % MAX_HASH_TABLE; |
---|
2216 | else |
---|
2217 | hi = ((5 + int_size_in_bytes (TREE_TYPE (exp))) |
---|
2218 | & ((1 << HASHBITS) - 1)) % MAX_HASH_TABLE; |
---|
2219 | |
---|
2220 | for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) |
---|
2221 | if (TREE_VALUE (link)) |
---|
2222 | hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE; |
---|
2223 | |
---|
2224 | return hi; |
---|
2225 | } |
---|
2226 | else if (code == ADDR_EXPR) |
---|
2227 | { |
---|
2228 | struct addr_const value; |
---|
2229 | decode_addr_const (exp, &value); |
---|
2230 | if (GET_CODE (value.base) == SYMBOL_REF) |
---|
2231 | { |
---|
2232 | /* Don't hash the address of the SYMBOL_REF; |
---|
2233 | only use the offset and the symbol name. */ |
---|
2234 | hi = value.offset; |
---|
2235 | p = XSTR (value.base, 0); |
---|
2236 | for (i = 0; p[i] != 0; i++) |
---|
2237 | hi = ((hi * 613) + (unsigned)(p[i])); |
---|
2238 | } |
---|
2239 | else if (GET_CODE (value.base) == LABEL_REF) |
---|
2240 | hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13; |
---|
2241 | |
---|
2242 | hi &= (1 << HASHBITS) - 1; |
---|
2243 | hi %= MAX_HASH_TABLE; |
---|
2244 | return hi; |
---|
2245 | } |
---|
2246 | else if (code == PLUS_EXPR || code == MINUS_EXPR) |
---|
2247 | return const_hash (TREE_OPERAND (exp, 0)) * 9 |
---|
2248 | + const_hash (TREE_OPERAND (exp, 1)); |
---|
2249 | else if (code == NOP_EXPR || code == CONVERT_EXPR) |
---|
2250 | return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2; |
---|
2251 | |
---|
2252 | /* Compute hashing function */ |
---|
2253 | hi = len; |
---|
2254 | for (i = 0; i < len; i++) |
---|
2255 | hi = ((hi * 613) + (unsigned)(p[i])); |
---|
2256 | |
---|
2257 | hi &= (1 << HASHBITS) - 1; |
---|
2258 | hi %= MAX_HASH_TABLE; |
---|
2259 | return hi; |
---|
2260 | } |
---|
2261 | |
---|
2262 | /* Compare a constant expression EXP with a constant-descriptor DESC. |
---|
2263 | Return 1 if DESC describes a constant with the same value as EXP. */ |
---|
2264 | |
---|
2265 | static int |
---|
2266 | compare_constant (exp, desc) |
---|
2267 | tree exp; |
---|
2268 | struct constant_descriptor *desc; |
---|
2269 | { |
---|
2270 | return 0 != compare_constant_1 (exp, desc->contents); |
---|
2271 | } |
---|
2272 | |
---|
2273 | /* Compare constant expression EXP with a substring P of a constant descriptor. |
---|
2274 | If they match, return a pointer to the end of the substring matched. |
---|
2275 | If they do not match, return 0. |
---|
2276 | |
---|
2277 | Since descriptors are written in polish prefix notation, |
---|
2278 | this function can be used recursively to test one operand of EXP |
---|
2279 | against a subdescriptor, and if it succeeds it returns the |
---|
2280 | address of the subdescriptor for the next operand. */ |
---|
2281 | |
---|
2282 | static char * |
---|
2283 | compare_constant_1 (exp, p) |
---|
2284 | tree exp; |
---|
2285 | char *p; |
---|
2286 | { |
---|
2287 | register char *strp; |
---|
2288 | register int len; |
---|
2289 | register enum tree_code code = TREE_CODE (exp); |
---|
2290 | |
---|
2291 | if (code != (enum tree_code) *p++) |
---|
2292 | return 0; |
---|
2293 | |
---|
2294 | if (code == INTEGER_CST) |
---|
2295 | { |
---|
2296 | /* Integer constants are the same only if the same width of type. */ |
---|
2297 | if (*p++ != TYPE_PRECISION (TREE_TYPE (exp))) |
---|
2298 | return 0; |
---|
2299 | strp = (char *) &TREE_INT_CST_LOW (exp); |
---|
2300 | len = 2 * sizeof TREE_INT_CST_LOW (exp); |
---|
2301 | } |
---|
2302 | else if (code == REAL_CST) |
---|
2303 | { |
---|
2304 | /* Real constants are the same only if the same width of type. */ |
---|
2305 | if (*p++ != TYPE_PRECISION (TREE_TYPE (exp))) |
---|
2306 | return 0; |
---|
2307 | strp = (char *) &TREE_REAL_CST (exp); |
---|
2308 | len = sizeof TREE_REAL_CST (exp); |
---|
2309 | } |
---|
2310 | else if (code == STRING_CST) |
---|
2311 | { |
---|
2312 | if (flag_writable_strings) |
---|
2313 | return 0; |
---|
2314 | strp = TREE_STRING_POINTER (exp); |
---|
2315 | len = TREE_STRING_LENGTH (exp); |
---|
2316 | if (bcmp ((char *) &TREE_STRING_LENGTH (exp), p, |
---|
2317 | sizeof TREE_STRING_LENGTH (exp))) |
---|
2318 | return 0; |
---|
2319 | p += sizeof TREE_STRING_LENGTH (exp); |
---|
2320 | } |
---|
2321 | else if (code == COMPLEX_CST) |
---|
2322 | { |
---|
2323 | p = compare_constant_1 (TREE_REALPART (exp), p); |
---|
2324 | if (p == 0) return 0; |
---|
2325 | p = compare_constant_1 (TREE_IMAGPART (exp), p); |
---|
2326 | return p; |
---|
2327 | } |
---|
2328 | else if (code == CONSTRUCTOR && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) |
---|
2329 | { |
---|
2330 | len = int_size_in_bytes (TREE_TYPE (exp)); |
---|
2331 | strp = (char*) alloca (len); |
---|
2332 | get_set_constructor_bytes (exp, (unsigned char *) strp, len); |
---|
2333 | } |
---|
2334 | else if (code == CONSTRUCTOR) |
---|
2335 | { |
---|
2336 | register tree link; |
---|
2337 | int length = list_length (CONSTRUCTOR_ELTS (exp)); |
---|
2338 | tree type; |
---|
2339 | |
---|
2340 | if (bcmp ((char *) &length, p, sizeof length)) |
---|
2341 | return 0; |
---|
2342 | p += sizeof length; |
---|
2343 | |
---|
2344 | /* For record constructors, insist that the types match. |
---|
2345 | For arrays, just verify both constructors are for arrays. */ |
---|
2346 | if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) |
---|
2347 | type = TREE_TYPE (exp); |
---|
2348 | else |
---|
2349 | type = 0; |
---|
2350 | if (bcmp ((char *) &type, p, sizeof type)) |
---|
2351 | return 0; |
---|
2352 | p += sizeof type; |
---|
2353 | |
---|
2354 | /* For arrays, insist that the size in bytes match. */ |
---|
2355 | if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) |
---|
2356 | { |
---|
2357 | int size = int_size_in_bytes (TREE_TYPE (exp)); |
---|
2358 | if (bcmp ((char *) &size, p, sizeof size)) |
---|
2359 | return 0; |
---|
2360 | p += sizeof size; |
---|
2361 | } |
---|
2362 | |
---|
2363 | for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) |
---|
2364 | { |
---|
2365 | if (TREE_VALUE (link)) |
---|
2366 | { |
---|
2367 | if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0) |
---|
2368 | return 0; |
---|
2369 | } |
---|
2370 | else |
---|
2371 | { |
---|
2372 | tree zero = 0; |
---|
2373 | |
---|
2374 | if (bcmp ((char *) &zero, p, sizeof zero)) |
---|
2375 | return 0; |
---|
2376 | p += sizeof zero; |
---|
2377 | } |
---|
2378 | } |
---|
2379 | |
---|
2380 | return p; |
---|
2381 | } |
---|
2382 | else if (code == ADDR_EXPR) |
---|
2383 | { |
---|
2384 | struct addr_const value; |
---|
2385 | decode_addr_const (exp, &value); |
---|
2386 | strp = (char *) &value.offset; |
---|
2387 | len = sizeof value.offset; |
---|
2388 | /* Compare the offset. */ |
---|
2389 | while (--len >= 0) |
---|
2390 | if (*p++ != *strp++) |
---|
2391 | return 0; |
---|
2392 | /* Compare symbol name. */ |
---|
2393 | strp = XSTR (value.base, 0); |
---|
2394 | len = strlen (strp) + 1; |
---|
2395 | } |
---|
2396 | else if (code == PLUS_EXPR || code == MINUS_EXPR) |
---|
2397 | { |
---|
2398 | p = compare_constant_1 (TREE_OPERAND (exp, 0), p); |
---|
2399 | if (p == 0) return 0; |
---|
2400 | p = compare_constant_1 (TREE_OPERAND (exp, 1), p); |
---|
2401 | return p; |
---|
2402 | } |
---|
2403 | else if (code == NOP_EXPR || code == CONVERT_EXPR) |
---|
2404 | { |
---|
2405 | p = compare_constant_1 (TREE_OPERAND (exp, 0), p); |
---|
2406 | return p; |
---|
2407 | } |
---|
2408 | |
---|
2409 | /* Compare constant contents. */ |
---|
2410 | while (--len >= 0) |
---|
2411 | if (*p++ != *strp++) |
---|
2412 | return 0; |
---|
2413 | |
---|
2414 | return p; |
---|
2415 | } |
---|
2416 | |
---|
2417 | /* Construct a constant descriptor for the expression EXP. |
---|
2418 | It is up to the caller to enter the descriptor in the hash table. */ |
---|
2419 | |
---|
2420 | static struct constant_descriptor * |
---|
2421 | record_constant (exp) |
---|
2422 | tree exp; |
---|
2423 | { |
---|
2424 | struct constant_descriptor *next = 0; |
---|
2425 | char *label = 0; |
---|
2426 | |
---|
2427 | /* Make a struct constant_descriptor. The first two pointers will |
---|
2428 | be filled in later. Here we just leave space for them. */ |
---|
2429 | |
---|
2430 | obstack_grow (&permanent_obstack, (char *) &next, sizeof next); |
---|
2431 | obstack_grow (&permanent_obstack, (char *) &label, sizeof label); |
---|
2432 | record_constant_1 (exp); |
---|
2433 | return (struct constant_descriptor *) obstack_finish (&permanent_obstack); |
---|
2434 | } |
---|
2435 | |
---|
2436 | /* Add a description of constant expression EXP |
---|
2437 | to the object growing in `permanent_obstack'. |
---|
2438 | No need to return its address; the caller will get that |
---|
2439 | from the obstack when the object is complete. */ |
---|
2440 | |
---|
2441 | static void |
---|
2442 | record_constant_1 (exp) |
---|
2443 | tree exp; |
---|
2444 | { |
---|
2445 | register char *strp; |
---|
2446 | register int len; |
---|
2447 | register enum tree_code code = TREE_CODE (exp); |
---|
2448 | |
---|
2449 | obstack_1grow (&permanent_obstack, (unsigned int) code); |
---|
2450 | |
---|
2451 | switch (code) |
---|
2452 | { |
---|
2453 | case INTEGER_CST: |
---|
2454 | obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp))); |
---|
2455 | strp = (char *) &TREE_INT_CST_LOW (exp); |
---|
2456 | len = 2 * sizeof TREE_INT_CST_LOW (exp); |
---|
2457 | break; |
---|
2458 | |
---|
2459 | case REAL_CST: |
---|
2460 | obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp))); |
---|
2461 | strp = (char *) &TREE_REAL_CST (exp); |
---|
2462 | len = sizeof TREE_REAL_CST (exp); |
---|
2463 | break; |
---|
2464 | |
---|
2465 | case STRING_CST: |
---|
2466 | if (flag_writable_strings) |
---|
2467 | return; |
---|
2468 | |
---|
2469 | strp = TREE_STRING_POINTER (exp); |
---|
2470 | len = TREE_STRING_LENGTH (exp); |
---|
2471 | obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp), |
---|
2472 | sizeof TREE_STRING_LENGTH (exp)); |
---|
2473 | break; |
---|
2474 | |
---|
2475 | case COMPLEX_CST: |
---|
2476 | record_constant_1 (TREE_REALPART (exp)); |
---|
2477 | record_constant_1 (TREE_IMAGPART (exp)); |
---|
2478 | return; |
---|
2479 | |
---|
2480 | case CONSTRUCTOR: |
---|
2481 | if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) |
---|
2482 | { |
---|
2483 | int nbytes = int_size_in_bytes (TREE_TYPE (exp)); |
---|
2484 | obstack_grow (&permanent_obstack, &nbytes, sizeof (nbytes)); |
---|
2485 | obstack_blank (&permanent_obstack, nbytes); |
---|
2486 | get_set_constructor_bytes |
---|
2487 | (exp, (unsigned char *) permanent_obstack.next_free, nbytes); |
---|
2488 | return; |
---|
2489 | } |
---|
2490 | else |
---|
2491 | { |
---|
2492 | register tree link; |
---|
2493 | int length = list_length (CONSTRUCTOR_ELTS (exp)); |
---|
2494 | tree type; |
---|
2495 | |
---|
2496 | obstack_grow (&permanent_obstack, (char *) &length, sizeof length); |
---|
2497 | |
---|
2498 | /* For record constructors, insist that the types match. |
---|
2499 | For arrays, just verify both constructors are for arrays. */ |
---|
2500 | if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) |
---|
2501 | type = TREE_TYPE (exp); |
---|
2502 | else |
---|
2503 | type = 0; |
---|
2504 | obstack_grow (&permanent_obstack, (char *) &type, sizeof type); |
---|
2505 | |
---|
2506 | /* For arrays, insist that the size in bytes match. */ |
---|
2507 | if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) |
---|
2508 | { |
---|
2509 | int size = int_size_in_bytes (TREE_TYPE (exp)); |
---|
2510 | obstack_grow (&permanent_obstack, (char *) &size, sizeof size); |
---|
2511 | } |
---|
2512 | |
---|
2513 | for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) |
---|
2514 | { |
---|
2515 | if (TREE_VALUE (link)) |
---|
2516 | record_constant_1 (TREE_VALUE (link)); |
---|
2517 | else |
---|
2518 | { |
---|
2519 | tree zero = 0; |
---|
2520 | |
---|
2521 | obstack_grow (&permanent_obstack, |
---|
2522 | (char *) &zero, sizeof zero); |
---|
2523 | } |
---|
2524 | } |
---|
2525 | } |
---|
2526 | return; |
---|
2527 | |
---|
2528 | case ADDR_EXPR: |
---|
2529 | { |
---|
2530 | struct addr_const value; |
---|
2531 | |
---|
2532 | decode_addr_const (exp, &value); |
---|
2533 | /* Record the offset. */ |
---|
2534 | obstack_grow (&permanent_obstack, |
---|
2535 | (char *) &value.offset, sizeof value.offset); |
---|
2536 | /* Record the symbol name. */ |
---|
2537 | obstack_grow (&permanent_obstack, XSTR (value.base, 0), |
---|
2538 | strlen (XSTR (value.base, 0)) + 1); |
---|
2539 | } |
---|
2540 | return; |
---|
2541 | |
---|
2542 | case PLUS_EXPR: |
---|
2543 | case MINUS_EXPR: |
---|
2544 | record_constant_1 (TREE_OPERAND (exp, 0)); |
---|
2545 | record_constant_1 (TREE_OPERAND (exp, 1)); |
---|
2546 | return; |
---|
2547 | |
---|
2548 | case NOP_EXPR: |
---|
2549 | case CONVERT_EXPR: |
---|
2550 | case NON_LVALUE_EXPR: |
---|
2551 | record_constant_1 (TREE_OPERAND (exp, 0)); |
---|
2552 | return; |
---|
2553 | |
---|
2554 | default: |
---|
2555 | abort (); |
---|
2556 | } |
---|
2557 | |
---|
2558 | /* Record constant contents. */ |
---|
2559 | obstack_grow (&permanent_obstack, strp, len); |
---|
2560 | } |
---|
2561 | |
---|
2562 | /* Record a list of constant expressions that were passed to |
---|
2563 | output_constant_def but that could not be output right away. */ |
---|
2564 | |
---|
2565 | struct deferred_constant |
---|
2566 | { |
---|
2567 | struct deferred_constant *next; |
---|
2568 | tree exp; |
---|
2569 | int reloc; |
---|
2570 | int labelno; |
---|
2571 | }; |
---|
2572 | |
---|
2573 | static struct deferred_constant *deferred_constants; |
---|
2574 | |
---|
2575 | /* Nonzero means defer output of addressed subconstants |
---|
2576 | (i.e., those for which output_constant_def is called.) */ |
---|
2577 | static int defer_addressed_constants_flag; |
---|
2578 | |
---|
2579 | /* Start deferring output of subconstants. */ |
---|
2580 | |
---|
2581 | void |
---|
2582 | defer_addressed_constants () |
---|
2583 | { |
---|
2584 | defer_addressed_constants_flag++; |
---|
2585 | } |
---|
2586 | |
---|
2587 | /* Stop deferring output of subconstants, |
---|
2588 | and output now all those that have been deferred. */ |
---|
2589 | |
---|
2590 | void |
---|
2591 | output_deferred_addressed_constants () |
---|
2592 | { |
---|
2593 | struct deferred_constant *p, *next; |
---|
2594 | |
---|
2595 | defer_addressed_constants_flag--; |
---|
2596 | |
---|
2597 | if (defer_addressed_constants_flag > 0) |
---|
2598 | return; |
---|
2599 | |
---|
2600 | for (p = deferred_constants; p; p = next) |
---|
2601 | { |
---|
2602 | output_constant_def_contents (p->exp, p->reloc, p->labelno); |
---|
2603 | next = p->next; |
---|
2604 | free (p); |
---|
2605 | } |
---|
2606 | |
---|
2607 | deferred_constants = 0; |
---|
2608 | } |
---|
2609 | |
---|
2610 | /* Make a copy of the whole tree structure for a constant. |
---|
2611 | This handles the same types of nodes that compare_constant |
---|
2612 | and record_constant handle. */ |
---|
2613 | |
---|
2614 | static tree |
---|
2615 | copy_constant (exp) |
---|
2616 | tree exp; |
---|
2617 | { |
---|
2618 | switch (TREE_CODE (exp)) |
---|
2619 | { |
---|
2620 | case ADDR_EXPR: |
---|
2621 | /* For ADDR_EXPR, we do not want to copy the decl whose address |
---|
2622 | is requested. We do want to copy constants though. */ |
---|
2623 | if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == 'c') |
---|
2624 | return build1 (TREE_CODE (exp), TREE_TYPE (exp), |
---|
2625 | copy_constant (TREE_OPERAND (exp, 0))); |
---|
2626 | else |
---|
2627 | return copy_node (exp); |
---|
2628 | |
---|
2629 | case INTEGER_CST: |
---|
2630 | case REAL_CST: |
---|
2631 | case STRING_CST: |
---|
2632 | return copy_node (exp); |
---|
2633 | |
---|
2634 | case COMPLEX_CST: |
---|
2635 | return build_complex (copy_constant (TREE_REALPART (exp)), |
---|
2636 | copy_constant (TREE_IMAGPART (exp))); |
---|
2637 | |
---|
2638 | case PLUS_EXPR: |
---|
2639 | case MINUS_EXPR: |
---|
2640 | return build (TREE_CODE (exp), TREE_TYPE (exp), |
---|
2641 | copy_constant (TREE_OPERAND (exp, 0)), |
---|
2642 | copy_constant (TREE_OPERAND (exp, 1))); |
---|
2643 | |
---|
2644 | case NOP_EXPR: |
---|
2645 | case CONVERT_EXPR: |
---|
2646 | return build1 (TREE_CODE (exp), TREE_TYPE (exp), |
---|
2647 | copy_constant (TREE_OPERAND (exp, 0))); |
---|
2648 | |
---|
2649 | case CONSTRUCTOR: |
---|
2650 | { |
---|
2651 | tree copy = copy_node (exp); |
---|
2652 | tree list = copy_list (CONSTRUCTOR_ELTS (exp)); |
---|
2653 | tree tail; |
---|
2654 | |
---|
2655 | CONSTRUCTOR_ELTS (copy) = list; |
---|
2656 | for (tail = list; tail; tail = TREE_CHAIN (tail)) |
---|
2657 | TREE_VALUE (tail) = copy_constant (TREE_VALUE (tail)); |
---|
2658 | if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) |
---|
2659 | for (tail = list; tail; tail = TREE_CHAIN (tail)) |
---|
2660 | TREE_PURPOSE (tail) = copy_constant (TREE_PURPOSE (tail)); |
---|
2661 | |
---|
2662 | return copy; |
---|
2663 | } |
---|
2664 | |
---|
2665 | default: |
---|
2666 | abort (); |
---|
2667 | } |
---|
2668 | } |
---|
2669 | |
---|
2670 | /* Return an rtx representing a reference to constant data in memory |
---|
2671 | for the constant expression EXP. |
---|
2672 | |
---|
2673 | If assembler code for such a constant has already been output, |
---|
2674 | return an rtx to refer to it. |
---|
2675 | Otherwise, output such a constant in memory (or defer it for later) |
---|
2676 | and generate an rtx for it. |
---|
2677 | |
---|
2678 | The TREE_CST_RTL of EXP is set up to point to that rtx. |
---|
2679 | The const_hash_table records which constants already have label strings. */ |
---|
2680 | |
---|
2681 | rtx |
---|
2682 | output_constant_def (exp) |
---|
2683 | tree exp; |
---|
2684 | { |
---|
2685 | register int hash; |
---|
2686 | register struct constant_descriptor *desc; |
---|
2687 | char label[256]; |
---|
2688 | char *found = 0; |
---|
2689 | int reloc; |
---|
2690 | register rtx def; |
---|
2691 | |
---|
2692 | if (TREE_CODE (exp) == INTEGER_CST) |
---|
2693 | abort (); /* No TREE_CST_RTL slot in these. */ |
---|
2694 | |
---|
2695 | if (TREE_CST_RTL (exp)) |
---|
2696 | return TREE_CST_RTL (exp); |
---|
2697 | |
---|
2698 | /* Make sure any other constants whose addresses appear in EXP |
---|
2699 | are assigned label numbers. */ |
---|
2700 | |
---|
2701 | reloc = output_addressed_constants (exp); |
---|
2702 | |
---|
2703 | /* Compute hash code of EXP. Search the descriptors for that hash code |
---|
2704 | to see if any of them describes EXP. If yes, the descriptor records |
---|
2705 | the label number already assigned. */ |
---|
2706 | |
---|
2707 | hash = const_hash (exp) % MAX_HASH_TABLE; |
---|
2708 | |
---|
2709 | for (desc = const_hash_table[hash]; desc; desc = desc->next) |
---|
2710 | if (compare_constant (exp, desc)) |
---|
2711 | { |
---|
2712 | found = desc->label; |
---|
2713 | break; |
---|
2714 | } |
---|
2715 | |
---|
2716 | if (found == 0) |
---|
2717 | { |
---|
2718 | /* No constant equal to EXP is known to have been output. |
---|
2719 | Make a constant descriptor to enter EXP in the hash table. |
---|
2720 | Assign the label number and record it in the descriptor for |
---|
2721 | future calls to this function to find. */ |
---|
2722 | |
---|
2723 | /* Create a string containing the label name, in LABEL. */ |
---|
2724 | ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); |
---|
2725 | |
---|
2726 | desc = record_constant (exp); |
---|
2727 | desc->next = const_hash_table[hash]; |
---|
2728 | desc->label |
---|
2729 | = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label)); |
---|
2730 | const_hash_table[hash] = desc; |
---|
2731 | } |
---|
2732 | else |
---|
2733 | { |
---|
2734 | /* Create a string containing the label name, in LABEL. */ |
---|
2735 | ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); |
---|
2736 | } |
---|
2737 | |
---|
2738 | /* We have a symbol name; construct the SYMBOL_REF and the MEM. */ |
---|
2739 | |
---|
2740 | push_obstacks_nochange (); |
---|
2741 | if (TREE_PERMANENT (exp)) |
---|
2742 | end_temporary_allocation (); |
---|
2743 | |
---|
2744 | def = gen_rtx (SYMBOL_REF, Pmode, desc->label); |
---|
2745 | |
---|
2746 | TREE_CST_RTL (exp) |
---|
2747 | = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), def); |
---|
2748 | RTX_UNCHANGING_P (TREE_CST_RTL (exp)) = 1; |
---|
2749 | if (AGGREGATE_TYPE_P (TREE_TYPE (exp))) |
---|
2750 | MEM_IN_STRUCT_P (TREE_CST_RTL (exp)) = 1; |
---|
2751 | |
---|
2752 | pop_obstacks (); |
---|
2753 | |
---|
2754 | /* Optionally set flags or add text to the name to record information |
---|
2755 | such as that it is a function name. If the name is changed, the macro |
---|
2756 | ASM_OUTPUT_LABELREF will have to know how to strip this information. */ |
---|
2757 | #ifdef ENCODE_SECTION_INFO |
---|
2758 | ENCODE_SECTION_INFO (exp); |
---|
2759 | #endif |
---|
2760 | |
---|
2761 | /* If this is the first time we've seen this particular constant, |
---|
2762 | output it (or defer its output for later). */ |
---|
2763 | if (found == 0) |
---|
2764 | { |
---|
2765 | if (defer_addressed_constants_flag) |
---|
2766 | { |
---|
2767 | struct deferred_constant *p; |
---|
2768 | p = (struct deferred_constant *) xmalloc (sizeof (struct deferred_constant)); |
---|
2769 | |
---|
2770 | push_obstacks_nochange (); |
---|
2771 | suspend_momentary (); |
---|
2772 | p->exp = copy_constant (exp); |
---|
2773 | pop_obstacks (); |
---|
2774 | p->reloc = reloc; |
---|
2775 | p->labelno = const_labelno++; |
---|
2776 | p->next = deferred_constants; |
---|
2777 | deferred_constants = p; |
---|
2778 | } |
---|
2779 | else |
---|
2780 | output_constant_def_contents (exp, reloc, const_labelno++); |
---|
2781 | } |
---|
2782 | |
---|
2783 | return TREE_CST_RTL (exp); |
---|
2784 | } |
---|
2785 | |
---|
2786 | /* Now output assembler code to define the label for EXP, |
---|
2787 | and follow it with the data of EXP. */ |
---|
2788 | |
---|
2789 | static void |
---|
2790 | output_constant_def_contents (exp, reloc, labelno) |
---|
2791 | tree exp; |
---|
2792 | int reloc; |
---|
2793 | int labelno; |
---|
2794 | { |
---|
2795 | int align; |
---|
2796 | |
---|
2797 | if (IN_NAMED_SECTION (exp)) |
---|
2798 | named_section (exp, NULL); |
---|
2799 | else |
---|
2800 | { |
---|
2801 | /* First switch to text section, except for writable strings. */ |
---|
2802 | #ifdef SELECT_SECTION |
---|
2803 | SELECT_SECTION (exp, reloc); |
---|
2804 | #else |
---|
2805 | if (((TREE_CODE (exp) == STRING_CST) && flag_writable_strings) |
---|
2806 | || (flag_pic && reloc)) |
---|
2807 | data_section (); |
---|
2808 | else |
---|
2809 | readonly_data_section (); |
---|
2810 | #endif |
---|
2811 | } |
---|
2812 | |
---|
2813 | /* Align the location counter as required by EXP's data type. */ |
---|
2814 | align = TYPE_ALIGN (TREE_TYPE (exp)); |
---|
2815 | #ifdef CONSTANT_ALIGNMENT |
---|
2816 | align = CONSTANT_ALIGNMENT (exp, align); |
---|
2817 | #endif |
---|
2818 | |
---|
2819 | if (align > BITS_PER_UNIT) |
---|
2820 | { |
---|
2821 | if (!output_bytecode) |
---|
2822 | { |
---|
2823 | ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); |
---|
2824 | } |
---|
2825 | else |
---|
2826 | { |
---|
2827 | BC_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); |
---|
2828 | } |
---|
2829 | } |
---|
2830 | |
---|
2831 | /* Output the label itself. */ |
---|
2832 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", labelno); |
---|
2833 | |
---|
2834 | /* Output the value of EXP. */ |
---|
2835 | output_constant (exp, |
---|
2836 | (TREE_CODE (exp) == STRING_CST |
---|
2837 | ? TREE_STRING_LENGTH (exp) |
---|
2838 | : int_size_in_bytes (TREE_TYPE (exp)))); |
---|
2839 | |
---|
2840 | } |
---|
2841 | |
---|
2842 | /* Similar hash facility for making memory-constants |
---|
2843 | from constant rtl-expressions. It is used on RISC machines |
---|
2844 | where immediate integer arguments and constant addresses are restricted |
---|
2845 | so that such constants must be stored in memory. |
---|
2846 | |
---|
2847 | This pool of constants is reinitialized for each function |
---|
2848 | so each function gets its own constants-pool that comes right before it. |
---|
2849 | |
---|
2850 | All structures allocated here are discarded when functions are saved for |
---|
2851 | inlining, so they do not need to be allocated permanently. */ |
---|
2852 | |
---|
2853 | #define MAX_RTX_HASH_TABLE 61 |
---|
2854 | static struct constant_descriptor **const_rtx_hash_table; |
---|
2855 | |
---|
2856 | /* Structure to represent sufficient information about a constant so that |
---|
2857 | it can be output when the constant pool is output, so that function |
---|
2858 | integration can be done, and to simplify handling on machines that reference |
---|
2859 | constant pool as base+displacement. */ |
---|
2860 | |
---|
2861 | struct pool_constant |
---|
2862 | { |
---|
2863 | struct constant_descriptor *desc; |
---|
2864 | struct pool_constant *next; |
---|
2865 | enum machine_mode mode; |
---|
2866 | rtx constant; |
---|
2867 | int labelno; |
---|
2868 | int align; |
---|
2869 | int offset; |
---|
2870 | }; |
---|
2871 | |
---|
2872 | /* Pointers to first and last constant in pool. */ |
---|
2873 | |
---|
2874 | static struct pool_constant *first_pool, *last_pool; |
---|
2875 | |
---|
2876 | /* Current offset in constant pool (does not include any machine-specific |
---|
2877 | header. */ |
---|
2878 | |
---|
2879 | static int pool_offset; |
---|
2880 | |
---|
2881 | /* Structure used to maintain hash table mapping symbols used to their |
---|
2882 | corresponding constants. */ |
---|
2883 | |
---|
2884 | struct pool_sym |
---|
2885 | { |
---|
2886 | char *label; |
---|
2887 | struct pool_constant *pool; |
---|
2888 | struct pool_sym *next; |
---|
2889 | }; |
---|
2890 | |
---|
2891 | static struct pool_sym **const_rtx_sym_hash_table; |
---|
2892 | |
---|
2893 | /* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true. |
---|
2894 | The argument is XSTR (... , 0) */ |
---|
2895 | |
---|
2896 | #define SYMHASH(LABEL) \ |
---|
2897 | ((((HOST_WIDE_INT) (LABEL)) & ((1 << HASHBITS) - 1)) % MAX_RTX_HASH_TABLE) |
---|
2898 | |
---|
2899 | /* Initialize constant pool hashing for next function. */ |
---|
2900 | |
---|
2901 | void |
---|
2902 | init_const_rtx_hash_table () |
---|
2903 | { |
---|
2904 | const_rtx_hash_table |
---|
2905 | = ((struct constant_descriptor **) |
---|
2906 | oballoc (MAX_RTX_HASH_TABLE * sizeof (struct constant_descriptor *))); |
---|
2907 | const_rtx_sym_hash_table |
---|
2908 | = ((struct pool_sym **) |
---|
2909 | oballoc (MAX_RTX_HASH_TABLE * sizeof (struct pool_sym *))); |
---|
2910 | bzero ((char *) const_rtx_hash_table, |
---|
2911 | MAX_RTX_HASH_TABLE * sizeof (struct constant_descriptor *)); |
---|
2912 | bzero ((char *) const_rtx_sym_hash_table, |
---|
2913 | MAX_RTX_HASH_TABLE * sizeof (struct pool_sym *)); |
---|
2914 | |
---|
2915 | first_pool = last_pool = 0; |
---|
2916 | pool_offset = 0; |
---|
2917 | } |
---|
2918 | |
---|
2919 | /* Save and restore status for a nested function. */ |
---|
2920 | |
---|
2921 | void |
---|
2922 | save_varasm_status (p) |
---|
2923 | struct function *p; |
---|
2924 | { |
---|
2925 | p->const_rtx_hash_table = const_rtx_hash_table; |
---|
2926 | p->const_rtx_sym_hash_table = const_rtx_sym_hash_table; |
---|
2927 | p->first_pool = first_pool; |
---|
2928 | p->last_pool = last_pool; |
---|
2929 | p->pool_offset = pool_offset; |
---|
2930 | } |
---|
2931 | |
---|
2932 | void |
---|
2933 | restore_varasm_status (p) |
---|
2934 | struct function *p; |
---|
2935 | { |
---|
2936 | const_rtx_hash_table = p->const_rtx_hash_table; |
---|
2937 | const_rtx_sym_hash_table = p->const_rtx_sym_hash_table; |
---|
2938 | first_pool = p->first_pool; |
---|
2939 | last_pool = p->last_pool; |
---|
2940 | pool_offset = p->pool_offset; |
---|
2941 | } |
---|
2942 | |
---|
2943 | enum kind { RTX_DOUBLE, RTX_INT }; |
---|
2944 | |
---|
2945 | struct rtx_const |
---|
2946 | { |
---|
2947 | #ifdef ONLY_INT_FIELDS |
---|
2948 | unsigned int kind : 16; |
---|
2949 | unsigned int mode : 16; |
---|
2950 | #else |
---|
2951 | enum kind kind : 16; |
---|
2952 | enum machine_mode mode : 16; |
---|
2953 | #endif |
---|
2954 | union { |
---|
2955 | union real_extract du; |
---|
2956 | struct addr_const addr; |
---|
2957 | struct {HOST_WIDE_INT high, low;} di; |
---|
2958 | } un; |
---|
2959 | }; |
---|
2960 | |
---|
2961 | /* Express an rtx for a constant integer (perhaps symbolic) |
---|
2962 | as the sum of a symbol or label plus an explicit integer. |
---|
2963 | They are stored into VALUE. */ |
---|
2964 | |
---|
2965 | static void |
---|
2966 | decode_rtx_const (mode, x, value) |
---|
2967 | enum machine_mode mode; |
---|
2968 | rtx x; |
---|
2969 | struct rtx_const *value; |
---|
2970 | { |
---|
2971 | /* Clear the whole structure, including any gaps. */ |
---|
2972 | |
---|
2973 | { |
---|
2974 | int *p = (int *) value; |
---|
2975 | int *end = (int *) (value + 1); |
---|
2976 | while (p < end) |
---|
2977 | *p++ = 0; |
---|
2978 | } |
---|
2979 | |
---|
2980 | value->kind = RTX_INT; /* Most usual kind. */ |
---|
2981 | value->mode = mode; |
---|
2982 | |
---|
2983 | switch (GET_CODE (x)) |
---|
2984 | { |
---|
2985 | case CONST_DOUBLE: |
---|
2986 | value->kind = RTX_DOUBLE; |
---|
2987 | if (GET_MODE (x) != VOIDmode) |
---|
2988 | { |
---|
2989 | value->mode = GET_MODE (x); |
---|
2990 | bcopy ((char *) &CONST_DOUBLE_LOW (x), |
---|
2991 | (char *) &value->un.du, sizeof value->un.du); |
---|
2992 | } |
---|
2993 | else |
---|
2994 | { |
---|
2995 | value->un.di.low = CONST_DOUBLE_LOW (x); |
---|
2996 | value->un.di.high = CONST_DOUBLE_HIGH (x); |
---|
2997 | } |
---|
2998 | break; |
---|
2999 | |
---|
3000 | case CONST_INT: |
---|
3001 | value->un.addr.offset = INTVAL (x); |
---|
3002 | break; |
---|
3003 | |
---|
3004 | case SYMBOL_REF: |
---|
3005 | case LABEL_REF: |
---|
3006 | case PC: |
---|
3007 | value->un.addr.base = x; |
---|
3008 | break; |
---|
3009 | |
---|
3010 | case CONST: |
---|
3011 | x = XEXP (x, 0); |
---|
3012 | if (GET_CODE (x) == PLUS) |
---|
3013 | { |
---|
3014 | value->un.addr.base = XEXP (x, 0); |
---|
3015 | if (GET_CODE (XEXP (x, 1)) != CONST_INT) |
---|
3016 | abort (); |
---|
3017 | value->un.addr.offset = INTVAL (XEXP (x, 1)); |
---|
3018 | } |
---|
3019 | else if (GET_CODE (x) == MINUS) |
---|
3020 | { |
---|
3021 | value->un.addr.base = XEXP (x, 0); |
---|
3022 | if (GET_CODE (XEXP (x, 1)) != CONST_INT) |
---|
3023 | abort (); |
---|
3024 | value->un.addr.offset = - INTVAL (XEXP (x, 1)); |
---|
3025 | } |
---|
3026 | else |
---|
3027 | abort (); |
---|
3028 | break; |
---|
3029 | |
---|
3030 | default: |
---|
3031 | abort (); |
---|
3032 | } |
---|
3033 | |
---|
3034 | if (value->kind == RTX_INT && value->un.addr.base != 0) |
---|
3035 | switch (GET_CODE (value->un.addr.base)) |
---|
3036 | { |
---|
3037 | case SYMBOL_REF: |
---|
3038 | case LABEL_REF: |
---|
3039 | /* Use the string's address, not the SYMBOL_REF's address, |
---|
3040 | for the sake of addresses of library routines. |
---|
3041 | For a LABEL_REF, compare labels. */ |
---|
3042 | value->un.addr.base = XEXP (value->un.addr.base, 0); |
---|
3043 | } |
---|
3044 | } |
---|
3045 | |
---|
3046 | /* Given a MINUS expression, simplify it if both sides |
---|
3047 | include the same symbol. */ |
---|
3048 | |
---|
3049 | rtx |
---|
3050 | simplify_subtraction (x) |
---|
3051 | rtx x; |
---|
3052 | { |
---|
3053 | struct rtx_const val0, val1; |
---|
3054 | |
---|
3055 | decode_rtx_const (GET_MODE (x), XEXP (x, 0), &val0); |
---|
3056 | decode_rtx_const (GET_MODE (x), XEXP (x, 1), &val1); |
---|
3057 | |
---|
3058 | if (val0.un.addr.base == val1.un.addr.base) |
---|
3059 | return GEN_INT (val0.un.addr.offset - val1.un.addr.offset); |
---|
3060 | return x; |
---|
3061 | } |
---|
3062 | |
---|
3063 | /* Compute a hash code for a constant RTL expression. */ |
---|
3064 | |
---|
3065 | static int |
---|
3066 | const_hash_rtx (mode, x) |
---|
3067 | enum machine_mode mode; |
---|
3068 | rtx x; |
---|
3069 | { |
---|
3070 | register int hi, i; |
---|
3071 | |
---|
3072 | struct rtx_const value; |
---|
3073 | decode_rtx_const (mode, x, &value); |
---|
3074 | |
---|
3075 | /* Compute hashing function */ |
---|
3076 | hi = 0; |
---|
3077 | for (i = 0; i < sizeof value / sizeof (int); i++) |
---|
3078 | hi += ((int *) &value)[i]; |
---|
3079 | |
---|
3080 | hi &= (1 << HASHBITS) - 1; |
---|
3081 | hi %= MAX_RTX_HASH_TABLE; |
---|
3082 | return hi; |
---|
3083 | } |
---|
3084 | |
---|
3085 | /* Compare a constant rtl object X with a constant-descriptor DESC. |
---|
3086 | Return 1 if DESC describes a constant with the same value as X. */ |
---|
3087 | |
---|
3088 | static int |
---|
3089 | compare_constant_rtx (mode, x, desc) |
---|
3090 | enum machine_mode mode; |
---|
3091 | rtx x; |
---|
3092 | struct constant_descriptor *desc; |
---|
3093 | { |
---|
3094 | register int *p = (int *) desc->contents; |
---|
3095 | register int *strp; |
---|
3096 | register int len; |
---|
3097 | struct rtx_const value; |
---|
3098 | |
---|
3099 | decode_rtx_const (mode, x, &value); |
---|
3100 | strp = (int *) &value; |
---|
3101 | len = sizeof value / sizeof (int); |
---|
3102 | |
---|
3103 | /* Compare constant contents. */ |
---|
3104 | while (--len >= 0) |
---|
3105 | if (*p++ != *strp++) |
---|
3106 | return 0; |
---|
3107 | |
---|
3108 | return 1; |
---|
3109 | } |
---|
3110 | |
---|
3111 | /* Construct a constant descriptor for the rtl-expression X. |
---|
3112 | It is up to the caller to enter the descriptor in the hash table. */ |
---|
3113 | |
---|
3114 | static struct constant_descriptor * |
---|
3115 | record_constant_rtx (mode, x) |
---|
3116 | enum machine_mode mode; |
---|
3117 | rtx x; |
---|
3118 | { |
---|
3119 | struct constant_descriptor *ptr; |
---|
3120 | char *label; |
---|
3121 | struct rtx_const value; |
---|
3122 | |
---|
3123 | decode_rtx_const (mode, x, &value); |
---|
3124 | |
---|
3125 | /* Put these things in the saveable obstack so we can ensure it won't |
---|
3126 | be freed if we are called from combine or some other phase that discards |
---|
3127 | memory allocated from function_obstack (current_obstack). */ |
---|
3128 | obstack_grow (saveable_obstack, &ptr, sizeof ptr); |
---|
3129 | obstack_grow (saveable_obstack, &label, sizeof label); |
---|
3130 | |
---|
3131 | /* Record constant contents. */ |
---|
3132 | obstack_grow (saveable_obstack, &value, sizeof value); |
---|
3133 | |
---|
3134 | return (struct constant_descriptor *) obstack_finish (saveable_obstack); |
---|
3135 | } |
---|
3136 | |
---|
3137 | /* Given a constant rtx X, make (or find) a memory constant for its value |
---|
3138 | and return a MEM rtx to refer to it in memory. */ |
---|
3139 | |
---|
3140 | rtx |
---|
3141 | force_const_mem (mode, x) |
---|
3142 | enum machine_mode mode; |
---|
3143 | rtx x; |
---|
3144 | { |
---|
3145 | register int hash; |
---|
3146 | register struct constant_descriptor *desc; |
---|
3147 | char label[256]; |
---|
3148 | char *found = 0; |
---|
3149 | rtx def; |
---|
3150 | |
---|
3151 | /* If we want this CONST_DOUBLE in the same mode as it is in memory |
---|
3152 | (this will always be true for floating CONST_DOUBLEs that have been |
---|
3153 | placed in memory, but not for VOIDmode (integer) CONST_DOUBLEs), |
---|
3154 | use the previous copy. Otherwise, make a new one. Note that in |
---|
3155 | the unlikely event that this same CONST_DOUBLE is used in two different |
---|
3156 | modes in an alternating fashion, we will allocate a lot of different |
---|
3157 | memory locations, but this should be extremely rare. */ |
---|
3158 | |
---|
3159 | /* Don't use CONST_DOUBLE_MEM in a nested function. |
---|
3160 | Nested functions have their own constant pools, |
---|
3161 | so they can't share the same values in CONST_DOUBLE_MEM |
---|
3162 | with the containing function. */ |
---|
3163 | if (outer_function_chain == 0) |
---|
3164 | if (GET_CODE (x) == CONST_DOUBLE |
---|
3165 | && GET_CODE (CONST_DOUBLE_MEM (x)) == MEM |
---|
3166 | && GET_MODE (CONST_DOUBLE_MEM (x)) == mode) |
---|
3167 | return CONST_DOUBLE_MEM (x); |
---|
3168 | |
---|
3169 | /* Compute hash code of X. Search the descriptors for that hash code |
---|
3170 | to see if any of them describes X. If yes, the descriptor records |
---|
3171 | the label number already assigned. */ |
---|
3172 | |
---|
3173 | hash = const_hash_rtx (mode, x); |
---|
3174 | |
---|
3175 | for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next) |
---|
3176 | if (compare_constant_rtx (mode, x, desc)) |
---|
3177 | { |
---|
3178 | found = desc->label; |
---|
3179 | break; |
---|
3180 | } |
---|
3181 | |
---|
3182 | if (found == 0) |
---|
3183 | { |
---|
3184 | register struct pool_constant *pool; |
---|
3185 | register struct pool_sym *sym; |
---|
3186 | int align; |
---|
3187 | |
---|
3188 | /* No constant equal to X is known to have been output. |
---|
3189 | Make a constant descriptor to enter X in the hash table. |
---|
3190 | Assign the label number and record it in the descriptor for |
---|
3191 | future calls to this function to find. */ |
---|
3192 | |
---|
3193 | desc = record_constant_rtx (mode, x); |
---|
3194 | desc->next = const_rtx_hash_table[hash]; |
---|
3195 | const_rtx_hash_table[hash] = desc; |
---|
3196 | |
---|
3197 | /* Align the location counter as required by EXP's data type. */ |
---|
3198 | align = (mode == VOIDmode) ? UNITS_PER_WORD : GET_MODE_SIZE (mode); |
---|
3199 | if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT) |
---|
3200 | align = BIGGEST_ALIGNMENT / BITS_PER_UNIT; |
---|
3201 | |
---|
3202 | pool_offset += align - 1; |
---|
3203 | pool_offset &= ~ (align - 1); |
---|
3204 | |
---|
3205 | /* If RTL is not being placed into the saveable obstack, make a |
---|
3206 | copy of X that is in the saveable obstack in case we are being |
---|
3207 | called from combine or some other phase that discards memory |
---|
3208 | it allocates. We need only do this if it is a CONST, since |
---|
3209 | no other RTX should be allocated in this situation. */ |
---|
3210 | if (rtl_obstack != saveable_obstack |
---|
3211 | && GET_CODE (x) == CONST) |
---|
3212 | { |
---|
3213 | push_obstacks_nochange (); |
---|
3214 | rtl_in_saveable_obstack (); |
---|
3215 | |
---|
3216 | x = gen_rtx (CONST, GET_MODE (x), |
---|
3217 | gen_rtx (PLUS, GET_MODE (x), |
---|
3218 | XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 0), 1))); |
---|
3219 | pop_obstacks (); |
---|
3220 | } |
---|
3221 | |
---|
3222 | /* Allocate a pool constant descriptor, fill it in, and chain it in. */ |
---|
3223 | |
---|
3224 | pool = (struct pool_constant *) savealloc (sizeof (struct pool_constant)); |
---|
3225 | pool->desc = desc; |
---|
3226 | pool->constant = x; |
---|
3227 | pool->mode = mode; |
---|
3228 | pool->labelno = const_labelno; |
---|
3229 | pool->align = align; |
---|
3230 | pool->offset = pool_offset; |
---|
3231 | pool->next = 0; |
---|
3232 | |
---|
3233 | if (last_pool == 0) |
---|
3234 | first_pool = pool; |
---|
3235 | else |
---|
3236 | last_pool->next = pool; |
---|
3237 | |
---|
3238 | last_pool = pool; |
---|
3239 | pool_offset += GET_MODE_SIZE (mode); |
---|
3240 | |
---|
3241 | /* Create a string containing the label name, in LABEL. */ |
---|
3242 | ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); |
---|
3243 | |
---|
3244 | ++const_labelno; |
---|
3245 | |
---|
3246 | desc->label = found |
---|
3247 | = (char *) obstack_copy0 (saveable_obstack, label, strlen (label)); |
---|
3248 | |
---|
3249 | /* Add label to symbol hash table. */ |
---|
3250 | hash = SYMHASH (found); |
---|
3251 | sym = (struct pool_sym *) savealloc (sizeof (struct pool_sym)); |
---|
3252 | sym->label = found; |
---|
3253 | sym->pool = pool; |
---|
3254 | sym->next = const_rtx_sym_hash_table[hash]; |
---|
3255 | const_rtx_sym_hash_table[hash] = sym; |
---|
3256 | } |
---|
3257 | |
---|
3258 | /* We have a symbol name; construct the SYMBOL_REF and the MEM. */ |
---|
3259 | |
---|
3260 | def = gen_rtx (MEM, mode, gen_rtx (SYMBOL_REF, Pmode, found)); |
---|
3261 | |
---|
3262 | RTX_UNCHANGING_P (def) = 1; |
---|
3263 | /* Mark the symbol_ref as belonging to this constants pool. */ |
---|
3264 | CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1; |
---|
3265 | current_function_uses_const_pool = 1; |
---|
3266 | |
---|
3267 | if (outer_function_chain == 0) |
---|
3268 | if (GET_CODE (x) == CONST_DOUBLE) |
---|
3269 | { |
---|
3270 | if (CONST_DOUBLE_MEM (x) == cc0_rtx) |
---|
3271 | { |
---|
3272 | CONST_DOUBLE_CHAIN (x) = const_double_chain; |
---|
3273 | const_double_chain = x; |
---|
3274 | } |
---|
3275 | CONST_DOUBLE_MEM (x) = def; |
---|
3276 | } |
---|
3277 | |
---|
3278 | return def; |
---|
3279 | } |
---|
3280 | |
---|
3281 | /* Given a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true, return a pointer to |
---|
3282 | the corresponding pool_constant structure. */ |
---|
3283 | |
---|
3284 | static struct pool_constant * |
---|
3285 | find_pool_constant (addr) |
---|
3286 | rtx addr; |
---|
3287 | { |
---|
3288 | struct pool_sym *sym; |
---|
3289 | char *label = XSTR (addr, 0); |
---|
3290 | |
---|
3291 | for (sym = const_rtx_sym_hash_table[SYMHASH (label)]; sym; sym = sym->next) |
---|
3292 | if (sym->label == label) |
---|
3293 | return sym->pool; |
---|
3294 | |
---|
3295 | abort (); |
---|
3296 | } |
---|
3297 | |
---|
3298 | /* Given a constant pool SYMBOL_REF, return the corresponding constant. */ |
---|
3299 | |
---|
3300 | rtx |
---|
3301 | get_pool_constant (addr) |
---|
3302 | rtx addr; |
---|
3303 | { |
---|
3304 | return (find_pool_constant (addr))->constant; |
---|
3305 | } |
---|
3306 | |
---|
3307 | /* Similar, return the mode. */ |
---|
3308 | |
---|
3309 | enum machine_mode |
---|
3310 | get_pool_mode (addr) |
---|
3311 | rtx addr; |
---|
3312 | { |
---|
3313 | return (find_pool_constant (addr))->mode; |
---|
3314 | } |
---|
3315 | |
---|
3316 | /* Similar, return the offset in the constant pool. */ |
---|
3317 | |
---|
3318 | int |
---|
3319 | get_pool_offset (addr) |
---|
3320 | rtx addr; |
---|
3321 | { |
---|
3322 | return (find_pool_constant (addr))->offset; |
---|
3323 | } |
---|
3324 | |
---|
3325 | /* Return the size of the constant pool. */ |
---|
3326 | |
---|
3327 | int |
---|
3328 | get_pool_size () |
---|
3329 | { |
---|
3330 | return pool_offset; |
---|
3331 | } |
---|
3332 | |
---|
3333 | /* Write all the constants in the constant pool. */ |
---|
3334 | |
---|
3335 | void |
---|
3336 | output_constant_pool (fnname, fndecl) |
---|
3337 | char *fnname; |
---|
3338 | tree fndecl; |
---|
3339 | { |
---|
3340 | struct pool_constant *pool; |
---|
3341 | rtx x; |
---|
3342 | union real_extract u; |
---|
3343 | |
---|
3344 | #ifdef ASM_OUTPUT_POOL_PROLOGUE |
---|
3345 | ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool_offset); |
---|
3346 | #endif |
---|
3347 | |
---|
3348 | for (pool = first_pool; pool; pool = pool->next) |
---|
3349 | { |
---|
3350 | x = pool->constant; |
---|
3351 | |
---|
3352 | /* See if X is a LABEL_REF (or a CONST referring to a LABEL_REF) |
---|
3353 | whose CODE_LABEL has been deleted. This can occur if a jump table |
---|
3354 | is eliminated by optimization. If so, write a constant of zero |
---|
3355 | instead. Note that this can also happen by turning the |
---|
3356 | CODE_LABEL into a NOTE. */ |
---|
3357 | if (((GET_CODE (x) == LABEL_REF |
---|
3358 | && (INSN_DELETED_P (XEXP (x, 0)) |
---|
3359 | || GET_CODE (XEXP (x, 0)) == NOTE))) |
---|
3360 | || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS |
---|
3361 | && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF |
---|
3362 | && (INSN_DELETED_P (XEXP (XEXP (XEXP (x, 0), 0), 0)) |
---|
3363 | || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == NOTE))) |
---|
3364 | x = const0_rtx; |
---|
3365 | |
---|
3366 | /* First switch to correct section. */ |
---|
3367 | #ifdef SELECT_RTX_SECTION |
---|
3368 | SELECT_RTX_SECTION (pool->mode, x); |
---|
3369 | #else |
---|
3370 | readonly_data_section (); |
---|
3371 | #endif |
---|
3372 | |
---|
3373 | #ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY |
---|
3374 | ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, pool->mode, |
---|
3375 | pool->align, pool->labelno, done); |
---|
3376 | #endif |
---|
3377 | |
---|
3378 | if (pool->align > 1) |
---|
3379 | ASM_OUTPUT_ALIGN (asm_out_file, exact_log2 (pool->align)); |
---|
3380 | |
---|
3381 | /* Output the label. */ |
---|
3382 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", pool->labelno); |
---|
3383 | |
---|
3384 | /* Output the value of the constant itself. */ |
---|
3385 | switch (GET_MODE_CLASS (pool->mode)) |
---|
3386 | { |
---|
3387 | case MODE_FLOAT: |
---|
3388 | if (GET_CODE (x) != CONST_DOUBLE) |
---|
3389 | abort (); |
---|
3390 | |
---|
3391 | bcopy ((char *) &CONST_DOUBLE_LOW (x), (char *) &u, sizeof u); |
---|
3392 | assemble_real (u.d, pool->mode); |
---|
3393 | break; |
---|
3394 | |
---|
3395 | case MODE_INT: |
---|
3396 | case MODE_PARTIAL_INT: |
---|
3397 | assemble_integer (x, GET_MODE_SIZE (pool->mode), 1); |
---|
3398 | break; |
---|
3399 | |
---|
3400 | default: |
---|
3401 | abort (); |
---|
3402 | } |
---|
3403 | |
---|
3404 | done: ; |
---|
3405 | } |
---|
3406 | |
---|
3407 | /* Done with this pool. */ |
---|
3408 | first_pool = last_pool = 0; |
---|
3409 | } |
---|
3410 | |
---|
3411 | /* Find all the constants whose addresses are referenced inside of EXP, |
---|
3412 | and make sure assembler code with a label has been output for each one. |
---|
3413 | Indicate whether an ADDR_EXPR has been encountered. */ |
---|
3414 | |
---|
3415 | static int |
---|
3416 | output_addressed_constants (exp) |
---|
3417 | tree exp; |
---|
3418 | { |
---|
3419 | int reloc = 0; |
---|
3420 | |
---|
3421 | switch (TREE_CODE (exp)) |
---|
3422 | { |
---|
3423 | case ADDR_EXPR: |
---|
3424 | { |
---|
3425 | register tree constant = TREE_OPERAND (exp, 0); |
---|
3426 | |
---|
3427 | while (TREE_CODE (constant) == COMPONENT_REF) |
---|
3428 | { |
---|
3429 | constant = TREE_OPERAND (constant, 0); |
---|
3430 | } |
---|
3431 | |
---|
3432 | if (TREE_CODE_CLASS (TREE_CODE (constant)) == 'c' |
---|
3433 | || TREE_CODE (constant) == CONSTRUCTOR) |
---|
3434 | /* No need to do anything here |
---|
3435 | for addresses of variables or functions. */ |
---|
3436 | output_constant_def (constant); |
---|
3437 | } |
---|
3438 | reloc = 1; |
---|
3439 | break; |
---|
3440 | |
---|
3441 | case PLUS_EXPR: |
---|
3442 | case MINUS_EXPR: |
---|
3443 | reloc = output_addressed_constants (TREE_OPERAND (exp, 0)); |
---|
3444 | reloc |= output_addressed_constants (TREE_OPERAND (exp, 1)); |
---|
3445 | break; |
---|
3446 | |
---|
3447 | case NOP_EXPR: |
---|
3448 | case CONVERT_EXPR: |
---|
3449 | case NON_LVALUE_EXPR: |
---|
3450 | reloc = output_addressed_constants (TREE_OPERAND (exp, 0)); |
---|
3451 | break; |
---|
3452 | |
---|
3453 | case CONSTRUCTOR: |
---|
3454 | { |
---|
3455 | register tree link; |
---|
3456 | for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) |
---|
3457 | if (TREE_VALUE (link) != 0) |
---|
3458 | reloc |= output_addressed_constants (TREE_VALUE (link)); |
---|
3459 | } |
---|
3460 | break; |
---|
3461 | |
---|
3462 | case ERROR_MARK: |
---|
3463 | break; |
---|
3464 | } |
---|
3465 | return reloc; |
---|
3466 | } |
---|
3467 | |
---|
3468 | /* Output assembler code for constant EXP to FILE, with no label. |
---|
3469 | This includes the pseudo-op such as ".int" or ".byte", and a newline. |
---|
3470 | Assumes output_addressed_constants has been done on EXP already. |
---|
3471 | |
---|
3472 | Generate exactly SIZE bytes of assembler data, padding at the end |
---|
3473 | with zeros if necessary. SIZE must always be specified. |
---|
3474 | |
---|
3475 | SIZE is important for structure constructors, |
---|
3476 | since trailing members may have been omitted from the constructor. |
---|
3477 | It is also important for initialization of arrays from string constants |
---|
3478 | since the full length of the string constant might not be wanted. |
---|
3479 | It is also needed for initialization of unions, where the initializer's |
---|
3480 | type is just one member, and that may not be as long as the union. |
---|
3481 | |
---|
3482 | There a case in which we would fail to output exactly SIZE bytes: |
---|
3483 | for a structure constructor that wants to produce more than SIZE bytes. |
---|
3484 | But such constructors will never be generated for any possible input. */ |
---|
3485 | |
---|
3486 | void |
---|
3487 | output_constant (exp, size) |
---|
3488 | register tree exp; |
---|
3489 | register int size; |
---|
3490 | { |
---|
3491 | register enum tree_code code = TREE_CODE (TREE_TYPE (exp)); |
---|
3492 | rtx x; |
---|
3493 | |
---|
3494 | if (size == 0) |
---|
3495 | return; |
---|
3496 | |
---|
3497 | /* Eliminate the NON_LVALUE_EXPR_EXPR that makes a cast not be an lvalue. |
---|
3498 | That way we get the constant (we hope) inside it. Also, strip off any |
---|
3499 | NOP_EXPR that converts between two record, union, array, or set types. */ |
---|
3500 | while ((TREE_CODE (exp) == NOP_EXPR |
---|
3501 | && (TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0)) |
---|
3502 | || AGGREGATE_TYPE_P (TREE_TYPE (exp)))) |
---|
3503 | || TREE_CODE (exp) == NON_LVALUE_EXPR) |
---|
3504 | exp = TREE_OPERAND (exp, 0); |
---|
3505 | |
---|
3506 | /* Allow a constructor with no elements for any data type. |
---|
3507 | This means to fill the space with zeros. */ |
---|
3508 | if (TREE_CODE (exp) == CONSTRUCTOR && CONSTRUCTOR_ELTS (exp) == 0) |
---|
3509 | { |
---|
3510 | if (output_bytecode) |
---|
3511 | bc_emit_const_skip (size); |
---|
3512 | else |
---|
3513 | assemble_zeros (size); |
---|
3514 | return; |
---|
3515 | } |
---|
3516 | |
---|
3517 | switch (code) |
---|
3518 | { |
---|
3519 | case CHAR_TYPE: |
---|
3520 | case BOOLEAN_TYPE: |
---|
3521 | case INTEGER_TYPE: |
---|
3522 | case ENUMERAL_TYPE: |
---|
3523 | case POINTER_TYPE: |
---|
3524 | case REFERENCE_TYPE: |
---|
3525 | /* ??? What about (int)((float)(int)&foo + 4) */ |
---|
3526 | while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR |
---|
3527 | || TREE_CODE (exp) == NON_LVALUE_EXPR) |
---|
3528 | exp = TREE_OPERAND (exp, 0); |
---|
3529 | |
---|
3530 | if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode, |
---|
3531 | EXPAND_INITIALIZER), |
---|
3532 | size, 0)) |
---|
3533 | error ("initializer for integer value is too complicated"); |
---|
3534 | size = 0; |
---|
3535 | break; |
---|
3536 | |
---|
3537 | case REAL_TYPE: |
---|
3538 | if (TREE_CODE (exp) != REAL_CST) |
---|
3539 | error ("initializer for floating value is not a floating constant"); |
---|
3540 | |
---|
3541 | assemble_real (TREE_REAL_CST (exp), |
---|
3542 | mode_for_size (size * BITS_PER_UNIT, MODE_FLOAT, 0)); |
---|
3543 | size = 0; |
---|
3544 | break; |
---|
3545 | |
---|
3546 | case COMPLEX_TYPE: |
---|
3547 | output_constant (TREE_REALPART (exp), size / 2); |
---|
3548 | output_constant (TREE_IMAGPART (exp), size / 2); |
---|
3549 | size -= (size / 2) * 2; |
---|
3550 | break; |
---|
3551 | |
---|
3552 | case ARRAY_TYPE: |
---|
3553 | if (TREE_CODE (exp) == CONSTRUCTOR) |
---|
3554 | { |
---|
3555 | output_constructor (exp, size); |
---|
3556 | return; |
---|
3557 | } |
---|
3558 | else if (TREE_CODE (exp) == STRING_CST) |
---|
3559 | { |
---|
3560 | int excess = 0; |
---|
3561 | |
---|
3562 | if (size > TREE_STRING_LENGTH (exp)) |
---|
3563 | { |
---|
3564 | excess = size - TREE_STRING_LENGTH (exp); |
---|
3565 | size = TREE_STRING_LENGTH (exp); |
---|
3566 | } |
---|
3567 | |
---|
3568 | assemble_string (TREE_STRING_POINTER (exp), size); |
---|
3569 | size = excess; |
---|
3570 | } |
---|
3571 | else |
---|
3572 | abort (); |
---|
3573 | break; |
---|
3574 | |
---|
3575 | case RECORD_TYPE: |
---|
3576 | case UNION_TYPE: |
---|
3577 | if (TREE_CODE (exp) == CONSTRUCTOR) |
---|
3578 | output_constructor (exp, size); |
---|
3579 | else |
---|
3580 | abort (); |
---|
3581 | return; |
---|
3582 | |
---|
3583 | case SET_TYPE: |
---|
3584 | if (TREE_CODE (exp) == INTEGER_CST) |
---|
3585 | assemble_integer (expand_expr (exp, NULL_RTX, |
---|
3586 | VOIDmode, EXPAND_INITIALIZER), |
---|
3587 | size, 1); |
---|
3588 | else if (TREE_CODE (exp) == CONSTRUCTOR) |
---|
3589 | { |
---|
3590 | unsigned char *buffer = (unsigned char *) alloca (size); |
---|
3591 | if (get_set_constructor_bytes (exp, buffer, size)) |
---|
3592 | abort (); |
---|
3593 | assemble_string ((char *) buffer, size); |
---|
3594 | } |
---|
3595 | else |
---|
3596 | error ("unknown set constructor type"); |
---|
3597 | return; |
---|
3598 | } |
---|
3599 | |
---|
3600 | if (size > 0) |
---|
3601 | assemble_zeros (size); |
---|
3602 | } |
---|
3603 | |
---|
3604 | /* Bytecode specific code to output assembler for integer. */ |
---|
3605 | |
---|
3606 | static void |
---|
3607 | bc_assemble_integer (exp, size) |
---|
3608 | tree exp; |
---|
3609 | int size; |
---|
3610 | { |
---|
3611 | tree const_part; |
---|
3612 | tree addr_part; |
---|
3613 | tree tmp; |
---|
3614 | |
---|
3615 | /* FIXME: is this fold() business going to be as good as the |
---|
3616 | expand_expr() using EXPAND_SUM above in the RTL case? I |
---|
3617 | hate RMS. |
---|
3618 | FIXME: Copied as is from BC-GCC1; may need work. Don't hate. -bson */ |
---|
3619 | |
---|
3620 | exp = fold (exp); |
---|
3621 | |
---|
3622 | while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR) |
---|
3623 | exp = TREE_OPERAND (exp, 0); |
---|
3624 | if (TREE_CODE (exp) == INTEGER_CST) |
---|
3625 | { |
---|
3626 | const_part = exp; |
---|
3627 | addr_part = 0; |
---|
3628 | } |
---|
3629 | else if (TREE_CODE (exp) == PLUS_EXPR) |
---|
3630 | { |
---|
3631 | const_part = TREE_OPERAND (exp, 0); |
---|
3632 | while (TREE_CODE (const_part) == NOP_EXPR |
---|
3633 | || TREE_CODE (const_part) == CONVERT_EXPR) |
---|
3634 | const_part = TREE_OPERAND (const_part, 0); |
---|
3635 | addr_part = TREE_OPERAND (exp, 1); |
---|
3636 | while (TREE_CODE (addr_part) == NOP_EXPR |
---|
3637 | || TREE_CODE (addr_part) == CONVERT_EXPR) |
---|
3638 | addr_part = TREE_OPERAND (addr_part, 0); |
---|
3639 | if (TREE_CODE (const_part) != INTEGER_CST) |
---|
3640 | tmp = const_part, const_part = addr_part, addr_part = tmp; |
---|
3641 | if (TREE_CODE (const_part) != INTEGER_CST |
---|
3642 | || TREE_CODE (addr_part) != ADDR_EXPR) |
---|
3643 | abort (); /* FIXME: we really haven't considered |
---|
3644 | all the possible cases here. */ |
---|
3645 | } |
---|
3646 | else if (TREE_CODE (exp) == ADDR_EXPR) |
---|
3647 | { |
---|
3648 | const_part = integer_zero_node; |
---|
3649 | addr_part = exp; |
---|
3650 | } |
---|
3651 | else |
---|
3652 | abort (); /* FIXME: ditto previous. */ |
---|
3653 | |
---|
3654 | if (addr_part == 0) |
---|
3655 | { |
---|
3656 | if (size == 1) |
---|
3657 | { |
---|
3658 | char c = TREE_INT_CST_LOW (const_part); |
---|
3659 | bc_emit (&c, 1); |
---|
3660 | size -= 1; |
---|
3661 | } |
---|
3662 | else if (size == 2) |
---|
3663 | { |
---|
3664 | short s = TREE_INT_CST_LOW (const_part); |
---|
3665 | bc_emit ((char *) &s, 2); |
---|
3666 | size -= 2; |
---|
3667 | } |
---|
3668 | else if (size == 4) |
---|
3669 | { |
---|
3670 | int i = TREE_INT_CST_LOW (const_part); |
---|
3671 | bc_emit ((char *) &i, 4); |
---|
3672 | size -= 4; |
---|
3673 | } |
---|
3674 | else if (size == 8) |
---|
3675 | { |
---|
3676 | if (WORDS_BIG_ENDIAN) |
---|
3677 | { |
---|
3678 | int i = TREE_INT_CST_HIGH (const_part); |
---|
3679 | bc_emit ((char *) &i, 4); |
---|
3680 | i = TREE_INT_CST_LOW (const_part); |
---|
3681 | bc_emit ((char *) &i, 4); |
---|
3682 | } |
---|
3683 | else |
---|
3684 | { |
---|
3685 | int i = TREE_INT_CST_LOW (const_part); |
---|
3686 | bc_emit ((char *) &i, 4); |
---|
3687 | i = TREE_INT_CST_HIGH (const_part); |
---|
3688 | bc_emit ((char *) &i, 4); |
---|
3689 | } |
---|
3690 | size -= 8; |
---|
3691 | } |
---|
3692 | } |
---|
3693 | else |
---|
3694 | if (size == 4 |
---|
3695 | && TREE_CODE (TREE_OPERAND (addr_part, 0)) == VAR_DECL) |
---|
3696 | bc_emit_labelref (IDENTIFIER_POINTER |
---|
3697 | (DECL_ASSEMBLER_NAME (TREE_OPERAND (addr_part, 0))), |
---|
3698 | TREE_INT_CST_LOW (const_part)); |
---|
3699 | else |
---|
3700 | abort (); /* FIXME: there may be more cases. */ |
---|
3701 | } |
---|
3702 | |
---|
3703 | /* Subroutine of output_constant, used for CONSTRUCTORs |
---|
3704 | (aggregate constants). |
---|
3705 | Generate at least SIZE bytes, padding if necessary. */ |
---|
3706 | |
---|
3707 | static void |
---|
3708 | output_constructor (exp, size) |
---|
3709 | tree exp; |
---|
3710 | int size; |
---|
3711 | { |
---|
3712 | register tree link, field = 0; |
---|
3713 | HOST_WIDE_INT min_index = 0; |
---|
3714 | /* Number of bytes output or skipped so far. |
---|
3715 | In other words, current position within the constructor. */ |
---|
3716 | int total_bytes = 0; |
---|
3717 | /* Non-zero means BYTE contains part of a byte, to be output. */ |
---|
3718 | int byte_buffer_in_use = 0; |
---|
3719 | register int byte; |
---|
3720 | |
---|
3721 | if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT) |
---|
3722 | abort (); |
---|
3723 | |
---|
3724 | if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) |
---|
3725 | field = TYPE_FIELDS (TREE_TYPE (exp)); |
---|
3726 | |
---|
3727 | if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE |
---|
3728 | && TYPE_DOMAIN (TREE_TYPE (exp)) != 0) |
---|
3729 | min_index |
---|
3730 | = TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (exp)))); |
---|
3731 | |
---|
3732 | /* As LINK goes through the elements of the constant, |
---|
3733 | FIELD goes through the structure fields, if the constant is a structure. |
---|
3734 | if the constant is a union, then we override this, |
---|
3735 | by getting the field from the TREE_LIST element. |
---|
3736 | But the constant could also be an array. Then FIELD is zero. */ |
---|
3737 | for (link = CONSTRUCTOR_ELTS (exp); |
---|
3738 | link; |
---|
3739 | link = TREE_CHAIN (link), |
---|
3740 | field = field ? TREE_CHAIN (field) : 0) |
---|
3741 | { |
---|
3742 | tree val = TREE_VALUE (link); |
---|
3743 | tree index = 0; |
---|
3744 | |
---|
3745 | /* the element in a union constructor specifies the proper field. */ |
---|
3746 | |
---|
3747 | if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE |
---|
3748 | || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE) |
---|
3749 | { |
---|
3750 | /* if available, use the type given by link */ |
---|
3751 | if (TREE_PURPOSE (link) != 0) |
---|
3752 | field = TREE_PURPOSE (link); |
---|
3753 | } |
---|
3754 | |
---|
3755 | if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) |
---|
3756 | index = TREE_PURPOSE (link); |
---|
3757 | |
---|
3758 | /* Eliminate the marker that makes a cast not be an lvalue. */ |
---|
3759 | if (val != 0) |
---|
3760 | STRIP_NOPS (val); |
---|
3761 | |
---|
3762 | if (field == 0 || !DECL_BIT_FIELD (field)) |
---|
3763 | { |
---|
3764 | /* An element that is not a bit-field. */ |
---|
3765 | |
---|
3766 | register int fieldsize; |
---|
3767 | /* Since this structure is static, |
---|
3768 | we know the positions are constant. */ |
---|
3769 | int bitpos = (field ? (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)) |
---|
3770 | / BITS_PER_UNIT) |
---|
3771 | : 0); |
---|
3772 | if (index != 0) |
---|
3773 | bitpos = (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (val))) |
---|
3774 | / BITS_PER_UNIT |
---|
3775 | * (TREE_INT_CST_LOW (index) - min_index)); |
---|
3776 | |
---|
3777 | /* Output any buffered-up bit-fields preceding this element. */ |
---|
3778 | if (byte_buffer_in_use) |
---|
3779 | { |
---|
3780 | ASM_OUTPUT_BYTE (asm_out_file, byte); |
---|
3781 | total_bytes++; |
---|
3782 | byte_buffer_in_use = 0; |
---|
3783 | } |
---|
3784 | |
---|
3785 | /* Advance to offset of this element. |
---|
3786 | Note no alignment needed in an array, since that is guaranteed |
---|
3787 | if each element has the proper size. */ |
---|
3788 | if ((field != 0 || index != 0) && bitpos != total_bytes) |
---|
3789 | { |
---|
3790 | if (!output_bytecode) |
---|
3791 | assemble_zeros (bitpos - total_bytes); |
---|
3792 | else |
---|
3793 | bc_emit_const_skip (bitpos - total_bytes); |
---|
3794 | total_bytes = bitpos; |
---|
3795 | } |
---|
3796 | |
---|
3797 | /* Determine size this element should occupy. */ |
---|
3798 | if (field) |
---|
3799 | { |
---|
3800 | if (TREE_CODE (DECL_SIZE (field)) != INTEGER_CST) |
---|
3801 | abort (); |
---|
3802 | if (TREE_INT_CST_LOW (DECL_SIZE (field)) > 100000) |
---|
3803 | { |
---|
3804 | /* This avoids overflow trouble. */ |
---|
3805 | tree size_tree = size_binop (CEIL_DIV_EXPR, |
---|
3806 | DECL_SIZE (field), |
---|
3807 | size_int (BITS_PER_UNIT)); |
---|
3808 | fieldsize = TREE_INT_CST_LOW (size_tree); |
---|
3809 | } |
---|
3810 | else |
---|
3811 | { |
---|
3812 | fieldsize = TREE_INT_CST_LOW (DECL_SIZE (field)); |
---|
3813 | fieldsize = (fieldsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT; |
---|
3814 | } |
---|
3815 | } |
---|
3816 | else |
---|
3817 | fieldsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp))); |
---|
3818 | |
---|
3819 | /* Output the element's initial value. */ |
---|
3820 | if (val == 0) |
---|
3821 | assemble_zeros (fieldsize); |
---|
3822 | else |
---|
3823 | output_constant (val, fieldsize); |
---|
3824 | |
---|
3825 | /* Count its size. */ |
---|
3826 | total_bytes += fieldsize; |
---|
3827 | } |
---|
3828 | else if (val != 0 && TREE_CODE (val) != INTEGER_CST) |
---|
3829 | error ("invalid initial value for member `%s'", |
---|
3830 | IDENTIFIER_POINTER (DECL_NAME (field))); |
---|
3831 | else |
---|
3832 | { |
---|
3833 | /* Element that is a bit-field. */ |
---|
3834 | |
---|
3835 | int next_offset = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)); |
---|
3836 | int end_offset |
---|
3837 | = (next_offset + TREE_INT_CST_LOW (DECL_SIZE (field))); |
---|
3838 | |
---|
3839 | if (val == 0) |
---|
3840 | val = integer_zero_node; |
---|
3841 | |
---|
3842 | /* If this field does not start in this (or, next) byte, |
---|
3843 | skip some bytes. */ |
---|
3844 | if (next_offset / BITS_PER_UNIT != total_bytes) |
---|
3845 | { |
---|
3846 | /* Output remnant of any bit field in previous bytes. */ |
---|
3847 | if (byte_buffer_in_use) |
---|
3848 | { |
---|
3849 | ASM_OUTPUT_BYTE (asm_out_file, byte); |
---|
3850 | total_bytes++; |
---|
3851 | byte_buffer_in_use = 0; |
---|
3852 | } |
---|
3853 | |
---|
3854 | /* If still not at proper byte, advance to there. */ |
---|
3855 | if (next_offset / BITS_PER_UNIT != total_bytes) |
---|
3856 | { |
---|
3857 | assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes); |
---|
3858 | total_bytes = next_offset / BITS_PER_UNIT; |
---|
3859 | } |
---|
3860 | } |
---|
3861 | |
---|
3862 | if (! byte_buffer_in_use) |
---|
3863 | byte = 0; |
---|
3864 | |
---|
3865 | /* We must split the element into pieces that fall within |
---|
3866 | separate bytes, and combine each byte with previous or |
---|
3867 | following bit-fields. */ |
---|
3868 | |
---|
3869 | /* next_offset is the offset n fbits from the beginning of |
---|
3870 | the structure to the next bit of this element to be processed. |
---|
3871 | end_offset is the offset of the first bit past the end of |
---|
3872 | this element. */ |
---|
3873 | while (next_offset < end_offset) |
---|
3874 | { |
---|
3875 | int this_time; |
---|
3876 | int shift; |
---|
3877 | HOST_WIDE_INT value; |
---|
3878 | int next_byte = next_offset / BITS_PER_UNIT; |
---|
3879 | int next_bit = next_offset % BITS_PER_UNIT; |
---|
3880 | |
---|
3881 | /* Advance from byte to byte |
---|
3882 | within this element when necessary. */ |
---|
3883 | while (next_byte != total_bytes) |
---|
3884 | { |
---|
3885 | ASM_OUTPUT_BYTE (asm_out_file, byte); |
---|
3886 | total_bytes++; |
---|
3887 | byte = 0; |
---|
3888 | } |
---|
3889 | |
---|
3890 | /* Number of bits we can process at once |
---|
3891 | (all part of the same byte). */ |
---|
3892 | this_time = MIN (end_offset - next_offset, |
---|
3893 | BITS_PER_UNIT - next_bit); |
---|
3894 | if (BYTES_BIG_ENDIAN) |
---|
3895 | { |
---|
3896 | /* On big-endian machine, take the most significant bits |
---|
3897 | first (of the bits that are significant) |
---|
3898 | and put them into bytes from the most significant end. */ |
---|
3899 | shift = end_offset - next_offset - this_time; |
---|
3900 | /* Don't try to take a bunch of bits that cross |
---|
3901 | the word boundary in the INTEGER_CST. */ |
---|
3902 | if (shift < HOST_BITS_PER_WIDE_INT |
---|
3903 | && shift + this_time > HOST_BITS_PER_WIDE_INT) |
---|
3904 | { |
---|
3905 | this_time -= (HOST_BITS_PER_WIDE_INT - shift); |
---|
3906 | shift = HOST_BITS_PER_WIDE_INT; |
---|
3907 | } |
---|
3908 | |
---|
3909 | /* Now get the bits from the appropriate constant word. */ |
---|
3910 | if (shift < HOST_BITS_PER_WIDE_INT) |
---|
3911 | { |
---|
3912 | value = TREE_INT_CST_LOW (val); |
---|
3913 | } |
---|
3914 | else if (shift < 2 * HOST_BITS_PER_WIDE_INT) |
---|
3915 | { |
---|
3916 | value = TREE_INT_CST_HIGH (val); |
---|
3917 | shift -= HOST_BITS_PER_WIDE_INT; |
---|
3918 | } |
---|
3919 | else |
---|
3920 | abort (); |
---|
3921 | byte |= (((value >> shift) |
---|
3922 | & (((HOST_WIDE_INT) 1 << this_time) - 1)) |
---|
3923 | << (BITS_PER_UNIT - this_time - next_bit)); |
---|
3924 | } |
---|
3925 | else |
---|
3926 | { |
---|
3927 | /* On little-endian machines, |
---|
3928 | take first the least significant bits of the value |
---|
3929 | and pack them starting at the least significant |
---|
3930 | bits of the bytes. */ |
---|
3931 | shift = (next_offset |
---|
3932 | - TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))); |
---|
3933 | /* Don't try to take a bunch of bits that cross |
---|
3934 | the word boundary in the INTEGER_CST. */ |
---|
3935 | if (shift < HOST_BITS_PER_WIDE_INT |
---|
3936 | && shift + this_time > HOST_BITS_PER_WIDE_INT) |
---|
3937 | { |
---|
3938 | this_time -= (HOST_BITS_PER_WIDE_INT - shift); |
---|
3939 | shift = HOST_BITS_PER_WIDE_INT; |
---|
3940 | } |
---|
3941 | |
---|
3942 | /* Now get the bits from the appropriate constant word. */ |
---|
3943 | if (shift < HOST_BITS_PER_INT) |
---|
3944 | value = TREE_INT_CST_LOW (val); |
---|
3945 | else if (shift < 2 * HOST_BITS_PER_WIDE_INT) |
---|
3946 | { |
---|
3947 | value = TREE_INT_CST_HIGH (val); |
---|
3948 | shift -= HOST_BITS_PER_WIDE_INT; |
---|
3949 | } |
---|
3950 | else |
---|
3951 | abort (); |
---|
3952 | byte |= (((value >> shift) |
---|
3953 | & (((HOST_WIDE_INT) 1 << this_time) - 1)) |
---|
3954 | << next_bit); |
---|
3955 | } |
---|
3956 | next_offset += this_time; |
---|
3957 | byte_buffer_in_use = 1; |
---|
3958 | } |
---|
3959 | } |
---|
3960 | } |
---|
3961 | if (byte_buffer_in_use) |
---|
3962 | { |
---|
3963 | ASM_OUTPUT_BYTE (asm_out_file, byte); |
---|
3964 | total_bytes++; |
---|
3965 | } |
---|
3966 | if (total_bytes < size) |
---|
3967 | assemble_zeros (size - total_bytes); |
---|
3968 | } |
---|
3969 | |
---|
3970 | /* Output asm to handle ``#pragma weak'' */ |
---|
3971 | void |
---|
3972 | handle_pragma_weak (what, name, value) |
---|
3973 | enum pragma_state what; |
---|
3974 | char *name, *value; |
---|
3975 | { |
---|
3976 | #ifdef HANDLE_PRAGMA_WEAK |
---|
3977 | if (what == ps_name || what == ps_value) |
---|
3978 | { |
---|
3979 | struct weak_syms *weak = |
---|
3980 | (struct weak_syms *)permalloc (sizeof (struct weak_syms)); |
---|
3981 | weak->next = weak_decls; |
---|
3982 | weak->name = permalloc (strlen (name) + 1); |
---|
3983 | strcpy (weak->name, name); |
---|
3984 | |
---|
3985 | if (what != ps_value) |
---|
3986 | weak->value = NULL_PTR; |
---|
3987 | |
---|
3988 | else |
---|
3989 | { |
---|
3990 | weak->value = permalloc (strlen (value) + 1); |
---|
3991 | strcpy (weak->value, value); |
---|
3992 | } |
---|
3993 | |
---|
3994 | weak_decls = weak; |
---|
3995 | } |
---|
3996 | else if (! (what == ps_done || what == ps_start)) |
---|
3997 | warning ("malformed `#pragma weak'"); |
---|
3998 | #endif /* HANDLE_PRAGMA_WEAK */ |
---|
3999 | } |
---|
4000 | |
---|
4001 | /* Declare DECL to be a weak symbol. */ |
---|
4002 | |
---|
4003 | void |
---|
4004 | declare_weak (decl) |
---|
4005 | tree decl; |
---|
4006 | { |
---|
4007 | if (! TREE_PUBLIC (decl)) |
---|
4008 | error_with_decl (decl, "weak declaration of `%s' must be public"); |
---|
4009 | else if (TREE_ASM_WRITTEN (decl)) |
---|
4010 | error_with_decl (decl, "weak declaration of `%s' must precede definition"); |
---|
4011 | else if (SUPPORTS_WEAK) |
---|
4012 | DECL_WEAK (decl) = 1; |
---|
4013 | } |
---|
4014 | |
---|
4015 | /* Emit any pending weak declarations. */ |
---|
4016 | |
---|
4017 | void |
---|
4018 | weak_finish () |
---|
4019 | { |
---|
4020 | #ifdef HANDLE_PRAGMA_WEAK |
---|
4021 | if (HANDLE_PRAGMA_WEAK) |
---|
4022 | { |
---|
4023 | struct weak_syms *t; |
---|
4024 | for (t = weak_decls; t; t = t->next) |
---|
4025 | { |
---|
4026 | ASM_WEAKEN_LABEL (asm_out_file, t->name); |
---|
4027 | if (t->value) |
---|
4028 | ASM_OUTPUT_DEF (asm_out_file, t->name, t->value); |
---|
4029 | } |
---|
4030 | } |
---|
4031 | #endif |
---|
4032 | } |
---|
4033 | |
---|
4034 | void |
---|
4035 | assemble_alias (decl, target) |
---|
4036 | tree decl, target; |
---|
4037 | { |
---|
4038 | #ifdef ASM_OUTPUT_DEF |
---|
4039 | char *name; |
---|
4040 | |
---|
4041 | make_decl_rtl (decl, (char*)0, 1); |
---|
4042 | name = XSTR (XEXP (DECL_RTL (decl), 0), 0); |
---|
4043 | |
---|
4044 | /* Make name accessible from other files, if appropriate. */ |
---|
4045 | |
---|
4046 | if (TREE_PUBLIC (decl)) |
---|
4047 | { |
---|
4048 | #ifdef ASM_WEAKEN_LABEL |
---|
4049 | if (DECL_WEAK (decl)) |
---|
4050 | ASM_WEAKEN_LABEL (asm_out_file, name); |
---|
4051 | else |
---|
4052 | #endif |
---|
4053 | if (output_bytecode) |
---|
4054 | BC_GLOBALIZE_LABEL (asm_out_file, name); |
---|
4055 | else |
---|
4056 | ASM_GLOBALIZE_LABEL (asm_out_file, name); |
---|
4057 | } |
---|
4058 | |
---|
4059 | ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target)); |
---|
4060 | TREE_ASM_WRITTEN (decl) = 1; |
---|
4061 | #else |
---|
4062 | warning ("alias definitions not supported in this configuration"); |
---|
4063 | #endif |
---|
4064 | } |
---|