Annotation of gcc/varasm.c, revision 1.1.1.6

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.