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