Annotation of GNUtools/cc/varasm.c, revision 1.1

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