Annotation of gcc/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 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 "expr.h"
        !            36: #include "hard-reg-set.h"
        !            37: #include "regs.h"
        !            38: 
        !            39: #include "obstack.h"
        !            40: 
        !            41: #ifndef ASM_STABS_OP
        !            42: #define ASM_STABS_OP ".stabs"
        !            43: #endif
        !            44: 
        !            45: /* File in which assembler code is being written.  */
        !            46: 
        !            47: extern FILE *asm_out_file;
        !            48: 
        !            49: /* The (assembler) name of the first globally-visible object output.  */
        !            50: char *first_global_object_name;
        !            51: 
        !            52: extern struct obstack *current_obstack;
        !            53: extern struct obstack *saveable_obstack;
        !            54: extern struct obstack permanent_obstack;
        !            55: #define obstack_chunk_alloc xmalloc
        !            56: extern int xmalloc ();
        !            57: 
        !            58: /* Number for making the label on the next
        !            59:    constant that is stored in memory.  */
        !            60: 
        !            61: int const_labelno;
        !            62: 
        !            63: /* Number for making the label on the next
        !            64:    static variable internal to a function.  */
        !            65: 
        !            66: int var_labelno;
        !            67: 
        !            68: /* Nonzero if at least one function definition has been seen.  */
        !            69: static int function_defined;
        !            70: 
        !            71: extern FILE *asm_out_file;
        !            72: 
        !            73: static char *compare_constant_1 ();
        !            74: static void record_constant_1 ();
        !            75: void output_constant_pool ();
        !            76: void assemble_name ();
        !            77: int output_addressed_constants ();
        !            78: void output_constant ();
        !            79: void output_constructor ();
        !            80: 
        !            81: #ifdef EXTRA_SECTIONS
        !            82: static enum in_section {no_section, in_text, in_data, EXTRA_SECTIONS} in_section
        !            83:   = no_section;
        !            84: #else
        !            85: static enum in_section {no_section, in_text, in_data} in_section
        !            86:   = no_section;
        !            87: #endif
        !            88: 
        !            89: /* Define functions like text_section for any extra sections.  */
        !            90: #ifdef EXTRA_SECTION_FUNCTIONS
        !            91: EXTRA_SECTION_FUNCTIONS
        !            92: #endif
        !            93: 
        !            94: /* Tell assembler to switch to text section.  */
        !            95: 
        !            96: void
        !            97: text_section ()
        !            98: {
        !            99:   if (in_section != in_text)
        !           100:     {
        !           101:       fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
        !           102:       in_section = in_text;
        !           103:     }
        !           104: }
        !           105: 
        !           106: /* Tell assembler to switch to read-only data section.  This is normally
        !           107:    the text section.  */
        !           108: 
        !           109: void
        !           110: readonly_data_section ()
        !           111: {
        !           112: #ifdef READONLY_DATA_SECTION
        !           113:   READONLY_DATA_SECTION ();
        !           114: #else
        !           115:   text_section ();
        !           116: #endif
        !           117: }
        !           118: 
        !           119: /* Tell assembler to switch to data section.  */
        !           120: 
        !           121: void
        !           122: data_section ()
        !           123: {
        !           124:   if (in_section != in_data)
        !           125:     {
        !           126:       if (flag_shared_data)
        !           127:        {
        !           128: #ifdef SHARED_SECTION_ASM_OP
        !           129:          fprintf (asm_out_file, "%s\n", SHARED_SECTION_ASM_OP);
        !           130: #else
        !           131:          fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
        !           132: #endif
        !           133:        }
        !           134:       else
        !           135:        fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
        !           136: 
        !           137:       in_section = in_data;
        !           138:     }
        !           139: }
        !           140: 
        !           141: /* Determine if we're in the text section. */
        !           142: 
        !           143: int
        !           144: in_text_section ()
        !           145: {
        !           146:   return in_section == in_text;
        !           147: }
        !           148: 
        !           149: /* Create the rtl to represent a function, for a function definition.
        !           150:    DECL is a FUNCTION_DECL node which describes which function.
        !           151:    The rtl is stored into DECL.  */
        !           152: 
        !           153: void
        !           154: make_function_rtl (decl)
        !           155:      tree decl;
        !           156: {
        !           157:   char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
        !           158: 
        !           159:   /* Rename a nested function to avoid conflicts.  */
        !           160:   if (decl_function_context (decl) != 0
        !           161:       && DECL_INITIAL (decl) != 0
        !           162:       && DECL_RTL (decl) == 0)
        !           163:     {
        !           164:       char *label;
        !           165: 
        !           166:       name = IDENTIFIER_POINTER (DECL_NAME (decl));
        !           167:       ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
        !           168:       name = obstack_copy0 (saveable_obstack, label, strlen (label));
        !           169:       var_labelno++;
        !           170:     }
        !           171: 
        !           172:   if (DECL_RTL (decl) == 0)
        !           173:     {
        !           174:       DECL_RTL (decl)
        !           175:        = gen_rtx (MEM, DECL_MODE (decl),
        !           176:                   gen_rtx (SYMBOL_REF, Pmode, name));
        !           177: 
        !           178:       /* Optionally set flags or add text to the name to record information
        !           179:         such as that it is a function name.  If the name is changed, the macro
        !           180:         ASM_OUTPUT_LABELREF will have to know how to strip this information.
        !           181:         And if it finds a * at the beginning after doing so, it must handle
        !           182:         that too.  */
        !           183: #ifdef ENCODE_SECTION_INFO
        !           184:       ENCODE_SECTION_INFO (decl);
        !           185: #endif
        !           186:     }
        !           187: 
        !           188:   /* Record at least one function has been defined.  */
        !           189:   function_defined = 1;
        !           190: }
        !           191: 
        !           192: /* Decode an `asm' spec for a declaration as a register name.
        !           193:    Return the register number, or -1 if nothing specified,
        !           194:    or -2 if the name is not a register.  */
        !           195: 
        !           196: int
        !           197: decode_reg_name (asmspec)
        !           198:      char *asmspec;
        !           199: {
        !           200:   if (asmspec != 0)
        !           201:     {
        !           202:       int i;
        !           203: 
        !           204:       /* Allow a decimal number as a "register name".  */
        !           205:       for (i = strlen (asmspec) - 1; i >= 0; i--)
        !           206:        if (! (asmspec[i] >= '0' && asmspec[i] <= '9'))
        !           207:          break;
        !           208:       if (asmspec[0] != 0 && i < 0)
        !           209:        {
        !           210:          i = atoi (asmspec);
        !           211:          if (i < FIRST_PSEUDO_REGISTER && i >= 0)
        !           212:            return i;
        !           213:          else
        !           214:            return -2;
        !           215:        }
        !           216: 
        !           217:       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        !           218:        if (reg_names[i][0] && ! strcmp (asmspec, reg_names[i]))
        !           219:          return i;
        !           220: 
        !           221:       if (asmspec[0] == '%')
        !           222:        for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        !           223:          if (reg_names[i][0] && ! strcmp (asmspec + 1, reg_names[i]))
        !           224:            return i;
        !           225: 
        !           226: #ifdef ADDITIONAL_REGISTER_NAMES
        !           227:       {
        !           228:        static struct { char *name; int number; } table[]
        !           229:          = ADDITIONAL_REGISTER_NAMES;
        !           230: 
        !           231:        for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
        !           232:          if (! strcmp (asmspec, table[i].name))
        !           233:            return table[i].number;
        !           234: 
        !           235:        if (asmspec[0] == '%')
        !           236:          for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
        !           237:            if (! strcmp (asmspec + 1, table[i].name))
        !           238:              return table[i].number;
        !           239:       }
        !           240: #endif /* ADDITIONAL_REGISTER_NAMES */
        !           241: 
        !           242:       return -2;
        !           243:     }
        !           244: 
        !           245:   return -1;
        !           246: }
        !           247: 
        !           248: /* Create the DECL_RTL for a declaration for a static or external variable
        !           249:    or static or external function.
        !           250:    ASMSPEC, if not 0, is the string which the user specified
        !           251:    as the assembler symbol name.
        !           252:    TOP_LEVEL is nonzero if this is a file-scope variable.
        !           253: 
        !           254:    This is never called for PARM_DECL nodes.  */
        !           255: 
        !           256: void
        !           257: make_decl_rtl (decl, asmspec, top_level)
        !           258:      tree decl;
        !           259:      char *asmspec;
        !           260:      int top_level;
        !           261: {
        !           262:   register char *name;
        !           263:   int reg_number = decode_reg_name (asmspec);
        !           264: 
        !           265:   if (DECL_ASSEMBLER_NAME (decl) != NULL_TREE)
        !           266:     name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
        !           267: 
        !           268:   if (reg_number == -2)
        !           269:     {
        !           270:       /* ASMSPEC is given, and not the name of a register.  */
        !           271:       name = (char *) obstack_alloc (saveable_obstack,
        !           272:                                     strlen (asmspec) + 2);
        !           273:       name[0] = '*';
        !           274:       strcpy (&name[1], asmspec);
        !           275:     }
        !           276: 
        !           277:   /* For a duplicate declaration, we can be called twice on the
        !           278:      same DECL node.  Don't alter the RTL already made
        !           279:      unless the old mode is wrong (which can happen when
        !           280:      the previous rtl was made when the type was incomplete).  */
        !           281:   if (DECL_RTL (decl) == 0
        !           282:       || GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
        !           283:     {
        !           284:       DECL_RTL (decl) = 0;
        !           285: 
        !           286:       /* First detect errors in declaring global registers.  */
        !           287:       if (TREE_REGDECL (decl) && reg_number == -1)
        !           288:        error_with_decl (decl,
        !           289:                         "register name not specified for `%s'");
        !           290:       else if (TREE_REGDECL (decl) && reg_number == -2)
        !           291:        error_with_decl (decl,
        !           292:                         "invalid register name for `%s'");
        !           293:       else if (reg_number >= 0 && ! TREE_REGDECL (decl))
        !           294:        error_with_decl (decl,
        !           295:                         "register name given for non-register variable `%s'");
        !           296:       else if (TREE_REGDECL (decl) && TREE_CODE (decl) == FUNCTION_DECL)
        !           297:        error ("function declared `register'");
        !           298:       else if (TREE_REGDECL (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
        !           299:        error_with_decl (decl, "data type of `%s' isn't suitable for a register");
        !           300:       /* Now handle properly declared static register variables.  */
        !           301:       else if (TREE_REGDECL (decl))
        !           302:        {
        !           303:          int nregs;
        !           304: #if 0 /* yylex should print the warning for this */
        !           305:          if (pedantic)
        !           306:            pedwarn ("ANSI C forbids global register variables");
        !           307: #endif
        !           308:          if (DECL_INITIAL (decl) != 0 && top_level)
        !           309:            {
        !           310:              DECL_INITIAL (decl) = 0;
        !           311:              error ("global register variable has initial value");
        !           312:            }
        !           313:          if (fixed_regs[reg_number] == 0
        !           314:              && function_defined && top_level)
        !           315:            error ("global register variable follows a function definition");
        !           316:          if (TREE_THIS_VOLATILE (decl))
        !           317:            warning ("volatile register variables don't work as you might wish");
        !           318:          DECL_RTL (decl) = gen_rtx (REG, DECL_MODE (decl), reg_number);
        !           319:          REG_USERVAR_P (DECL_RTL (decl)) = 1;
        !           320: 
        !           321:          if (top_level)
        !           322:            {
        !           323:              /* Make this register fixed, so not usable for anything else.  */
        !           324:              nregs = HARD_REGNO_NREGS (reg_number, DECL_MODE (decl));
        !           325:              while (nregs > 0)
        !           326:                global_regs[reg_number + --nregs] = 1;
        !           327:              init_reg_sets_1 ();
        !           328:            }
        !           329:        }
        !           330: 
        !           331:       /* Now handle ordinary static variables and functions (in memory).
        !           332:         Also handle vars declared register invalidly.  */
        !           333:       if (DECL_RTL (decl) == 0)
        !           334:        {
        !           335:          /* Can't use just the variable's own name for a variable
        !           336:             whose scope is less than the whole file.
        !           337:             Concatenate a distinguishing number.  */
        !           338:          if (!top_level && !TREE_EXTERNAL (decl) && asmspec == 0)
        !           339:            {
        !           340:              char *label;
        !           341: 
        !           342:              ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
        !           343:              name = obstack_copy0 (saveable_obstack, label, strlen (label));
        !           344:              var_labelno++;
        !           345:            }
        !           346: 
        !           347:          DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl),
        !           348:                                     gen_rtx (SYMBOL_REF, Pmode, name));
        !           349:          if (TREE_THIS_VOLATILE (decl))
        !           350:            MEM_VOLATILE_P (DECL_RTL (decl)) = 1;
        !           351:          if (TREE_READONLY (decl))
        !           352:            RTX_UNCHANGING_P (DECL_RTL (decl)) = 1;
        !           353:          MEM_IN_STRUCT_P (DECL_RTL (decl))
        !           354:            = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
        !           355:               || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
        !           356:               || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE);
        !           357: 
        !           358:          /* Optionally set flags or add text to the name to record information
        !           359:             such as that it is a function name.
        !           360:             If the name is changed, the macro ASM_OUTPUT_LABELREF
        !           361:             will have to know how to strip this information.
        !           362:             And if it finds a * at the beginning after doing so,
        !           363:             it must handle that too.  */
        !           364: #ifdef ENCODE_SECTION_INFO
        !           365:          ENCODE_SECTION_INFO (decl);
        !           366: #endif
        !           367:        }
        !           368:     }
        !           369: }
        !           370: 
        !           371: /* Output a string of literal assembler code
        !           372:    for an `asm' keyword used between functions.  */
        !           373: 
        !           374: void
        !           375: assemble_asm (string)
        !           376:      tree string;
        !           377: {
        !           378:   app_enable ();
        !           379: 
        !           380:   if (TREE_CODE (string) == ADDR_EXPR)
        !           381:     string = TREE_OPERAND (string, 0);
        !           382: 
        !           383:   fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));
        !           384: }
        !           385: 
        !           386: /* Tiemann: please get rid of this conditional and put appropriate
        !           387:    definitions in each of the files that should have them.
        !           388:    The type of debugging format is not the right parameter to
        !           389:    control how some other aspect of assembler output is done.  */
        !           390: 
        !           391: #if !(defined(DBX_DEBUGGING_INFO) && !defined(FASCIST_ASSEMBLER))
        !           392: #ifndef ASM_OUTPUT_CONSTRUCTOR
        !           393: #define ASM_OUTPUT_CONSTRUCTOR(file, name)
        !           394: #endif
        !           395: #ifndef ASM_OUTPUT_DESTRUCTOR
        !           396: #define ASM_OUTPUT_DESTRUCTOR(file, name)
        !           397: #endif
        !           398: #endif
        !           399: 
        !           400: /* Record an element in the table of global destructors.
        !           401:    How this is done depends on what sort of assembler and linker
        !           402:    are in use.
        !           403: 
        !           404:    NAME should be the name of a global function to be called
        !           405:    at exit time.  This name is output using assemble_name.  */
        !           406: 
        !           407: void
        !           408: assemble_destructor (name)
        !           409:      char *name;
        !           410: {
        !           411: #ifdef ASM_OUTPUT_DESTRUCTOR
        !           412:   ASM_OUTPUT_DESTRUCTOR (asm_out_file, name);
        !           413: #else
        !           414:   if (flag_gnu_linker)
        !           415:     {
        !           416:       /* Now tell GNU LD that this is part of the static destructor set.  */
        !           417:       /* This code works for any machine provided you use GNU as/ld.  */
        !           418:       fprintf (asm_out_file, "%s \"___DTOR_LIST__\",22,0,0,", ASM_STABS_OP);
        !           419:       assemble_name (asm_out_file, name);
        !           420:       fputc ('\n', asm_out_file);
        !           421:     }
        !           422: #endif
        !           423: }
        !           424: 
        !           425: /* Likewise for global constructors.  */
        !           426: 
        !           427: void
        !           428: assemble_constructor (name)
        !           429:      char *name;
        !           430: {
        !           431: #ifdef ASM_OUTPUT_CONSTRUCTOR
        !           432:   ASM_OUTPUT_CONSTRUCTOR (asm_out_file, name);
        !           433: #else
        !           434:   if (flag_gnu_linker)
        !           435:     {
        !           436:       /* Now tell GNU LD that this is part of the static constructor set.  */
        !           437:       /* This code works for any machine provided you use GNU as/ld.  */
        !           438:       fprintf (asm_out_file, "%s \"___CTOR_LIST__\",22,0,0,", ASM_STABS_OP);
        !           439:       assemble_name (asm_out_file, name);
        !           440:       fputc ('\n', asm_out_file);
        !           441:     }
        !           442: #endif
        !           443: }
        !           444: 
        !           445: /* Likewise for entries we want to record for garbage collection.
        !           446:    Garbage collection is still under development.  */
        !           447: 
        !           448: void
        !           449: assemble_gc_entry (name)
        !           450:      char *name;
        !           451: {
        !           452: #ifdef ASM_OUTPUT_GC_ENTRY
        !           453:   ASM_OUTPUT_GC_ENTRY (asm_out_file, name);
        !           454: #else
        !           455:   if (flag_gnu_linker)
        !           456:     {
        !           457:       /* Now tell GNU LD that this is part of the static constructor set.  */
        !           458:       fprintf (asm_out_file, "%s \"___PTR_LIST__\",22,0,0,", ASM_STABS_OP);
        !           459:       assemble_name (asm_out_file, name);
        !           460:       fputc ('\n', asm_out_file);
        !           461:     }
        !           462: #endif
        !           463: }
        !           464: 
        !           465: /* Output assembler code for the constant pool of a function and associated
        !           466:    with defining the name of the function.  DECL describes the function.
        !           467:    NAME is the function's name.  For the constant pool, we use the current
        !           468:    constant pool data.  */
        !           469: 
        !           470: void
        !           471: assemble_start_function (decl, fnname)
        !           472:      tree decl;
        !           473:      char *fnname;
        !           474: {
        !           475:   int align;
        !           476: 
        !           477:   /* The following code does not need preprocessing in the assembler.  */
        !           478: 
        !           479:   app_disable ();
        !           480: 
        !           481:   output_constant_pool (fnname, decl);
        !           482: 
        !           483:   text_section ();
        !           484: 
        !           485: 
        !           486:   /* Tell assembler to move to target machine's alignment for functions.  */
        !           487:   align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
        !           488:   if (align > 0)
        !           489:     ASM_OUTPUT_ALIGN (asm_out_file, align);
        !           490: 
        !           491: #ifdef ASM_OUTPUT_FUNCTION_PREFIX
        !           492:   ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname);
        !           493: #endif
        !           494: 
        !           495: #ifdef SDB_DEBUGGING_INFO
        !           496:   /* Output SDB definition of the function.  */
        !           497:   if (write_symbols == SDB_DEBUG)
        !           498:     sdbout_mark_begin_function ();
        !           499: #endif
        !           500: 
        !           501: #ifdef DBX_DEBUGGING_INFO
        !           502:   /* Output SDB definition of the function.  */
        !           503:   if (write_symbols == DBX_DEBUG)
        !           504:     dbxout_begin_function ();
        !           505: #endif
        !           506: 
        !           507:   /* Make function name accessible from other files, if appropriate.  */
        !           508: 
        !           509:   if (TREE_PUBLIC (decl))
        !           510:     {
        !           511:       if (!first_global_object_name)
        !           512:        first_global_object_name = fnname + (fnname[0] == '*');
        !           513:       ASM_GLOBALIZE_LABEL (asm_out_file, fnname);
        !           514:     }
        !           515: 
        !           516:   /* Do any machine/system dependent processing of the function name */
        !           517: #ifdef ASM_DECLARE_FUNCTION_NAME
        !           518:   ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
        !           519: #else
        !           520:   /* Standard thing is just output label for the function.  */
        !           521:   ASM_OUTPUT_LABEL (asm_out_file, fnname);
        !           522: #endif /* ASM_DECLARE_FUNCTION_NAME */
        !           523: }
        !           524: 
        !           525: /* Output assembler code associated with defining the size of the
        !           526:    function.  DECL describes the function.  NAME is the function's name.  */
        !           527: 
        !           528: void
        !           529: assemble_end_function (decl, fnname)
        !           530:      tree decl;
        !           531:      char *fnname;
        !           532: {
        !           533: #ifdef ASM_DECLARE_FUNCTION_SIZE
        !           534:   ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);
        !           535: #endif
        !           536: }
        !           537: 
        !           538: /* Assemble code to leave SIZE bytes of zeros.  */
        !           539: 
        !           540: void
        !           541: assemble_zeros (size)
        !           542:      int size;
        !           543: {
        !           544: #ifdef ASM_NO_SKIP_IN_TEXT
        !           545:   /* The `space' pseudo in the text section outputs nop insns rather than 0s,
        !           546:      so we must output 0s explicitly in the text section.  */
        !           547:   if (ASM_NO_SKIP_IN_TEXT && in_text_section ())
        !           548:     {
        !           549:       int i;
        !           550: 
        !           551:       for (i = 0; i < size - 20; i += 20)
        !           552:        {
        !           553: #ifdef ASM_BYTE_OP
        !           554:          fprintf (asm_out_file,
        !           555:                   "%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);
        !           556: #else
        !           557:          fprintf (asm_out_file,
        !           558:                   "\tbyte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n");
        !           559: #endif
        !           560:        }
        !           561:       if (i < size)
        !           562:         {
        !           563: #ifdef ASM_BYTE_OP
        !           564:          fprintf (asm_out_file, "%s 0", ASM_BYTE_OP);
        !           565: #else
        !           566:          fprintf (asm_out_file, "\tbyte 0");
        !           567: #endif
        !           568:          i++;
        !           569:          for (; i < size; i++)
        !           570:            fprintf (asm_out_file, ",0");
        !           571:          fprintf (asm_out_file, "\n");
        !           572:        }
        !           573:     }
        !           574:   else
        !           575: #endif
        !           576:     ASM_OUTPUT_SKIP (asm_out_file, size);
        !           577: }
        !           578: 
        !           579: /* Assemble a string constant with the specified C string as contents.  */
        !           580: 
        !           581: void
        !           582: assemble_string (p, size)
        !           583:      unsigned char *p;
        !           584:      int size;
        !           585: {
        !           586:   register int i;
        !           587:   int pos = 0;
        !           588:   int maximum = 2000;
        !           589: 
        !           590:   /* If the string is very long, split it up.  */
        !           591: 
        !           592:   while (pos < size)
        !           593:     {
        !           594:       int thissize = size - pos;
        !           595:       if (thissize > maximum)
        !           596:        thissize = maximum;
        !           597: 
        !           598: #ifdef ASM_OUTPUT_ASCII
        !           599:       ASM_OUTPUT_ASCII (asm_out_file, p, thissize);
        !           600: #else
        !           601:       fprintf (asm_out_file, "\t.ascii \"");
        !           602: 
        !           603:       for (i = 0; i < thissize; i++)
        !           604:        {
        !           605:          register int c = p[i];
        !           606:          if (c == '\"' || c == '\\')
        !           607:            putc ('\\', asm_out_file);
        !           608:          if (c >= ' ' && c < 0177)
        !           609:            putc (c, asm_out_file);
        !           610:          else
        !           611:            {
        !           612:              fprintf (asm_out_file, "\\%o", c);
        !           613:              /* After an octal-escape, if a digit follows,
        !           614:                 terminate one string constant and start another.
        !           615:                 The Vax assembler fails to stop reading the escape
        !           616:                 after three digits, so this is the only way we
        !           617:                 can get it to parse the data properly.  */
        !           618:              if (i < thissize - 1
        !           619:                  && p[i + 1] >= '0' && p[i + 1] <= '9')
        !           620:                fprintf (asm_out_file, "\"\n\t.ascii \"");
        !           621:            }
        !           622:        }
        !           623:       fprintf (asm_out_file, "\"\n");
        !           624: #endif /* no ASM_OUTPUT_ASCII */
        !           625: 
        !           626:       pos += thissize;
        !           627:       p += thissize;
        !           628:     }
        !           629: }
        !           630: 
        !           631: /* Assemble everything that is needed for a variable or function declaration.
        !           632:    Not used for automatic variables, and not used for function definitions.
        !           633:    Should not be called for variables of incomplete structure type.
        !           634: 
        !           635:    TOP_LEVEL is nonzero if this variable has file scope.
        !           636:    AT_END is nonzero if this is the special handling, at end of compilation,
        !           637:    to define things that have had only tentative definitions.  */
        !           638: 
        !           639: void
        !           640: assemble_variable (decl, top_level, at_end)
        !           641:      tree decl;
        !           642:      int top_level;
        !           643:      int at_end;
        !           644: {
        !           645:   register char *name;
        !           646:   int align;
        !           647:   tree size_tree;
        !           648:   int reloc = 0;
        !           649: 
        !           650:   if (GET_CODE (DECL_RTL (decl)) == REG)
        !           651:     {
        !           652:       /* Do output symbol info for global register variables, but do nothing
        !           653:         else for them.  */
        !           654: 
        !           655:       if (TREE_ASM_WRITTEN (decl))
        !           656:        return;
        !           657:       TREE_ASM_WRITTEN (decl) = 1;
        !           658: 
        !           659: #ifdef DBX_DEBUGGING_INFO
        !           660:       /* File-scope global variables are output here.  */
        !           661:       if (write_symbols == DBX_DEBUG && top_level)
        !           662:        dbxout_symbol (decl, 0);
        !           663: #endif
        !           664: #ifdef SDB_DEBUGGING_INFO
        !           665:       if (write_symbols == SDB_DEBUG && top_level
        !           666:          /* Leave initialized global vars for end of compilation;
        !           667:             see comment in compile_file.  */
        !           668:          && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0))
        !           669:        sdbout_symbol (decl, 0);
        !           670: #endif
        !           671: 
        !           672:       /* Don't output any DWARF debugging information for variables here.
        !           673:         In the case of local variables, the information for them is output
        !           674:         when we do our recursive traversal of the tree representation for
        !           675:         the entire containing function.  In the case of file-scope variables,
        !           676:         we output information for all of them at the very end of compilation
        !           677:         while we are doing our final traversal of the chain of file-scope
        !           678:         declarations.  */
        !           679: 
        !           680:       return;
        !           681:     }
        !           682: 
        !           683:   /* Normally no need to say anything for external references,
        !           684:      since assembler considers all undefined symbols external.  */
        !           685: 
        !           686:   if (TREE_EXTERNAL (decl))
        !           687:     return;
        !           688: 
        !           689:   /* Output no assembler code for a function declaration.
        !           690:      Only definitions of functions output anything.  */
        !           691: 
        !           692:   if (TREE_CODE (decl) == FUNCTION_DECL)
        !           693:     return;
        !           694: 
        !           695:   /* If type was incomplete when the variable was declared,
        !           696:      see if it is complete now.  */
        !           697: 
        !           698:   if (DECL_SIZE (decl) == 0)
        !           699:     layout_decl (decl, 0);
        !           700: 
        !           701:   /* Still incomplete => don't allocate it; treat the tentative defn
        !           702:      (which is what it must have been) as an `extern' reference.  */
        !           703: 
        !           704:   if (DECL_SIZE (decl) == 0)
        !           705:     {
        !           706:       error_with_file_and_line (DECL_SOURCE_FILE (decl),
        !           707:                                DECL_SOURCE_LINE (decl),
        !           708:                                "storage size of static var `%s' isn't known",
        !           709:                                IDENTIFIER_POINTER (DECL_NAME (decl)));
        !           710:       return;
        !           711:     }
        !           712: 
        !           713:   /* The first declaration of a variable that comes through this function
        !           714:      decides whether it is global (in C, has external linkage)
        !           715:      or local (in C, has internal linkage).  So do nothing more
        !           716:      if this function has already run.  */
        !           717: 
        !           718:   if (TREE_ASM_WRITTEN (decl))
        !           719:     return;
        !           720: 
        !           721:   TREE_ASM_WRITTEN (decl) = 1;
        !           722: 
        !           723: #ifdef DBX_DEBUGGING_INFO
        !           724:   /* File-scope global variables are output here.  */
        !           725:   if (write_symbols == DBX_DEBUG && top_level)
        !           726:     dbxout_symbol (decl, 0);
        !           727: #endif
        !           728: #ifdef SDB_DEBUGGING_INFO
        !           729:   if (write_symbols == SDB_DEBUG && top_level
        !           730:       /* Leave initialized global vars for end of compilation;
        !           731:         see comment in compile_file.  */
        !           732:       && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0))
        !           733:     sdbout_symbol (decl, 0);
        !           734: #endif
        !           735: 
        !           736:   /* Don't output any DWARF debugging information for variables here.
        !           737:      In the case of local variables, the information for them is output
        !           738:      when we do our recursive traversal of the tree representation for
        !           739:      the entire containing function.  In the case of file-scope variables,
        !           740:      we output information for all of them at the very end of compilation
        !           741:      while we are doing our final traversal of the chain of file-scope
        !           742:      declarations.  */
        !           743: 
        !           744:   /* If storage size is erroneously variable, just continue.
        !           745:      Error message was already made.  */
        !           746: 
        !           747:   if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
        !           748:     return;
        !           749: 
        !           750:   app_disable ();
        !           751: 
        !           752:   /* This is better than explicit arithmetic, since it avoids overflow.  */
        !           753:   size_tree = size_binop (CEIL_DIV_EXPR,
        !           754:                          DECL_SIZE (decl), size_int (BITS_PER_UNIT));
        !           755: 
        !           756:   if (TREE_INT_CST_HIGH (size_tree) != 0)
        !           757:     {
        !           758:       error_with_decl (decl, "size of variable `%s' is too large");
        !           759:       return;
        !           760:     }
        !           761: 
        !           762:   name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
        !           763: 
        !           764:   /* Handle uninitialized definitions.  */
        !           765: 
        !           766:   /* ANSI specifies that a tentative definition which is not merged with
        !           767:      a non-tentative definition behaves exactly like a definition with an
        !           768:      initializer equal to zero.  (Section 3.7.2)
        !           769:      -fno-common gives strict ANSI behavior.  Usually you don't want it.  */
        !           770:   if (! flag_no_common
        !           771:       && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
        !           772:     {
        !           773:       int size = TREE_INT_CST_LOW (size_tree);
        !           774:       int rounded = size;
        !           775: 
        !           776:       if (TREE_INT_CST_HIGH (size_tree) != 0)
        !           777:        error_with_decl (decl, "size of variable `%s' is too large");
        !           778:       /* Don't allocate zero bytes of common,
        !           779:         since that means "undefined external" in the linker.  */
        !           780:       if (size == 0) rounded = 1;
        !           781:       /* Round size up to multiple of BIGGEST_ALIGNMENT bits
        !           782:         so that each uninitialized object starts on such a boundary.  */
        !           783:       rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
        !           784:       rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
        !           785:                 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
        !           786: #if 0
        !           787:       if (flag_shared_data)
        !           788:        data_section ();
        !           789: #endif
        !           790:       if (TREE_PUBLIC (decl))
        !           791:        {
        !           792: #ifdef ASM_OUTPUT_SHARED_COMMON
        !           793:          if (flag_shared_data)
        !           794:            ASM_OUTPUT_SHARED_COMMON (asm_out_file, name, size, rounded);
        !           795:          else
        !           796: #endif
        !           797: #ifdef ASM_OUTPUT_ALIGNED_COMMON
        !           798:            ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
        !           799:                                       DECL_ALIGN (decl));
        !           800: #else
        !           801:            ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);
        !           802: #endif
        !           803:        }
        !           804:       else
        !           805:        {
        !           806: #ifdef ASM_OUTPUT_SHARED_LOCAL
        !           807:          if (flag_shared_data)
        !           808:            ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded);
        !           809:          else
        !           810: #endif
        !           811: #ifdef ASM_OUTPUT_ALIGNED_LOCAL
        !           812:            ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
        !           813:                                      DECL_ALIGN (decl));
        !           814: #else
        !           815:            ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
        !           816: #endif
        !           817:        }
        !           818:       return;
        !           819:     }
        !           820: 
        !           821:   /* Handle initialized definitions.  */
        !           822: 
        !           823:   /* First make the assembler name(s) global if appropriate.  */
        !           824:   if (TREE_PUBLIC (decl) && DECL_NAME (decl))
        !           825:     {
        !           826:       if (!first_global_object_name)
        !           827:        first_global_object_name = name + (name[0] == '*');
        !           828:       ASM_GLOBALIZE_LABEL (asm_out_file, name);
        !           829:     }
        !           830: #if 0
        !           831:   for (d = equivalents; d; d = TREE_CHAIN (d))
        !           832:     {
        !           833:       tree e = TREE_VALUE (d);
        !           834:       if (TREE_PUBLIC (e) && DECL_NAME (e))
        !           835:        ASM_GLOBALIZE_LABEL (asm_out_file,
        !           836:                             XSTR (XEXP (DECL_RTL (e), 0), 0));
        !           837:     }
        !           838: #endif
        !           839: 
        !           840:   /* Output any data that we will need to use the address of.  */
        !           841:   if (DECL_INITIAL (decl))
        !           842:     reloc = output_addressed_constants (DECL_INITIAL (decl));
        !           843: 
        !           844:   /* Switch to the proper section for this data.  */
        !           845: #ifdef SELECT_SECTION
        !           846:   SELECT_SECTION (decl, reloc);
        !           847: #else
        !           848:   if (TREE_READONLY (decl)
        !           849:       && ! TREE_THIS_VOLATILE (decl)
        !           850:       && ! (flag_pic && reloc))
        !           851:     readonly_data_section ();
        !           852:   else
        !           853:     data_section ();
        !           854: #endif
        !           855: 
        !           856:   /* Compute and output the alignment of this data.  */
        !           857: 
        !           858:   align = DECL_ALIGN (decl);
        !           859:   /* Some object file formats have a maximum alignment which they support.
        !           860:      In particular, a.out format supports a maximum alignment of 4.  */
        !           861: #ifndef MAX_OFILE_ALIGNMENT
        !           862: #define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT
        !           863: #endif
        !           864:   if (align > MAX_OFILE_ALIGNMENT)
        !           865:     {
        !           866:       warning_with_decl (decl,
        !           867:          "alignment of `%s' is greater than maximum object file alignment");
        !           868:       align = MAX_OFILE_ALIGNMENT;
        !           869:     }
        !           870: #ifdef DATA_ALIGNMENT
        !           871:   /* On some machines, it is good to increase alignment sometimes.  */
        !           872:   align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
        !           873: #endif
        !           874: #ifdef CONSTANT_ALIGNMENT
        !           875:   if (DECL_INITIAL (decl))
        !           876:     align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
        !           877: #endif
        !           878: 
        !           879:   /* Reset the alignment in case we have made it tighter, so we can benefit
        !           880:      from it in get_pointer_alignment.  */
        !           881:   DECL_ALIGN (decl) = align;
        !           882: 
        !           883:   if (align > BITS_PER_UNIT)
        !           884:     ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
        !           885: 
        !           886:   /* Do any machine/system dependent processing of the object.  */
        !           887: #ifdef ASM_DECLARE_OBJECT_NAME
        !           888:   ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);
        !           889: #else
        !           890:   /* Standard thing is just output label for the object.  */
        !           891:   ASM_OUTPUT_LABEL (asm_out_file, name);
        !           892: #endif /* ASM_DECLARE_OBJECT_NAME */
        !           893: 
        !           894: #if 0
        !           895:   for (d = equivalents; d; d = TREE_CHAIN (d))
        !           896:     {
        !           897:       tree e = TREE_VALUE (d);
        !           898:       ASM_OUTPUT_LABEL (asm_out_file, XSTR (XEXP (DECL_RTL (e), 0), 0));
        !           899:     }
        !           900: #endif
        !           901: 
        !           902:   if (DECL_INITIAL (decl))
        !           903:     /* Output the actual data.  */
        !           904:     output_constant (DECL_INITIAL (decl),
        !           905:                     int_size_in_bytes (TREE_TYPE (decl)));
        !           906:   else
        !           907:     /* Leave space for it.  */
        !           908:     assemble_zeros (int_size_in_bytes (TREE_TYPE (decl)));
        !           909: }
        !           910: 
        !           911: /* Output something to declare an external symbol to the assembler.
        !           912:    (Most assemblers don't need this, so we normally output nothing.)
        !           913:    Do nothing if DECL is not external.  */
        !           914: 
        !           915: void
        !           916: assemble_external (decl)
        !           917:      tree decl;
        !           918: {
        !           919: #ifdef ASM_OUTPUT_EXTERNAL
        !           920:   if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd'
        !           921:       && TREE_EXTERNAL (decl) && TREE_PUBLIC (decl))
        !           922:     {
        !           923:       rtx rtl = DECL_RTL (decl);
        !           924: 
        !           925:       if (GET_CODE (rtl) == MEM && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
        !           926:          && ! SYMBOL_REF_USED (XEXP (rtl, 0)))
        !           927:        {
        !           928:          /* Some systems do require some output.  */
        !           929:          SYMBOL_REF_USED (XEXP (rtl, 0)) = 1;
        !           930:          ASM_OUTPUT_EXTERNAL (asm_out_file, decl, XSTR (XEXP (rtl, 0), 0));
        !           931:        }
        !           932:     }
        !           933: #endif
        !           934: }
        !           935: 
        !           936: /* Similar, for calling a library function FUN.  */
        !           937: 
        !           938: void
        !           939: assemble_external_libcall (fun)
        !           940:      rtx fun;
        !           941: {
        !           942: #ifdef ASM_OUTPUT_EXTERNAL_LIBCALL
        !           943:   /* Declare library function name external when first used, if nec.  */
        !           944:   if (! SYMBOL_REF_USED (fun))
        !           945:     {
        !           946:       SYMBOL_REF_USED (fun) = 1;
        !           947:       ASM_OUTPUT_EXTERNAL_LIBCALL (asm_out_file, fun);
        !           948:     }
        !           949: #endif
        !           950: }
        !           951: 
        !           952: /* Declare the label NAME global.  */
        !           953: 
        !           954: void
        !           955: assemble_global (name)
        !           956:      char *name;
        !           957: {
        !           958:   ASM_GLOBALIZE_LABEL (asm_out_file, name);
        !           959: }
        !           960: 
        !           961: /* Assemble a label named NAME.  */
        !           962: 
        !           963: void
        !           964: assemble_label (name)
        !           965:      char *name;
        !           966: {
        !           967:   ASM_OUTPUT_LABEL (asm_out_file, name);
        !           968: }
        !           969: 
        !           970: /* Output to FILE a reference to the assembler name of a C-level name NAME.
        !           971:    If NAME starts with a *, the rest of NAME is output verbatim.
        !           972:    Otherwise NAME is transformed in an implementation-defined way
        !           973:    (usually by the addition of an underscore).
        !           974:    Many macros in the tm file are defined to call this function.  */
        !           975: 
        !           976: void
        !           977: assemble_name (file, name)
        !           978:      FILE *file;
        !           979:      char *name;
        !           980: {
        !           981:   if (name[0] == '*')
        !           982:     fputs (&name[1], file);
        !           983:   else
        !           984:     ASM_OUTPUT_LABELREF (file, name);
        !           985: }
        !           986: 
        !           987: /* Allocate SIZE bytes writable static space with a gensym name
        !           988:    and return an RTX to refer to its address.  */
        !           989: 
        !           990: rtx
        !           991: assemble_static_space (size)
        !           992:      int size;
        !           993: {
        !           994:   char name[12];
        !           995:   char *namestring;
        !           996:   rtx x;
        !           997:   /* Round size up to multiple of BIGGEST_ALIGNMENT bits
        !           998:      so that each uninitialized object starts on such a boundary.  */
        !           999:   int rounded = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
        !          1000:                 / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
        !          1001:                 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
        !          1002: 
        !          1003: #if 0
        !          1004:   if (flag_shared_data)
        !          1005:     data_section ();
        !          1006: #endif
        !          1007: 
        !          1008:   ASM_GENERATE_INTERNAL_LABEL (name, "LF", const_labelno);
        !          1009:   ++const_labelno;
        !          1010: 
        !          1011:   namestring = (char *) obstack_alloc (saveable_obstack,
        !          1012:                                       strlen (name) + 2);
        !          1013:   strcpy (namestring, name);
        !          1014: 
        !          1015:   x = gen_rtx (SYMBOL_REF, Pmode, namestring);
        !          1016: #ifdef ASM_OUTPUT_ALIGNED_LOCAL
        !          1017:   ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT);
        !          1018: #else
        !          1019:   ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
        !          1020: #endif
        !          1021:   return x;
        !          1022: }
        !          1023: 
        !          1024: /* Assemble the static constant template for function entry trampolines.
        !          1025:    This is done at most once per compilation.
        !          1026:    Returns an RTX for the address of the template.  */
        !          1027: 
        !          1028: rtx
        !          1029: assemble_trampoline_template ()
        !          1030: {
        !          1031:   char label[256];
        !          1032:   char *name;
        !          1033:   int align;
        !          1034: 
        !          1035:   /* Write the assembler code to define one.  */
        !          1036:   align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
        !          1037:   if (align > 0)
        !          1038:     ASM_OUTPUT_ALIGN (asm_out_file, align);
        !          1039: 
        !          1040:   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LTRAMP", 0);
        !          1041:   TRAMPOLINE_TEMPLATE (asm_out_file);
        !          1042: 
        !          1043:   /* Record the rtl to refer to it.  */
        !          1044:   ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0);
        !          1045:   name
        !          1046:     = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
        !          1047:   return gen_rtx (SYMBOL_REF, Pmode, name);
        !          1048: }
        !          1049: 
        !          1050: /* Assemble the integer constant X into an object of SIZE bytes.
        !          1051:    X must be either a CONST_INT or CONST_DOUBLE.
        !          1052: 
        !          1053:    Return 1 if we were able to output the constant, otherwise 0.  If FORCE is
        !          1054:    non-zero, abort if we can't output the constant.  */
        !          1055: 
        !          1056: int
        !          1057: assemble_integer (x, size, force)
        !          1058:      rtx x;
        !          1059:      int size;
        !          1060:      int force;
        !          1061: {
        !          1062:   /* First try to use the standard 1, 2, 4, 8, and 16 byte
        !          1063:      ASM_OUTPUT... macros. */
        !          1064: 
        !          1065:   switch (size)
        !          1066:     {
        !          1067: #ifdef ASM_OUTPUT_CHAR
        !          1068:     case 1:
        !          1069:       ASM_OUTPUT_CHAR (asm_out_file, x);
        !          1070:       return 1;
        !          1071: #endif
        !          1072: 
        !          1073: #ifdef ASM_OUTPUT_SHORT
        !          1074:     case 2:
        !          1075:       ASM_OUTPUT_SHORT (asm_out_file, x);
        !          1076:       return 1;
        !          1077: #endif
        !          1078: 
        !          1079: #ifdef ASM_OUTPUT_INT
        !          1080:     case 4:
        !          1081:       ASM_OUTPUT_INT (asm_out_file, x);
        !          1082:       return 1;
        !          1083: #endif
        !          1084: 
        !          1085: #ifdef ASM_OUTPUT_DOUBLE_INT
        !          1086:     case 8:
        !          1087:       ASM_OUTPUT_DOUBLE_INT (asm_out_file, x);
        !          1088:       return 1;
        !          1089: #endif
        !          1090: 
        !          1091: #ifdef ASM_OUTPUT_QUADRUPLE_INT
        !          1092:     case 16:
        !          1093:       ASM_OUTPUT_QUADRUPLE_INT (asm_out_file, x);
        !          1094:       return 1;
        !          1095: #endif
        !          1096:     }
        !          1097: 
        !          1098:   /* If we couldn't do it that way, there are two other possibilities: First,
        !          1099:      if the machine can output an explicit byte and this is a 1 byte constant,
        !          1100:      we can use ASM_OUTPUT_BYTE.  */
        !          1101: 
        !          1102: #ifdef ASM_OUTPUT_BYTE
        !          1103:   if (size == 1 && GET_CODE (x) == CONST_INT)
        !          1104:     {
        !          1105:       ASM_OUTPUT_BYTE (asm_out_file, INTVAL (x));
        !          1106:       return 1;
        !          1107:     }
        !          1108: #endif
        !          1109: 
        !          1110:   /* Finally, if SIZE is larger than a single word, try to output the constant
        !          1111:      one word at a time.  */
        !          1112: 
        !          1113:   if (size > UNITS_PER_WORD)
        !          1114:     {
        !          1115:       int i;
        !          1116:       enum machine_mode mode
        !          1117:        = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
        !          1118:       rtx word;
        !          1119: 
        !          1120:       for (i = 0; i < size / UNITS_PER_WORD; i++)
        !          1121:        {
        !          1122:          word = operand_subword (x, i, 0, mode);
        !          1123: 
        !          1124:          if (word == 0)
        !          1125:            break;
        !          1126: 
        !          1127:          if (! assemble_integer (word, UNITS_PER_WORD, 0))
        !          1128:            break;
        !          1129:        }
        !          1130: 
        !          1131:       if (i == size / UNITS_PER_WORD)
        !          1132:        return 1;
        !          1133:       /* If we output at least one word and then could not finish,
        !          1134:         there is no valid way to continue.  */
        !          1135:       if (i > 0)
        !          1136:        abort ();
        !          1137:     }
        !          1138: 
        !          1139:   if (force)
        !          1140:     abort ();
        !          1141: 
        !          1142:   return 0;
        !          1143: }
        !          1144: 
        !          1145: /* Assemble the floating-point constant D into an object of size MODE.  */
        !          1146: 
        !          1147: void
        !          1148: assemble_real (d, mode)
        !          1149:      REAL_VALUE_TYPE d;
        !          1150:      enum machine_mode mode;
        !          1151: {
        !          1152:   jmp_buf output_constant_handler;
        !          1153: 
        !          1154:   if (setjmp (output_constant_handler))
        !          1155:     {
        !          1156:       error ("floating point trap outputting a constant");
        !          1157: #ifdef REAL_IS_NOT_DOUBLE
        !          1158:       bzero (&d, sizeof d);
        !          1159:       d = dconst0;
        !          1160: #else
        !          1161:       d = 0;
        !          1162: #endif
        !          1163:     }
        !          1164: 
        !          1165:   set_float_handler (output_constant_handler);
        !          1166: 
        !          1167:   switch (mode)
        !          1168:     {
        !          1169: #ifdef ASM_OUTPUT_FLOAT
        !          1170:     case SFmode:
        !          1171:       ASM_OUTPUT_FLOAT (asm_out_file, d);
        !          1172:       break;
        !          1173: #endif
        !          1174: 
        !          1175: #ifdef ASM_OUTPUT_DOUBLE
        !          1176:     case DFmode:
        !          1177:       ASM_OUTPUT_DOUBLE (asm_out_file, d);
        !          1178:       break;
        !          1179: #endif
        !          1180: 
        !          1181: #ifdef ASM_OUTPUT_LONG_DOUBLE
        !          1182:     case TFmode:
        !          1183:       ASM_OUTPUT_LONG_DOUBLE (asm_out_file, d);
        !          1184:       break;
        !          1185: #endif
        !          1186: 
        !          1187:     default:
        !          1188:       abort ();
        !          1189:     }
        !          1190: 
        !          1191:   set_float_handler (0);
        !          1192: }
        !          1193: 
        !          1194: /* Here we combine duplicate floating constants to make
        !          1195:    CONST_DOUBLE rtx's, and force those out to memory when necessary.  */
        !          1196: 
        !          1197: /* Chain of all CONST_DOUBLE rtx's constructed for the current function.
        !          1198:    They are chained through the CONST_DOUBLE_CHAIN.
        !          1199:    A CONST_DOUBLE rtx has CONST_DOUBLE_MEM != cc0_rtx iff it is on this chain.
        !          1200:    In that case, CONST_DOUBLE_MEM is either a MEM,
        !          1201:    or const0_rtx if no MEM has been made for this CONST_DOUBLE yet.  */
        !          1202: 
        !          1203: static rtx const_double_chain;
        !          1204: 
        !          1205: /* Return a CONST_DOUBLE for a value specified as a pair of ints.
        !          1206:    For an integer, I0 is the low-order word and I1 is the high-order word.
        !          1207:    For a real number, I0 is the word with the low address
        !          1208:    and I1 is the word with the high address.  */
        !          1209: 
        !          1210: rtx
        !          1211: immed_double_const (i0, i1, mode)
        !          1212:      int i0, i1;
        !          1213:      enum machine_mode mode;
        !          1214: {
        !          1215:   register rtx r;
        !          1216:   int in_current_obstack;
        !          1217: 
        !          1218:   if (GET_MODE_CLASS (mode) == MODE_INT)
        !          1219:     {
        !          1220:       /* We clear out all bits that don't belong in MODE, unless they and our
        !          1221:         sign bit are all one.  So we get either a reasonable negative value
        !          1222:         or a reasonable unsigned value for this mode.  */
        !          1223:       int width = GET_MODE_BITSIZE (mode);
        !          1224:       if (width < HOST_BITS_PER_INT
        !          1225:          && ((i0 & ((-1) << (width - 1))) != ((-1) << (width - 1))))
        !          1226:        i0 &= (1 << width) - 1, i1 = 0;
        !          1227:       else if (width == HOST_BITS_PER_INT
        !          1228:               && ! (i1 == ~0 && i0 < 0))
        !          1229:        i1 = 0;
        !          1230:       else if (width > 2 * HOST_BITS_PER_INT)
        !          1231:        /* We cannot represent this value as a constant.  */
        !          1232:        abort ();
        !          1233: 
        !          1234:       /* If MODE fits within HOST_BITS_PER_INT, always use a CONST_INT.
        !          1235: 
        !          1236:         ??? Strictly speaking, this is wrong if we create a CONST_INT
        !          1237:         for a large unsigned constant with the size of MODE being
        !          1238:         HOST_BITS_PER_INT and later try to interpret that constant in a wider
        !          1239:         mode.  In that case we will mis-interpret it as a negative number.
        !          1240: 
        !          1241:         Unfortunately, the only alternative is to make a CONST_DOUBLE
        !          1242:         for any constant in any mode if it is an unsigned constant larger
        !          1243:         than the maximum signed integer in an int on the host.  However,
        !          1244:         doing this will break everyone that always expects to see a CONST_INT
        !          1245:         for SImode and smaller.
        !          1246: 
        !          1247:         We have always been making CONST_INTs in this case, so nothing new
        !          1248:         is being broken.  */
        !          1249: 
        !          1250:       if (width <= HOST_BITS_PER_INT)
        !          1251:        i1 = (i0 < 0) ? ~0 : 0;
        !          1252: 
        !          1253:       /* If this integer fits in one word, return a CONST_INT.  */
        !          1254:       if ((i1 == 0 && i0 >= 0)
        !          1255:          || (i1 == ~0 && i0 < 0))
        !          1256:        return gen_rtx (CONST_INT, VOIDmode, i0);
        !          1257: 
        !          1258:       /* We use VOIDmode for integers.  */
        !          1259:       mode = VOIDmode;
        !          1260:     }
        !          1261: 
        !          1262:   /* Search the chain for an existing CONST_DOUBLE with the right value.
        !          1263:      If one is found, return it.  */
        !          1264: 
        !          1265:   for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
        !          1266:     if (CONST_DOUBLE_LOW (r) == i0 && CONST_DOUBLE_HIGH (r) == i1
        !          1267:        && GET_MODE (r) == mode)
        !          1268:       return r;
        !          1269: 
        !          1270:   /* No; make a new one and add it to the chain.
        !          1271: 
        !          1272:      We may be called by an optimizer which may be discarding any memory
        !          1273:      allocated during its processing (such as combine and loop).  However,
        !          1274:      we will be leaving this constant on the chain, so we cannot tolerate
        !          1275:      freed memory.  So switch to saveable_obstack for this allocation
        !          1276:      and then switch back if we were in current_obstack.  */
        !          1277: 
        !          1278:   in_current_obstack = rtl_in_saveable_obstack ();
        !          1279:   r = gen_rtx (CONST_DOUBLE, mode, 0, i0, i1);
        !          1280:   if (in_current_obstack)
        !          1281:     rtl_in_current_obstack ();
        !          1282: 
        !          1283:   CONST_DOUBLE_CHAIN (r) = const_double_chain;
        !          1284:   const_double_chain = r;
        !          1285: 
        !          1286:   /* Store const0_rtx in mem-slot since this CONST_DOUBLE is on the chain.
        !          1287:      Actual use of mem-slot is only through force_const_mem.  */
        !          1288: 
        !          1289:   CONST_DOUBLE_MEM (r) = const0_rtx;
        !          1290: 
        !          1291:   return r;
        !          1292: }
        !          1293: 
        !          1294: /* Return a CONST_DOUBLE for a specified `double' value
        !          1295:    and machine mode.  */
        !          1296: 
        !          1297: rtx
        !          1298: immed_real_const_1 (d, mode)
        !          1299:      REAL_VALUE_TYPE d;
        !          1300:      enum machine_mode mode;
        !          1301: {
        !          1302:   union real_extract u;
        !          1303:   register rtx r;
        !          1304:   int in_current_obstack;
        !          1305: 
        !          1306:   /* Get the desired `double' value as a sequence of ints
        !          1307:      since that is how they are stored in a CONST_DOUBLE.  */
        !          1308: 
        !          1309:   u.d = d;
        !          1310: 
        !          1311:   /* Detect special cases.  */
        !          1312: 
        !          1313:   if (REAL_VALUES_EQUAL (dconst0, d))
        !          1314:     return CONST0_RTX (mode);
        !          1315:   else if (REAL_VALUES_EQUAL (dconst1, d))
        !          1316:     return CONST1_RTX (mode);
        !          1317: 
        !          1318:   if (sizeof u == 2 * sizeof (int))
        !          1319:     return immed_double_const (u.i[0], u.i[1], mode);
        !          1320: 
        !          1321:   /* The rest of this function handles the case where
        !          1322:      a float value requires more than 2 ints of space.
        !          1323:      It will be deleted as dead code on machines that don't need it.  */
        !          1324: 
        !          1325:   /* Search the chain for an existing CONST_DOUBLE with the right value.
        !          1326:      If one is found, return it.  */
        !          1327: 
        !          1328:   for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
        !          1329:     if (! bcmp (&CONST_DOUBLE_LOW (r), &u, sizeof u)
        !          1330:        && GET_MODE (r) == mode)
        !          1331:       return r;
        !          1332: 
        !          1333:   /* No; make a new one and add it to the chain.
        !          1334: 
        !          1335:      We may be called by an optimizer which may be discarding any memory
        !          1336:      allocated during its processing (such as combine and loop).  However,
        !          1337:      we will be leaving this constant on the chain, so we cannot tolerate
        !          1338:      freed memory.  So switch to saveable_obstack for this allocation
        !          1339:      and then switch back if we were in current_obstack.  */
        !          1340: 
        !          1341:   in_current_obstack = rtl_in_saveable_obstack ();
        !          1342:   r = rtx_alloc (CONST_DOUBLE);
        !          1343:   PUT_MODE (r, mode);
        !          1344:   bcopy (&u, &CONST_DOUBLE_LOW (r), sizeof u);
        !          1345:   if (in_current_obstack)
        !          1346:     rtl_in_current_obstack ();
        !          1347: 
        !          1348:   CONST_DOUBLE_CHAIN (r) = const_double_chain;
        !          1349:   const_double_chain = r;
        !          1350: 
        !          1351:   /* Store const0_rtx in CONST_DOUBLE_MEM since this CONST_DOUBLE is on the
        !          1352:      chain, but has not been allocated memory.  Actual use of CONST_DOUBLE_MEM
        !          1353:      is only through force_const_mem.  */
        !          1354: 
        !          1355:   CONST_DOUBLE_MEM (r) = const0_rtx;
        !          1356: 
        !          1357:   return r;
        !          1358: }
        !          1359: 
        !          1360: /* Return a CONST_DOUBLE rtx for a value specified by EXP,
        !          1361:    which must be a REAL_CST tree node.  */
        !          1362: 
        !          1363: rtx
        !          1364: immed_real_const (exp)
        !          1365:      tree exp;
        !          1366: {
        !          1367:   return immed_real_const_1 (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)));
        !          1368: }
        !          1369: 
        !          1370: /* At the end of a function, forget the memory-constants
        !          1371:    previously made for CONST_DOUBLEs.  Mark them as not on real_constant_chain.
        !          1372:    Also clear out real_constant_chain and clear out all the chain-pointers.  */
        !          1373: 
        !          1374: void
        !          1375: clear_const_double_mem ()
        !          1376: {
        !          1377:   register rtx r, next;
        !          1378: 
        !          1379:   for (r = const_double_chain; r; r = next)
        !          1380:     {
        !          1381:       next = CONST_DOUBLE_CHAIN (r);
        !          1382:       CONST_DOUBLE_CHAIN (r) = 0;
        !          1383:       CONST_DOUBLE_MEM (r) = cc0_rtx;
        !          1384:     }
        !          1385:   const_double_chain = 0;
        !          1386: }
        !          1387: 
        !          1388: /* Given an expression EXP with a constant value,
        !          1389:    reduce it to the sum of an assembler symbol and an integer.
        !          1390:    Store them both in the structure *VALUE.
        !          1391:    Abort if EXP does not reduce.  */
        !          1392: 
        !          1393: struct addr_const
        !          1394: {
        !          1395:   rtx base;
        !          1396:   int offset;
        !          1397: };
        !          1398: 
        !          1399: static void
        !          1400: decode_addr_const (exp, value)
        !          1401:      tree exp;
        !          1402:      struct addr_const *value;
        !          1403: {
        !          1404:   register tree target = TREE_OPERAND (exp, 0);
        !          1405:   register int offset = 0;
        !          1406:   register rtx x;
        !          1407: 
        !          1408:   while (1)
        !          1409:     {
        !          1410:       if (TREE_CODE (target) == COMPONENT_REF
        !          1411:          && (TREE_CODE (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1)))
        !          1412:              == INTEGER_CST))
        !          1413:        {
        !          1414:          offset += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1))) / BITS_PER_UNIT;
        !          1415:          target = TREE_OPERAND (target, 0);
        !          1416:        }
        !          1417:       else if (TREE_CODE (target) == ARRAY_REF)
        !          1418:        {
        !          1419:          if (TREE_CODE (TREE_OPERAND (target, 1)) != INTEGER_CST
        !          1420:              || TREE_CODE (TYPE_SIZE (TREE_TYPE (target))) != INTEGER_CST)
        !          1421:            abort ();
        !          1422:          offset += ((TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (target)))
        !          1423:                      * TREE_INT_CST_LOW (TREE_OPERAND (target, 1)))
        !          1424:                     / BITS_PER_UNIT);
        !          1425:          target = TREE_OPERAND (target, 0);
        !          1426:        }
        !          1427:       else
        !          1428:        break;
        !          1429:     }
        !          1430: 
        !          1431:   switch (TREE_CODE (target))
        !          1432:     {
        !          1433:     case VAR_DECL:
        !          1434:     case FUNCTION_DECL:
        !          1435:       x = DECL_RTL (target);
        !          1436:       break;
        !          1437: 
        !          1438:     case LABEL_DECL:
        !          1439:       x = gen_rtx (MEM, FUNCTION_MODE,
        !          1440:                   gen_rtx (LABEL_REF, VOIDmode,
        !          1441:                            label_rtx (TREE_OPERAND (exp, 0))));
        !          1442:       break;
        !          1443: 
        !          1444:     case REAL_CST:
        !          1445:     case STRING_CST:
        !          1446:     case COMPLEX_CST:
        !          1447:     case CONSTRUCTOR:
        !          1448:       x = TREE_CST_RTL (target);
        !          1449:       break;
        !          1450: 
        !          1451:     default:
        !          1452:       abort ();
        !          1453:     }
        !          1454: 
        !          1455:   if (GET_CODE (x) != MEM)
        !          1456:     abort ();
        !          1457:   x = XEXP (x, 0);
        !          1458: 
        !          1459:   value->base = x;
        !          1460:   value->offset = offset;
        !          1461: }
        !          1462: 
        !          1463: /* Uniquize all constants that appear in memory.
        !          1464:    Each constant in memory thus far output is recorded
        !          1465:    in `const_hash_table' with a `struct constant_descriptor'
        !          1466:    that contains a polish representation of the value of
        !          1467:    the constant.
        !          1468: 
        !          1469:    We cannot store the trees in the hash table
        !          1470:    because the trees may be temporary.  */
        !          1471: 
        !          1472: struct constant_descriptor
        !          1473: {
        !          1474:   struct constant_descriptor *next;
        !          1475:   char *label;
        !          1476:   char contents[1];
        !          1477: };
        !          1478: 
        !          1479: #define HASHBITS 30
        !          1480: #define MAX_HASH_TABLE 1009
        !          1481: static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
        !          1482: 
        !          1483: /* Compute a hash code for a constant expression.  */
        !          1484: 
        !          1485: int
        !          1486: const_hash (exp)
        !          1487:      tree exp;
        !          1488: {
        !          1489:   register char *p;
        !          1490:   register int len, hi, i;
        !          1491:   register enum tree_code code = TREE_CODE (exp);
        !          1492: 
        !          1493:   if (code == INTEGER_CST)
        !          1494:     {
        !          1495:       p = (char *) &TREE_INT_CST_LOW (exp);
        !          1496:       len = 2 * sizeof TREE_INT_CST_LOW (exp);
        !          1497:     }
        !          1498:   else if (code == REAL_CST)
        !          1499:     {
        !          1500:       p = (char *) &TREE_REAL_CST (exp);
        !          1501:       len = sizeof TREE_REAL_CST (exp);
        !          1502:     }
        !          1503:   else if (code == STRING_CST)
        !          1504:     p = TREE_STRING_POINTER (exp), len = TREE_STRING_LENGTH (exp);
        !          1505:   else if (code == COMPLEX_CST)
        !          1506:     return const_hash (TREE_REALPART (exp)) * 5
        !          1507:       + const_hash (TREE_IMAGPART (exp));
        !          1508:   else if (code == CONSTRUCTOR)
        !          1509:     {
        !          1510:       register tree link;
        !          1511: 
        !          1512:       /* For record type, include the type in the hashing.
        !          1513:         We do not do so for array types
        !          1514:         because (1) the sizes of the elements are sufficient
        !          1515:         and (2) distinct array types can have the same constructor.  */
        !          1516:       if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
        !          1517:        hi = ((int) TREE_TYPE (exp) & ((1 << HASHBITS) - 1)) % MAX_HASH_TABLE;
        !          1518:       else
        !          1519:        hi = 5;
        !          1520: 
        !          1521:       for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
        !          1522:        hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE;
        !          1523: 
        !          1524:       return hi;
        !          1525:     }
        !          1526:   else if (code == ADDR_EXPR)
        !          1527:     {
        !          1528:       struct addr_const value;
        !          1529:       decode_addr_const (exp, &value);
        !          1530:       if (GET_CODE (value.base) == SYMBOL_REF)
        !          1531:        {
        !          1532:          /* Don't hash the address of the SYMBOL_REF;
        !          1533:             only use the offset and the symbol name.  */
        !          1534:          hi = value.offset;
        !          1535:          p = XSTR (value.base, 0);
        !          1536:          for (i = 0; p[i] != 0; i++)
        !          1537:            hi = ((hi * 613) + (unsigned)(p[i]));
        !          1538:        }
        !          1539:       else if (GET_CODE (value.base) == LABEL_REF)
        !          1540:        hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;
        !          1541: 
        !          1542:       hi &= (1 << HASHBITS) - 1;
        !          1543:       hi %= MAX_HASH_TABLE;
        !          1544:       return hi;
        !          1545:     }
        !          1546:   else if (code == PLUS_EXPR || code == MINUS_EXPR)
        !          1547:     return const_hash (TREE_OPERAND (exp, 0)) * 9
        !          1548:       +  const_hash (TREE_OPERAND (exp, 1));
        !          1549:   else if (code == NOP_EXPR || code == CONVERT_EXPR)
        !          1550:     return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
        !          1551: 
        !          1552:   /* Compute hashing function */
        !          1553:   hi = len;
        !          1554:   for (i = 0; i < len; i++)
        !          1555:     hi = ((hi * 613) + (unsigned)(p[i]));
        !          1556: 
        !          1557:   hi &= (1 << HASHBITS) - 1;
        !          1558:   hi %= MAX_HASH_TABLE;
        !          1559:   return hi;
        !          1560: }
        !          1561: 
        !          1562: /* Compare a constant expression EXP with a constant-descriptor DESC.
        !          1563:    Return 1 if DESC describes a constant with the same value as EXP.  */
        !          1564: 
        !          1565: static int
        !          1566: compare_constant (exp, desc)
        !          1567:      tree exp;
        !          1568:      struct constant_descriptor *desc;
        !          1569: {
        !          1570:   return 0 != compare_constant_1 (exp, desc->contents);
        !          1571: }
        !          1572: 
        !          1573: /* Compare constant expression EXP with a substring P of a constant descriptor.
        !          1574:    If they match, return a pointer to the end of the substring matched.
        !          1575:    If they do not match, return 0.
        !          1576: 
        !          1577:    Since descriptors are written in polish prefix notation,
        !          1578:    this function can be used recursively to test one operand of EXP
        !          1579:    against a subdescriptor, and if it succeeds it returns the
        !          1580:    address of the subdescriptor for the next operand.  */
        !          1581: 
        !          1582: static char *
        !          1583: compare_constant_1 (exp, p)
        !          1584:      tree exp;
        !          1585:      char *p;
        !          1586: {
        !          1587:   register char *strp;
        !          1588:   register int len;
        !          1589:   register enum tree_code code = TREE_CODE (exp);
        !          1590: 
        !          1591:   if (code != (enum tree_code) *p++)
        !          1592:     return 0;
        !          1593: 
        !          1594:   if (code == INTEGER_CST)
        !          1595:     {
        !          1596:       /* Integer constants are the same only if the same width of type.  */
        !          1597:       if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
        !          1598:        return 0;
        !          1599:       strp = (char *) &TREE_INT_CST_LOW (exp);
        !          1600:       len = 2 * sizeof TREE_INT_CST_LOW (exp);
        !          1601:     }
        !          1602:   else if (code == REAL_CST)
        !          1603:     {
        !          1604:       /* Real constants are the same only if the same width of type.  */
        !          1605:       if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
        !          1606:        return 0;
        !          1607:       strp = (char *) &TREE_REAL_CST (exp);
        !          1608:       len = sizeof TREE_REAL_CST (exp);
        !          1609:     }
        !          1610:   else if (code == STRING_CST)
        !          1611:     {
        !          1612:       if (flag_writable_strings)
        !          1613:        return 0;
        !          1614:       strp = TREE_STRING_POINTER (exp);
        !          1615:       len = TREE_STRING_LENGTH (exp);
        !          1616:       if (bcmp (&TREE_STRING_LENGTH (exp), p,
        !          1617:                sizeof TREE_STRING_LENGTH (exp)))
        !          1618:        return 0;
        !          1619:       p += sizeof TREE_STRING_LENGTH (exp);
        !          1620:     }
        !          1621:   else if (code == COMPLEX_CST)
        !          1622:     {
        !          1623:       p = compare_constant_1 (TREE_REALPART (exp), p);
        !          1624:       if (p == 0) return 0;
        !          1625:       p = compare_constant_1 (TREE_IMAGPART (exp), p);
        !          1626:       return p;
        !          1627:     }
        !          1628:   else if (code == CONSTRUCTOR)
        !          1629:     {
        !          1630:       register tree link;
        !          1631:       int length = list_length (CONSTRUCTOR_ELTS (exp));
        !          1632:       tree type;
        !          1633: 
        !          1634:       if (bcmp (&length, p, sizeof length))
        !          1635:        return 0;
        !          1636:       p += sizeof length;
        !          1637: 
        !          1638:       /* For record constructors, insist that the types match.
        !          1639:         For arrays, just verify both constructors are for arrays.  */
        !          1640:       if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
        !          1641:        type = TREE_TYPE (exp);
        !          1642:       else
        !          1643:        type = 0;
        !          1644:       if (bcmp (&type, p, sizeof type))
        !          1645:        return 0;
        !          1646:       p += sizeof type;
        !          1647: 
        !          1648:       for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
        !          1649:        if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0)
        !          1650:          return 0;
        !          1651:       return p;
        !          1652:     }
        !          1653:   else if (code == ADDR_EXPR)
        !          1654:     {
        !          1655:       struct addr_const value;
        !          1656:       decode_addr_const (exp, &value);
        !          1657:       strp = (char *) &value.offset;
        !          1658:       len = sizeof value.offset;
        !          1659:       /* Compare the offset.  */
        !          1660:       while (--len >= 0)
        !          1661:        if (*p++ != *strp++)
        !          1662:          return 0;
        !          1663:       /* Compare symbol name.  */
        !          1664:       strp = XSTR (value.base, 0);
        !          1665:       len = strlen (strp) + 1;
        !          1666:     }
        !          1667:   else if (code == PLUS_EXPR || code == MINUS_EXPR)
        !          1668:     {
        !          1669:       p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
        !          1670:       if (p == 0) return 0;
        !          1671:       p = compare_constant_1 (TREE_OPERAND (exp, 1), p);
        !          1672:       return p;
        !          1673:     }
        !          1674:   else if (code == NOP_EXPR || code == CONVERT_EXPR)
        !          1675:     {
        !          1676:       p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
        !          1677:       return p;
        !          1678:     }
        !          1679: 
        !          1680:   /* Compare constant contents.  */
        !          1681:   while (--len >= 0)
        !          1682:     if (*p++ != *strp++)
        !          1683:       return 0;
        !          1684: 
        !          1685:   return p;
        !          1686: }
        !          1687: 
        !          1688: /* Construct a constant descriptor for the expression EXP.
        !          1689:    It is up to the caller to enter the descriptor in the hash table.  */
        !          1690: 
        !          1691: static struct constant_descriptor *
        !          1692: record_constant (exp)
        !          1693:      tree exp;
        !          1694: {
        !          1695:   struct constant_descriptor *ptr = 0;
        !          1696:   int buf;
        !          1697: 
        !          1698:   obstack_grow (&permanent_obstack, &ptr, sizeof ptr);
        !          1699:   obstack_grow (&permanent_obstack, &buf, sizeof buf);
        !          1700:   record_constant_1 (exp);
        !          1701:   return (struct constant_descriptor *) obstack_finish (&permanent_obstack);
        !          1702: }
        !          1703: 
        !          1704: /* Add a description of constant expression EXP
        !          1705:    to the object growing in `permanent_obstack'.
        !          1706:    No need to return its address; the caller will get that
        !          1707:    from the obstack when the object is complete.  */
        !          1708: 
        !          1709: static void
        !          1710: record_constant_1 (exp)
        !          1711:      tree exp;
        !          1712: {
        !          1713:   register char *strp;
        !          1714:   register int len;
        !          1715:   register enum tree_code code = TREE_CODE (exp);
        !          1716: 
        !          1717:   obstack_1grow (&permanent_obstack, (unsigned int) code);
        !          1718: 
        !          1719:   if (code == INTEGER_CST)
        !          1720:     {
        !          1721:       obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
        !          1722:       strp = (char *) &TREE_INT_CST_LOW (exp);
        !          1723:       len = 2 * sizeof TREE_INT_CST_LOW (exp);
        !          1724:     }
        !          1725:   else if (code == REAL_CST)
        !          1726:     {
        !          1727:       obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
        !          1728:       strp = (char *) &TREE_REAL_CST (exp);
        !          1729:       len = sizeof TREE_REAL_CST (exp);
        !          1730:     }
        !          1731:   else if (code == STRING_CST)
        !          1732:     {
        !          1733:       if (flag_writable_strings)
        !          1734:        return;
        !          1735:       strp = TREE_STRING_POINTER (exp);
        !          1736:       len = TREE_STRING_LENGTH (exp);
        !          1737:       obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp),
        !          1738:                    sizeof TREE_STRING_LENGTH (exp));
        !          1739:     }
        !          1740:   else if (code == COMPLEX_CST)
        !          1741:     {
        !          1742:       record_constant_1 (TREE_REALPART (exp));
        !          1743:       record_constant_1 (TREE_IMAGPART (exp));
        !          1744:       return;
        !          1745:     }
        !          1746:   else if (code == CONSTRUCTOR)
        !          1747:     {
        !          1748:       register tree link;
        !          1749:       int length = list_length (CONSTRUCTOR_ELTS (exp));
        !          1750:       tree type;
        !          1751: 
        !          1752:       obstack_grow (&permanent_obstack, (char *) &length, sizeof length);
        !          1753: 
        !          1754:       /* For record constructors, insist that the types match.
        !          1755:         For arrays, just verify both constructors are for arrays.  */
        !          1756:       if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
        !          1757:        type = TREE_TYPE (exp);
        !          1758:       else
        !          1759:        type = 0;
        !          1760:       obstack_grow (&permanent_obstack, (char *) &type, sizeof type);
        !          1761: 
        !          1762:       for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
        !          1763:        record_constant_1 (TREE_VALUE (link));
        !          1764:       return;
        !          1765:     }
        !          1766:   else if (code == ADDR_EXPR)
        !          1767:     {
        !          1768:       struct addr_const value;
        !          1769:       decode_addr_const (exp, &value);
        !          1770:       /* Record the offset.  */
        !          1771:       obstack_grow (&permanent_obstack,
        !          1772:                    (char *) &value.offset, sizeof value.offset);
        !          1773:       /* Record the symbol name.  */
        !          1774:       obstack_grow (&permanent_obstack, XSTR (value.base, 0),
        !          1775:                    strlen (XSTR (value.base, 0)) + 1);
        !          1776:       return;
        !          1777:     }
        !          1778:   else if (code == PLUS_EXPR || code == MINUS_EXPR)
        !          1779:     {
        !          1780:       record_constant_1 (TREE_OPERAND (exp, 0));
        !          1781:       record_constant_1 (TREE_OPERAND (exp, 1));
        !          1782:       return;
        !          1783:     }
        !          1784:   else if (code == NOP_EXPR || code == CONVERT_EXPR)
        !          1785:     {
        !          1786:       record_constant_1 (TREE_OPERAND (exp, 0));
        !          1787:       return;
        !          1788:     }
        !          1789: 
        !          1790:   /* Record constant contents.  */
        !          1791:   obstack_grow (&permanent_obstack, strp, len);
        !          1792: }
        !          1793: 
        !          1794: /* Return an rtx representing a reference to constant data in memory
        !          1795:    for the constant expression EXP.
        !          1796:    If assembler code for such a constant has already been output,
        !          1797:    return an rtx to refer to it.
        !          1798:    Otherwise, output such a constant in memory and generate
        !          1799:    an rtx for it.  The TREE_CST_RTL of EXP is set up to point to that rtx.
        !          1800:    The const_hash_table records which constants already have label strings.  */
        !          1801: 
        !          1802: rtx
        !          1803: output_constant_def (exp)
        !          1804:      tree exp;
        !          1805: {
        !          1806:   register int hash, align;
        !          1807:   register struct constant_descriptor *desc;
        !          1808:   char label[256];
        !          1809:   char *found = 0;
        !          1810:   int reloc;
        !          1811:   register rtx def;
        !          1812: 
        !          1813:   if (TREE_CODE (exp) == INTEGER_CST)
        !          1814:     abort ();                  /* No TREE_CST_RTL slot in these.  */
        !          1815: 
        !          1816:   if (TREE_CST_RTL (exp))
        !          1817:     return TREE_CST_RTL (exp);
        !          1818: 
        !          1819:   /* Make sure any other constants whose addresses appear in EXP
        !          1820:      are assigned label numbers.  */
        !          1821: 
        !          1822:   reloc = output_addressed_constants (exp);
        !          1823: 
        !          1824:   /* Compute hash code of EXP.  Search the descriptors for that hash code
        !          1825:      to see if any of them describes EXP.  If yes, the descriptor records
        !          1826:      the label number already assigned.  */
        !          1827: 
        !          1828:   hash = const_hash (exp) % MAX_HASH_TABLE;
        !          1829: 
        !          1830:   for (desc = const_hash_table[hash]; desc; desc = desc->next)
        !          1831:     if (compare_constant (exp, desc))
        !          1832:       {
        !          1833:        found = desc->label;
        !          1834:        break;
        !          1835:       }
        !          1836: 
        !          1837:   if (found == 0)
        !          1838:     {
        !          1839:       /* No constant equal to EXP is known to have been output.
        !          1840:         Make a constant descriptor to enter EXP in the hash table.
        !          1841:         Assign the label number and record it in the descriptor for
        !          1842:         future calls to this function to find.  */
        !          1843: 
        !          1844:       /* Create a string containing the label name, in LABEL.  */
        !          1845:       ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
        !          1846: 
        !          1847:       desc = record_constant (exp);
        !          1848:       desc->next = const_hash_table[hash];
        !          1849:       desc->label
        !          1850:        = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
        !          1851:       const_hash_table[hash] = desc;
        !          1852:     }
        !          1853: 
        !          1854:   /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
        !          1855: 
        !          1856:   push_obstacks_nochange ();
        !          1857:   if (TREE_PERMANENT (exp))
        !          1858:     end_temporary_allocation ();
        !          1859: 
        !          1860:   def = gen_rtx (SYMBOL_REF, Pmode, desc->label);
        !          1861: 
        !          1862:   TREE_CST_RTL (exp)
        !          1863:     = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), def);
        !          1864:   RTX_UNCHANGING_P (TREE_CST_RTL (exp)) = 1;
        !          1865: 
        !          1866:   pop_obstacks ();
        !          1867: 
        !          1868:   /* Optionally set flags or add text to the name to record information
        !          1869:      such as that it is a function name.  If the name is changed, the macro
        !          1870:      ASM_OUTPUT_LABELREF will have to know how to strip this information.
        !          1871:      And if it finds a * at the beginning after doing so, it must handle
        !          1872:      that too.  */
        !          1873: #ifdef ENCODE_SECTION_INFO
        !          1874:   ENCODE_SECTION_INFO (exp);
        !          1875: #endif
        !          1876: 
        !          1877:   if (found == 0)
        !          1878:     {
        !          1879:       /* Now output assembler code to define that label
        !          1880:         and follow it with the data of EXP.  */
        !          1881: 
        !          1882:       /* First switch to text section, except for writable strings.  */
        !          1883: #ifdef SELECT_SECTION
        !          1884:       SELECT_SECTION (exp, reloc);
        !          1885: #else
        !          1886:       if (((TREE_CODE (exp) == STRING_CST) && flag_writable_strings)
        !          1887:          || (flag_pic && reloc))
        !          1888:        data_section ();
        !          1889:       else
        !          1890:        readonly_data_section ();
        !          1891: #endif
        !          1892: 
        !          1893:       /* Align the location counter as required by EXP's data type.  */
        !          1894:       align = TYPE_ALIGN (TREE_TYPE (exp));
        !          1895: #ifdef CONSTANT_ALIGNMENT
        !          1896:       align = CONSTANT_ALIGNMENT (exp, align);
        !          1897: #endif
        !          1898: 
        !          1899:       if (align > BITS_PER_UNIT)
        !          1900:        ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
        !          1901: 
        !          1902:       /* Output the label itself.  */
        !          1903:       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", const_labelno);
        !          1904: 
        !          1905:       /* Output the value of EXP.  */
        !          1906:       output_constant (exp,
        !          1907:                       (TREE_CODE (exp) == STRING_CST
        !          1908:                        ? TREE_STRING_LENGTH (exp)
        !          1909:                        : int_size_in_bytes (TREE_TYPE (exp))));
        !          1910: 
        !          1911:       ++const_labelno;
        !          1912:     }
        !          1913: 
        !          1914:   return TREE_CST_RTL (exp);
        !          1915: }
        !          1916: 
        !          1917: /* Similar hash facility for making memory-constants
        !          1918:    from constant rtl-expressions.  It is used on RISC machines
        !          1919:    where immediate integer arguments and constant addresses are restricted
        !          1920:    so that such constants must be stored in memory.
        !          1921: 
        !          1922:    This pool of constants is reinitialized for each function
        !          1923:    so each function gets its own constants-pool that comes right before it.
        !          1924: 
        !          1925:    All structures allocated here are discarded when functions are saved for
        !          1926:    inlining, so they do not need to be allocated permanently.  */
        !          1927: 
        !          1928: #define MAX_RTX_HASH_TABLE 61
        !          1929: static struct constant_descriptor *const_rtx_hash_table[MAX_RTX_HASH_TABLE];
        !          1930: 
        !          1931: /* Structure to represent sufficient information about a constant so that
        !          1932:    it can be output when the constant pool is output, so that function
        !          1933:    integration can be done, and to simplify handling on machines that reference
        !          1934:    constant pool as base+displacement.  */
        !          1935: 
        !          1936: struct pool_constant
        !          1937: {
        !          1938:   struct constant_descriptor *desc;
        !          1939:   struct pool_constant *next;
        !          1940:   enum machine_mode mode;
        !          1941:   rtx constant;
        !          1942:   int labelno;
        !          1943:   int align;
        !          1944:   int offset;
        !          1945: };
        !          1946: 
        !          1947: /* Pointers to first and last constant in pool.  */
        !          1948: 
        !          1949: static struct pool_constant *first_pool, *last_pool;
        !          1950: 
        !          1951: /* Current offset in constant pool (does not include any machine-specific
        !          1952:    header.  */
        !          1953: 
        !          1954: static int pool_offset;
        !          1955: 
        !          1956: /* Structure used to maintain hash table mapping symbols used to their
        !          1957:    corresponding constants.  */
        !          1958: 
        !          1959: struct pool_sym
        !          1960: {
        !          1961:   char *label;
        !          1962:   struct pool_constant *pool;
        !          1963:   struct pool_sym *next;
        !          1964: };
        !          1965: 
        !          1966: static struct pool_sym *const_rtx_sym_hash_table[MAX_RTX_HASH_TABLE];
        !          1967: 
        !          1968: /* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true.
        !          1969:    The argument is XSTR (... , 0)  */
        !          1970: 
        !          1971: #define SYMHASH(LABEL) \
        !          1972:   ((((int) (LABEL)) & ((1 << HASHBITS) - 1))  % MAX_RTX_HASH_TABLE)
        !          1973: 
        !          1974: /* Initialize constant pool hashing for next function.  */
        !          1975: 
        !          1976: void
        !          1977: init_const_rtx_hash_table ()
        !          1978: {
        !          1979:   bzero (const_rtx_hash_table, sizeof const_rtx_hash_table);
        !          1980:   bzero (const_rtx_sym_hash_table, sizeof const_rtx_sym_hash_table);
        !          1981: 
        !          1982:   first_pool = last_pool = 0;
        !          1983:   pool_offset = 0;
        !          1984: }
        !          1985: 
        !          1986: enum kind { RTX_DOUBLE, RTX_INT };
        !          1987: 
        !          1988: struct rtx_const
        !          1989: {
        !          1990: #ifdef ONLY_INT_FIELDS
        !          1991:   unsigned int kind : 16;
        !          1992:   unsigned int mode : 16;
        !          1993: #else
        !          1994:   enum kind kind : 16;
        !          1995:   enum machine_mode mode : 16;
        !          1996: #endif
        !          1997:   union {
        !          1998:     union real_extract du;
        !          1999:     struct addr_const addr;
        !          2000:   } un;
        !          2001: };
        !          2002: 
        !          2003: /* Express an rtx for a constant integer (perhaps symbolic)
        !          2004:    as the sum of a symbol or label plus an explicit integer.
        !          2005:    They are stored into VALUE.  */
        !          2006: 
        !          2007: static void
        !          2008: decode_rtx_const (mode, x, value)
        !          2009:      enum machine_mode mode;
        !          2010:      rtx x;
        !          2011:      struct rtx_const *value;
        !          2012: {
        !          2013:   /* Clear the whole structure, including any gaps.  */
        !          2014: 
        !          2015:   {
        !          2016:     int *p = (int *) value;
        !          2017:     int *end = (int *) (value + 1);
        !          2018:     while (p < end)
        !          2019:       *p++ = 0;
        !          2020:   }
        !          2021: 
        !          2022:   value->kind = RTX_INT;       /* Most usual kind. */
        !          2023:   value->mode = mode;
        !          2024: 
        !          2025:   switch (GET_CODE (x))
        !          2026:     {
        !          2027:     case CONST_DOUBLE:
        !          2028:       value->kind = RTX_DOUBLE;
        !          2029:       value->mode = GET_MODE (x);
        !          2030:       bcopy (&CONST_DOUBLE_LOW (x), &value->un.du, sizeof value->un.du);
        !          2031:       break;
        !          2032: 
        !          2033:     case CONST_INT:
        !          2034:       value->un.addr.offset = INTVAL (x);
        !          2035:       break;
        !          2036: 
        !          2037:     case SYMBOL_REF:
        !          2038:     case LABEL_REF:
        !          2039:       value->un.addr.base = x;
        !          2040:       break;
        !          2041: 
        !          2042:     case CONST:
        !          2043:       x = XEXP (x, 0);
        !          2044:       if (GET_CODE (x) == PLUS)
        !          2045:        {
        !          2046:          value->un.addr.base = XEXP (x, 0);
        !          2047:          if (GET_CODE (XEXP (x, 1)) != CONST_INT)
        !          2048:            abort ();
        !          2049:          value->un.addr.offset = INTVAL (XEXP (x, 1));
        !          2050:        }
        !          2051:       else if (GET_CODE (x) == MINUS)
        !          2052:        {
        !          2053:          value->un.addr.base = XEXP (x, 0);
        !          2054:          if (GET_CODE (XEXP (x, 1)) != CONST_INT)
        !          2055:            abort ();
        !          2056:          value->un.addr.offset = - INTVAL (XEXP (x, 1));
        !          2057:        }
        !          2058:       else
        !          2059:        abort ();
        !          2060:       break;
        !          2061: 
        !          2062:     default:
        !          2063:       abort ();
        !          2064:     }
        !          2065: 
        !          2066:   if (value->kind == RTX_INT && value->un.addr.base != 0)
        !          2067:     switch (GET_CODE (value->un.addr.base))
        !          2068:       {
        !          2069:       case SYMBOL_REF:
        !          2070:       case LABEL_REF:
        !          2071:        /* Use the string's address, not the SYMBOL_REF's address,
        !          2072:           for the sake of addresses of library routines.
        !          2073:           For a LABEL_REF, compare labels.  */
        !          2074:        value->un.addr.base = XEXP (value->un.addr.base, 0);
        !          2075:       }
        !          2076: }
        !          2077: 
        !          2078: /* Compute a hash code for a constant RTL expression.  */
        !          2079: 
        !          2080: int
        !          2081: const_hash_rtx (mode, x)
        !          2082:      enum machine_mode mode;
        !          2083:      rtx x;
        !          2084: {
        !          2085:   register int hi, i;
        !          2086: 
        !          2087:   struct rtx_const value;
        !          2088:   decode_rtx_const (mode, x, &value);
        !          2089: 
        !          2090:   /* Compute hashing function */
        !          2091:   hi = 0;
        !          2092:   for (i = 0; i < sizeof value / sizeof (int); i++)
        !          2093:     hi += ((int *) &value)[i];
        !          2094: 
        !          2095:   hi &= (1 << HASHBITS) - 1;
        !          2096:   hi %= MAX_RTX_HASH_TABLE;
        !          2097:   return hi;
        !          2098: }
        !          2099: 
        !          2100: /* Compare a constant rtl object X with a constant-descriptor DESC.
        !          2101:    Return 1 if DESC describes a constant with the same value as X.  */
        !          2102: 
        !          2103: static int
        !          2104: compare_constant_rtx (mode, x, desc)
        !          2105:      enum machine_mode mode;
        !          2106:      rtx x;
        !          2107:      struct constant_descriptor *desc;
        !          2108: {
        !          2109:   register int *p = (int *) desc->contents;
        !          2110:   register int *strp;
        !          2111:   register int len;
        !          2112:   struct rtx_const value;
        !          2113: 
        !          2114:   decode_rtx_const (mode, x, &value);
        !          2115:   strp = (int *) &value;
        !          2116:   len = sizeof value / sizeof (int);
        !          2117: 
        !          2118:   /* Compare constant contents.  */
        !          2119:   while (--len >= 0)
        !          2120:     if (*p++ != *strp++)
        !          2121:       return 0;
        !          2122: 
        !          2123:   return 1;
        !          2124: }
        !          2125: 
        !          2126: /* Construct a constant descriptor for the rtl-expression X.
        !          2127:    It is up to the caller to enter the descriptor in the hash table.  */
        !          2128: 
        !          2129: static struct constant_descriptor *
        !          2130: record_constant_rtx (mode, x)
        !          2131:      enum machine_mode mode;
        !          2132:      rtx x;
        !          2133: {
        !          2134:   struct constant_descriptor *ptr;
        !          2135:   char *label;
        !          2136:   struct rtx_const value;
        !          2137: 
        !          2138:   decode_rtx_const (mode, x, &value);
        !          2139: 
        !          2140:   obstack_grow (current_obstack, &ptr, sizeof ptr);
        !          2141:   obstack_grow (current_obstack, &label, sizeof label);
        !          2142: 
        !          2143:   /* Record constant contents.  */
        !          2144:   obstack_grow (current_obstack, &value, sizeof value);
        !          2145: 
        !          2146:   return (struct constant_descriptor *) obstack_finish (current_obstack);
        !          2147: }
        !          2148: 
        !          2149: /* Given a constant rtx X, make (or find) a memory constant for its value
        !          2150:    and return a MEM rtx to refer to it in memory.  */
        !          2151: 
        !          2152: rtx
        !          2153: force_const_mem (mode, x)
        !          2154:      enum machine_mode mode;
        !          2155:      rtx x;
        !          2156: {
        !          2157:   register int hash;
        !          2158:   register struct constant_descriptor *desc;
        !          2159:   char label[256];
        !          2160:   char *found = 0;
        !          2161:   rtx def;
        !          2162: 
        !          2163:   /* If we want this CONST_DOUBLE in the same mode as it is in memory
        !          2164:      (this will always be true for floating CONST_DOUBLEs that have been
        !          2165:      placed in memory, but not for VOIDmode (integer) CONST_DOUBLEs),
        !          2166:      use the previous copy.  Otherwise, make a new one.  Note that in
        !          2167:      the unlikely event that this same CONST_DOUBLE is used in two different
        !          2168:      modes in an alternating fashion, we will allocate a lot of different
        !          2169:      memory locations, but this should be extremely rare.  */
        !          2170: 
        !          2171:   if (GET_CODE (x) == CONST_DOUBLE
        !          2172:       && GET_CODE (CONST_DOUBLE_MEM (x)) == MEM
        !          2173:       && GET_MODE (CONST_DOUBLE_MEM (x)) == mode)
        !          2174:     return CONST_DOUBLE_MEM (x);
        !          2175: 
        !          2176:   /* Compute hash code of X.  Search the descriptors for that hash code
        !          2177:      to see if any of them describes X.  If yes, the descriptor records
        !          2178:      the label number already assigned.  */
        !          2179: 
        !          2180:   hash = const_hash_rtx (mode, x);
        !          2181: 
        !          2182:   for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next)
        !          2183:     if (compare_constant_rtx (mode, x, desc))
        !          2184:       {
        !          2185:        found = desc->label;
        !          2186:        break;
        !          2187:       }
        !          2188: 
        !          2189:   if (found == 0)
        !          2190:     {
        !          2191:       register struct pool_constant *pool;
        !          2192:       register struct pool_sym *sym;
        !          2193:       int align;
        !          2194: 
        !          2195:       /* No constant equal to X is known to have been output.
        !          2196:         Make a constant descriptor to enter X in the hash table.
        !          2197:         Assign the label number and record it in the descriptor for
        !          2198:         future calls to this function to find.  */
        !          2199: 
        !          2200:       desc = record_constant_rtx (mode, x);
        !          2201:       desc->next = const_rtx_hash_table[hash];
        !          2202:       const_rtx_hash_table[hash] = desc;
        !          2203: 
        !          2204:       /* Align the location counter as required by EXP's data type.  */
        !          2205:       align = (mode == VOIDmode) ? UNITS_PER_WORD : GET_MODE_SIZE (mode);
        !          2206:       if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
        !          2207:        align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
        !          2208: 
        !          2209:       pool_offset += align - 1;
        !          2210:       pool_offset &= ~ (align - 1);
        !          2211: 
        !          2212:       /* Allocate a pool constant descriptor, fill it in, and chain it in.  */
        !          2213: 
        !          2214:       pool = (struct pool_constant *) oballoc (sizeof (struct pool_constant));
        !          2215:       pool->desc = desc;
        !          2216:       pool->constant = x;
        !          2217:       pool->mode = mode;
        !          2218:       pool->labelno = const_labelno;
        !          2219:       pool->align = align;
        !          2220:       pool->offset = pool_offset;
        !          2221:       pool->next = 0;
        !          2222: 
        !          2223:       if (last_pool == 0)
        !          2224:        first_pool = pool;
        !          2225:       else
        !          2226:        last_pool->next = pool;
        !          2227: 
        !          2228:       last_pool = pool;
        !          2229:       pool_offset += GET_MODE_SIZE (mode);
        !          2230: 
        !          2231:       /* Create a string containing the label name, in LABEL.  */
        !          2232:       ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
        !          2233: 
        !          2234:       ++const_labelno;
        !          2235: 
        !          2236:       desc->label = found
        !          2237:        = (char *) obstack_copy0 (saveable_obstack, label, strlen (label));
        !          2238: 
        !          2239:       /* Add label to symbol hash table.  */
        !          2240:       hash = SYMHASH (found);
        !          2241:       sym = (struct pool_sym *) oballoc (sizeof (struct pool_sym));
        !          2242:       sym->label = found;
        !          2243:       sym->pool = pool;
        !          2244:       sym->next = const_rtx_sym_hash_table[hash];
        !          2245:       const_rtx_sym_hash_table[hash] = sym;
        !          2246:     }
        !          2247: 
        !          2248:   /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
        !          2249: 
        !          2250:   def = gen_rtx (MEM, mode, gen_rtx (SYMBOL_REF, Pmode, found));
        !          2251: 
        !          2252:   RTX_UNCHANGING_P (def) = 1;
        !          2253:   /* Mark the symbol_ref as belonging to this constants pool.  */
        !          2254:   CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1;
        !          2255:   current_function_uses_const_pool = 1;
        !          2256: 
        !          2257:   if (GET_CODE (x) == CONST_DOUBLE)
        !          2258:     {
        !          2259:       if (CONST_DOUBLE_MEM (x) == cc0_rtx)
        !          2260:        {
        !          2261:          CONST_DOUBLE_CHAIN (x) = const_double_chain;
        !          2262:          const_double_chain = x;
        !          2263:        }
        !          2264:       CONST_DOUBLE_MEM (x) = def;
        !          2265:     }
        !          2266: 
        !          2267:   return def;
        !          2268: }
        !          2269: 
        !          2270: /* Given a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true, return a pointer to
        !          2271:    the corresponding pool_constant structure.  */
        !          2272: 
        !          2273: static struct pool_constant *
        !          2274: find_pool_constant (addr)
        !          2275:      rtx addr;
        !          2276: {
        !          2277:   struct pool_sym *sym;
        !          2278:   char *label = XSTR (addr, 0);
        !          2279: 
        !          2280:   for (sym = const_rtx_sym_hash_table[SYMHASH (label)]; sym; sym = sym->next)
        !          2281:     if (sym->label == label)
        !          2282:       return sym->pool;
        !          2283: 
        !          2284:   abort ();
        !          2285: }
        !          2286: 
        !          2287: /* Given a constant pool SYMBOL_REF, return the corresponding constant.  */
        !          2288: 
        !          2289: rtx
        !          2290: get_pool_constant (addr)
        !          2291:      rtx addr;
        !          2292: {
        !          2293:   return (find_pool_constant (addr))->constant;
        !          2294: }
        !          2295: 
        !          2296: /* Similar, return the mode.  */
        !          2297: 
        !          2298: enum machine_mode
        !          2299: get_pool_mode (addr)
        !          2300:      rtx addr;
        !          2301: {
        !          2302:   return (find_pool_constant (addr))->mode;
        !          2303: }
        !          2304: 
        !          2305: /* Similar, return the offset in the constant pool.  */
        !          2306: 
        !          2307: int
        !          2308: get_pool_offset (addr)
        !          2309:      rtx addr;
        !          2310: {
        !          2311:   return (find_pool_constant (addr))->offset;
        !          2312: }
        !          2313: 
        !          2314: /* Return the size of the constant pool.  */
        !          2315: 
        !          2316: int
        !          2317: get_pool_size ()
        !          2318: {
        !          2319:   return pool_offset;
        !          2320: }
        !          2321: 
        !          2322: /* Write all the constants in the constant pool.  */
        !          2323: 
        !          2324: void
        !          2325: output_constant_pool (fnname, fndecl)
        !          2326:      char *fnname;
        !          2327:      tree fndecl;
        !          2328: {
        !          2329:   struct pool_constant *pool;
        !          2330:   rtx x;
        !          2331:   union real_extract u;
        !          2332: 
        !          2333: #ifdef ASM_OUTPUT_POOL_PROLOGUE
        !          2334:   ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool_offset);
        !          2335: #endif
        !          2336: 
        !          2337:   for (pool = first_pool; pool; pool = pool->next)
        !          2338:     {
        !          2339:       x = pool->constant;
        !          2340: 
        !          2341:       /* See if X is a LABEL_REF (or a CONST referring to a LABEL_REF)
        !          2342:         whose CODE_LABEL has been deleted.  This can occur if a jump table
        !          2343:         is eliminated by optimization.  If so, write a constant of zero
        !          2344:         instead.  */
        !          2345:       if ((GET_CODE (x) == LABEL_REF && INSN_DELETED_P (XEXP (x, 0)))
        !          2346:          || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
        !          2347:              && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF
        !          2348:              && INSN_DELETED_P (XEXP (XEXP (XEXP (x, 0), 0), 0))))
        !          2349:        x = const0_rtx;
        !          2350: 
        !          2351:       /* First switch to correct section.  */
        !          2352: #ifdef SELECT_RTX_SECTION
        !          2353:       SELECT_RTX_SECTION (pool->mode, x);
        !          2354: #else
        !          2355:       readonly_data_section ();
        !          2356: #endif
        !          2357: 
        !          2358: #ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
        !          2359:       ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, pool->mode,
        !          2360:                                     pool->align, pool->labelno, done);
        !          2361: #endif
        !          2362: 
        !          2363:       if (pool->align > 1)
        !          2364:        ASM_OUTPUT_ALIGN (asm_out_file, exact_log2 (pool->align));
        !          2365: 
        !          2366:       /* Output the label.  */
        !          2367:       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", pool->labelno);
        !          2368: 
        !          2369:       /* Output the value of the constant itself.  */
        !          2370:       switch (GET_MODE_CLASS (pool->mode))
        !          2371:        {
        !          2372:        case MODE_FLOAT:
        !          2373:          if (GET_CODE (x) != CONST_DOUBLE)
        !          2374:            abort ();
        !          2375: 
        !          2376:          bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u);
        !          2377:          assemble_real (u.d, pool->mode);
        !          2378:          break;
        !          2379: 
        !          2380:        case MODE_INT:
        !          2381:          assemble_integer (x, GET_MODE_SIZE (pool->mode), 1);
        !          2382:          break;
        !          2383: 
        !          2384:        default:
        !          2385:          abort ();
        !          2386:        }
        !          2387: 
        !          2388:     done: ;
        !          2389:     }
        !          2390: 
        !          2391:   /* Done with this pool.  */
        !          2392:   first_pool = last_pool = 0;
        !          2393: }
        !          2394: 
        !          2395: /* Find all the constants whose addresses are referenced inside of EXP,
        !          2396:    and make sure assembler code with a label has been output for each one.
        !          2397:    Indicate whether an ADDR_EXPR has been encountered.  */
        !          2398: 
        !          2399: int
        !          2400: output_addressed_constants (exp)
        !          2401:      tree exp;
        !          2402: {
        !          2403:   int reloc = 0;
        !          2404: 
        !          2405:   switch (TREE_CODE (exp))
        !          2406:     {
        !          2407:     case ADDR_EXPR:
        !          2408:       {
        !          2409:        register tree constant = TREE_OPERAND (exp, 0);
        !          2410: 
        !          2411:        while (TREE_CODE (constant) == COMPONENT_REF)
        !          2412:          {
        !          2413:            constant = TREE_OPERAND (constant, 0);
        !          2414:          }
        !          2415: 
        !          2416:        if (TREE_CODE_CLASS (TREE_CODE (constant)) == 'c'
        !          2417:            || TREE_CODE (constant) == CONSTRUCTOR)
        !          2418:          /* No need to do anything here
        !          2419:             for addresses of variables or functions.  */
        !          2420:          output_constant_def (constant);
        !          2421:       }
        !          2422:       reloc = 1;
        !          2423:       break;
        !          2424: 
        !          2425:     case PLUS_EXPR:
        !          2426:     case MINUS_EXPR:
        !          2427:       reloc = output_addressed_constants (TREE_OPERAND (exp, 0));
        !          2428:       reloc |= output_addressed_constants (TREE_OPERAND (exp, 1));
        !          2429:       break;
        !          2430: 
        !          2431:     case NOP_EXPR:
        !          2432:     case CONVERT_EXPR:
        !          2433:       reloc = output_addressed_constants (TREE_OPERAND (exp, 0));
        !          2434:       break;
        !          2435: 
        !          2436:     case CONSTRUCTOR:
        !          2437:       {
        !          2438:        register tree link;
        !          2439:        for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
        !          2440:          if (TREE_VALUE (link) != 0)
        !          2441:            reloc |= output_addressed_constants (TREE_VALUE (link));
        !          2442:       }
        !          2443:       break;
        !          2444: 
        !          2445:     case ERROR_MARK:
        !          2446:       break;
        !          2447:     }
        !          2448:   return reloc;
        !          2449: }
        !          2450: 
        !          2451: /* Output assembler code for constant EXP to FILE, with no label.
        !          2452:    This includes the pseudo-op such as ".int" or ".byte", and a newline.
        !          2453:    Assumes output_addressed_constants has been done on EXP already.
        !          2454: 
        !          2455:    Generate exactly SIZE bytes of assembler data, padding at the end
        !          2456:    with zeros if necessary.  SIZE must always be specified.
        !          2457: 
        !          2458:    SIZE is important for structure constructors,
        !          2459:    since trailing members may have been omitted from the constructor.
        !          2460:    It is also important for initialization of arrays from string constants
        !          2461:    since the full length of the string constant might not be wanted.
        !          2462:    It is also needed for initialization of unions, where the initializer's
        !          2463:    type is just one member, and that may not be as long as the union.
        !          2464: 
        !          2465:    There a case in which we would fail to output exactly SIZE bytes:
        !          2466:    for a structure constructor that wants to produce more than SIZE bytes.
        !          2467:    But such constructors will never be generated for any possible input.  */
        !          2468: 
        !          2469: void
        !          2470: output_constant (exp, size)
        !          2471:      register tree exp;
        !          2472:      register int size;
        !          2473: {
        !          2474:   register enum tree_code code = TREE_CODE (TREE_TYPE (exp));
        !          2475:   rtx x;
        !          2476: 
        !          2477:   if (size == 0)
        !          2478:     return;
        !          2479: 
        !          2480:   /* Allow a constructor with no elements for any data type.
        !          2481:      This means to fill the space with zeros.  */
        !          2482:   if (TREE_CODE (exp) == CONSTRUCTOR
        !          2483:       && TREE_OPERAND (exp, 1) == 0)
        !          2484:     {
        !          2485:       assemble_zeros (size);
        !          2486:       return;
        !          2487:     }
        !          2488: 
        !          2489:   /* Eliminate the NOP_EXPR that makes a cast not be an lvalue.
        !          2490:      That way we get the constant (we hope) inside it.  */
        !          2491:   if (TREE_CODE (exp) == NOP_EXPR
        !          2492:       && TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0)))
        !          2493:     exp = TREE_OPERAND (exp, 0);
        !          2494: 
        !          2495:   switch (code)
        !          2496:     {
        !          2497:     case INTEGER_TYPE:
        !          2498:     case ENUMERAL_TYPE:
        !          2499:     case POINTER_TYPE:
        !          2500:     case REFERENCE_TYPE:
        !          2501:       /* ??? What about       (int)((float)(int)&foo + 4)    */
        !          2502:       while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
        !          2503:             || TREE_CODE (exp) == NON_LVALUE_EXPR)
        !          2504:        exp = TREE_OPERAND (exp, 0);
        !          2505: 
        !          2506:       if (! assemble_integer (expand_expr (exp, 0, VOIDmode,
        !          2507:                                           EXPAND_INITIALIZER),
        !          2508:                              size, 0))
        !          2509:        error ("initializer for integer value is too complicated");
        !          2510:       size = 0;
        !          2511:       break;
        !          2512: 
        !          2513:     case REAL_TYPE:
        !          2514:       if (TREE_CODE (exp) != REAL_CST)
        !          2515:        error ("initializer for floating value is not a floating constant");
        !          2516: 
        !          2517:       assemble_real (TREE_REAL_CST (exp),
        !          2518:                     mode_for_size (size * BITS_PER_UNIT, MODE_FLOAT, 0));
        !          2519:       size = 0;
        !          2520:       break;
        !          2521: 
        !          2522:     case COMPLEX_TYPE:
        !          2523:       output_constant (TREE_REALPART (exp), size / 2);
        !          2524:       output_constant (TREE_IMAGPART (exp), size / 2);
        !          2525:       size -= (size / 2) * 2;
        !          2526:       break;
        !          2527: 
        !          2528:     case ARRAY_TYPE:
        !          2529:       if (TREE_CODE (exp) == CONSTRUCTOR)
        !          2530:        {
        !          2531:          output_constructor (exp, size);
        !          2532:          return;
        !          2533:        }
        !          2534:       else if (TREE_CODE (exp) == STRING_CST)
        !          2535:        {
        !          2536:          int excess = 0;
        !          2537: 
        !          2538:          if (size > TREE_STRING_LENGTH (exp))
        !          2539:            {
        !          2540:              excess = size - TREE_STRING_LENGTH (exp);
        !          2541:              size = TREE_STRING_LENGTH (exp);
        !          2542:            }
        !          2543: 
        !          2544:          assemble_string (TREE_STRING_POINTER (exp), size);
        !          2545:          size = excess;
        !          2546:        }
        !          2547:       else
        !          2548:        abort ();
        !          2549:       break;
        !          2550: 
        !          2551:     case RECORD_TYPE:
        !          2552:     case UNION_TYPE:
        !          2553:       if (TREE_CODE (exp) == CONSTRUCTOR)
        !          2554:        output_constructor (exp, size);
        !          2555:       else
        !          2556:        abort ();
        !          2557:       return;
        !          2558:     }
        !          2559: 
        !          2560:   if (size > 0)
        !          2561:     assemble_zeros (size);
        !          2562: }
        !          2563: 
        !          2564: /* Subroutine of output_constant, used for CONSTRUCTORs
        !          2565:    (aggregate constants).
        !          2566:    Generate at least SIZE bytes, padding if necessary.  */
        !          2567: 
        !          2568: void
        !          2569: output_constructor (exp, size)
        !          2570:      tree exp;
        !          2571:      int size;
        !          2572: {
        !          2573:   register tree link, field = 0;
        !          2574:   /* Number of bytes output or skipped so far.
        !          2575:      In other words, current position within the constructor.  */
        !          2576:   int total_bytes = 0;
        !          2577:   /* Non-zero means BYTE contains part of a byte, to be output.  */
        !          2578:   int byte_buffer_in_use = 0;
        !          2579:   register int byte;
        !          2580: 
        !          2581:   if (HOST_BITS_PER_INT < BITS_PER_UNIT)
        !          2582:     abort ();
        !          2583: 
        !          2584:   if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
        !          2585:     field = TYPE_FIELDS (TREE_TYPE (exp));
        !          2586: 
        !          2587:   /* As LINK goes through the elements of the constant,
        !          2588:      FIELD goes through the structure fields, if the constant is a structure.
        !          2589:      if the constant is a union, then we override this,
        !          2590:      by getting the field from the TREE_LIST element.
        !          2591:      But the constant could also be an array.  Then FIELD is zero.  */
        !          2592:   for (link = CONSTRUCTOR_ELTS (exp);
        !          2593:        link;
        !          2594:        link = TREE_CHAIN (link),
        !          2595:        field = field ? TREE_CHAIN (field) : 0)
        !          2596:     {
        !          2597:       tree val = TREE_VALUE (link);
        !          2598:       /* the element in a union constructor specifies the proper field.  */
        !          2599:       if (TREE_PURPOSE (link) != 0)
        !          2600:        field = TREE_PURPOSE (link);
        !          2601: 
        !          2602:       /* Eliminate the marker that makes a cast not be an lvalue.  */
        !          2603:       if (val != 0 && TREE_CODE (val) == NON_LVALUE_EXPR)
        !          2604:        val = TREE_OPERAND (val, 0);
        !          2605: 
        !          2606:       if (field == 0 || !DECL_BIT_FIELD (field))
        !          2607:        {
        !          2608:          register int fieldsize;
        !          2609:          /* Since this structure is static,
        !          2610:             we know the positions are constant.  */
        !          2611:          int bitpos = (field ? (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))
        !          2612:                                 / BITS_PER_UNIT)
        !          2613:                        : 0);
        !          2614: 
        !          2615:          /* An element that is not a bit-field.
        !          2616:             Output any buffered-up bit-fields preceding it.  */
        !          2617:          if (byte_buffer_in_use)
        !          2618:            {
        !          2619:              ASM_OUTPUT_BYTE (asm_out_file, byte);
        !          2620:              total_bytes++;
        !          2621:              byte_buffer_in_use = 0;
        !          2622:            }
        !          2623: 
        !          2624:          /* Advance to offset of this element.
        !          2625:             Note no alignment needed in an array, since that is guaranteed
        !          2626:             if each element has the proper size.  */
        !          2627:          if (field != 0 && bitpos != total_bytes)
        !          2628:            {
        !          2629:              assemble_zeros (bitpos - total_bytes);
        !          2630:              total_bytes = bitpos;
        !          2631:            }
        !          2632: 
        !          2633:          /* Determine size this element should occupy.  */
        !          2634:          if (field)
        !          2635:            {
        !          2636:              if (TREE_CODE (DECL_SIZE (field)) != INTEGER_CST)
        !          2637:                abort ();
        !          2638:              if (TREE_INT_CST_LOW (DECL_SIZE (field)) > 100000)
        !          2639:                {
        !          2640:                  /* This avoids overflow trouble.  */
        !          2641:                  tree size_tree = size_binop (CEIL_DIV_EXPR,
        !          2642:                                               DECL_SIZE (field),
        !          2643:                                               size_int (BITS_PER_UNIT));
        !          2644:                  fieldsize = TREE_INT_CST_LOW (size_tree);
        !          2645:                }
        !          2646:              else
        !          2647:                {
        !          2648:                  fieldsize = TREE_INT_CST_LOW (DECL_SIZE (field));
        !          2649:                  fieldsize = (fieldsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
        !          2650:                }
        !          2651:            }
        !          2652:          else
        !          2653:            fieldsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
        !          2654: 
        !          2655:          /* Output the element's initial value.  */
        !          2656:          if (val == 0)
        !          2657:            assemble_zeros (fieldsize);
        !          2658:          else
        !          2659:            output_constant (val, fieldsize);
        !          2660: 
        !          2661:          /* Count its size.  */
        !          2662:          total_bytes += fieldsize;
        !          2663:        }
        !          2664:       else if (val != 0 && TREE_CODE (val) != INTEGER_CST)
        !          2665:        error ("invalid initial value for member `%s'",
        !          2666:               IDENTIFIER_POINTER (DECL_NAME (field)));
        !          2667:       else
        !          2668:        {
        !          2669:          /* Element that is a bit-field.  */
        !          2670: 
        !          2671:          int next_offset = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
        !          2672:          int end_offset
        !          2673:            = (next_offset + TREE_INT_CST_LOW (DECL_SIZE (field)));
        !          2674: 
        !          2675:          if (val == 0)
        !          2676:            val = integer_zero_node;
        !          2677: 
        !          2678:          /* If this field does not start in this (or, next) byte,
        !          2679:             skip some bytes.  */
        !          2680:          if (next_offset / BITS_PER_UNIT != total_bytes)
        !          2681:            {
        !          2682:              /* Output remnant of any bit field in previous bytes.  */
        !          2683:              if (byte_buffer_in_use)
        !          2684:                {
        !          2685:                  ASM_OUTPUT_BYTE (asm_out_file, byte);
        !          2686:                  total_bytes++;
        !          2687:                  byte_buffer_in_use = 0;
        !          2688:                }
        !          2689: 
        !          2690:              /* If still not at proper byte, advance to there.  */
        !          2691:              if (next_offset / BITS_PER_UNIT != total_bytes)
        !          2692:                {
        !          2693:                  assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);
        !          2694:                  total_bytes = next_offset / BITS_PER_UNIT;
        !          2695:                }
        !          2696:            }
        !          2697: 
        !          2698:          if (! byte_buffer_in_use)
        !          2699:            byte = 0;
        !          2700: 
        !          2701:          /* We must split the element into pieces that fall within
        !          2702:             separate bytes, and combine each byte with previous or
        !          2703:             following bit-fields.  */
        !          2704: 
        !          2705:          /* next_offset is the offset n fbits from the begining of
        !          2706:             the structure to the next bit of this element to be processed.
        !          2707:             end_offset is the offset of the first bit past the end of
        !          2708:             this element.  */
        !          2709:          while (next_offset < end_offset)
        !          2710:            {
        !          2711:              int this_time;
        !          2712:              int shift, value;
        !          2713:              int next_byte = next_offset / BITS_PER_UNIT;
        !          2714:              int next_bit = next_offset % BITS_PER_UNIT;
        !          2715: 
        !          2716:              /* Advance from byte to byte
        !          2717:                 within this element when necessary.  */
        !          2718:              while (next_byte != total_bytes)
        !          2719:                {
        !          2720:                  ASM_OUTPUT_BYTE (asm_out_file, byte);
        !          2721:                  total_bytes++;
        !          2722:                  byte = 0;
        !          2723:                }
        !          2724: 
        !          2725:              /* Number of bits we can process at once
        !          2726:                 (all part of the same byte).  */
        !          2727:              this_time = MIN (end_offset - next_offset,
        !          2728:                               BITS_PER_UNIT - next_bit);
        !          2729: #if BYTES_BIG_ENDIAN
        !          2730:              /* On big-endian machine, take the most significant bits
        !          2731:                 first (of the bits that are significant)
        !          2732:                 and put them into bytes from the most significant end.  */
        !          2733:              shift = end_offset - next_offset - this_time;
        !          2734:              /* Don't try to take a bunch of bits that cross
        !          2735:                 the word boundary in the INTEGER_CST.  */
        !          2736:              if (shift < HOST_BITS_PER_INT
        !          2737:                  && shift + this_time > HOST_BITS_PER_INT)
        !          2738:                {
        !          2739:                  this_time -= (HOST_BITS_PER_INT - shift);
        !          2740:                  shift = HOST_BITS_PER_INT;
        !          2741:                }
        !          2742: 
        !          2743:              /* Now get the bits from the appropriate constant word.  */
        !          2744:              if (shift < HOST_BITS_PER_INT)
        !          2745:                {
        !          2746:                  value = TREE_INT_CST_LOW (val);
        !          2747:                }
        !          2748:              else if (shift < 2 * HOST_BITS_PER_INT)
        !          2749:                {
        !          2750:                  value = TREE_INT_CST_HIGH (val);
        !          2751:                  shift -= HOST_BITS_PER_INT;
        !          2752:                }
        !          2753:              else
        !          2754:                abort ();
        !          2755:              byte |= (((value >> shift) & ((1 << this_time) - 1))
        !          2756:                       << (BITS_PER_UNIT - this_time - next_bit));
        !          2757: #else
        !          2758:              /* On little-endian machines,
        !          2759:                 take first the least significant bits of the value
        !          2760:                 and pack them starting at the least significant
        !          2761:                 bits of the bytes.  */
        !          2762:              shift = (next_offset
        !          2763:                       - TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)));
        !          2764:              /* Don't try to take a bunch of bits that cross
        !          2765:                 the word boundary in the INTEGER_CST.  */
        !          2766:              if (shift < HOST_BITS_PER_INT
        !          2767:                  && shift + this_time > HOST_BITS_PER_INT)
        !          2768:                {
        !          2769:                  this_time -= (HOST_BITS_PER_INT - shift);
        !          2770:                  shift = HOST_BITS_PER_INT;
        !          2771:                }
        !          2772: 
        !          2773:              /* Now get the bits from the appropriate constant word.  */
        !          2774:              if (shift < HOST_BITS_PER_INT)
        !          2775:                value = TREE_INT_CST_LOW (val);
        !          2776:              else if (shift < 2 * HOST_BITS_PER_INT)
        !          2777:                {
        !          2778:                  value = TREE_INT_CST_HIGH (val);
        !          2779:                  shift -= HOST_BITS_PER_INT;
        !          2780:                }
        !          2781:              else
        !          2782:                abort ();
        !          2783:              byte |= ((value >> shift) & ((1 << this_time) - 1)) << next_bit;
        !          2784: #endif
        !          2785:              next_offset += this_time;
        !          2786:              byte_buffer_in_use = 1;
        !          2787:            }
        !          2788:        }
        !          2789:     }
        !          2790:   if (byte_buffer_in_use)
        !          2791:     {
        !          2792:       ASM_OUTPUT_BYTE (asm_out_file, byte);
        !          2793:       total_bytes++;
        !          2794:     }
        !          2795:   if (total_bytes < size)
        !          2796:     assemble_zeros (size - total_bytes);
        !          2797: }

unix.superglobalmegacorp.com

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