Annotation of researchv10dc/cmd/gcc/varasm.c, revision 1.1.1.1

1.1       root        1: /* Output variables, constants and external declarations, for GNU compiler.
                      2:    Copyright (C) 1987, 1988 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is distributed in the hope that it will be useful,
                      7: but WITHOUT ANY WARRANTY.  No author or distributor
                      8: accepts responsibility to anyone for the consequences of using it
                      9: or for whether it serves any particular purpose or works at all,
                     10: unless he says so in writing.  Refer to the GNU CC General Public
                     11: License for full details.
                     12: 
                     13: Everyone is granted permission to copy, modify and redistribute
                     14: GNU CC, but only under the conditions described in the
                     15: GNU CC General Public License.   A copy of this license is
                     16: supposed to have been given to you along with GNU CC so you
                     17: can know your rights and responsibilities.  It should be in a
                     18: file named COPYING.  Among other things, the copyright notice
                     19: and this notice must be preserved on all copies.  */
                     20: 
                     21: 
                     22: /* This file handles generation of all the assembler code
                     23:    *except* the instructions of a function.
                     24:    This includes declarations of variables and their initial values.
                     25: 
                     26:    We also output the assembler code for constants stored in memory
                     27:    and are responsible for combining constants with the same value.  */
                     28: 
                     29: #include <stdio.h>
                     30: /* #include <stab.h> */
                     31: #include "config.h"
                     32: #include "rtl.h"
                     33: #include "tree.h"
                     34: #include "flags.h"
                     35: #include "expr.h"
                     36: 
                     37: #include "obstack.h"
                     38: 
                     39: #define MIN(a, b) ((a) < (b) ? (a) : (b))
                     40: 
                     41: /* File in which assembler code is being written.  */
                     42: 
                     43: extern FILE *asm_out_file;
                     44: 
                     45: extern struct obstack *current_obstack;
                     46: extern struct obstack *saveable_obstack;
                     47: extern struct obstack permanent_obstack;
                     48: #define obstack_chunk_alloc xmalloc
                     49: extern int xmalloc ();
                     50: 
                     51: /* Number for making the label on the next
                     52:    constant that is stored in memory.  */
                     53: 
                     54: int const_labelno;
                     55: 
                     56: /* Number for making the label on the next
                     57:    static variable internal to a function.  */
                     58: 
                     59: int var_labelno;
                     60: 
                     61: extern FILE *asm_out_file;
                     62: 
                     63: static char *compare_constant_1 ();
                     64: static void record_constant_1 ();
                     65: void assemble_name ();
                     66: void output_addressed_constants ();
                     67: void output_constant ();
                     68: void output_constructor ();
                     69: 
                     70: /* Output a string of literal assembler code
                     71:    for an `asm' keyword used between functions.  */
                     72: 
                     73: void
                     74: assemble_asm (string)
                     75:      tree string;
                     76: {
                     77:   app_enable ();
                     78: 
                     79:   fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));
                     80: }
                     81: 
                     82: /* Output assembler code associated with defining the name of a function
                     83:    as described by DECL.  */
                     84: 
                     85: void
                     86: assemble_function (decl)
                     87:      tree decl;
                     88: {
                     89:   rtx x, n;
                     90:   char *fnname;
                     91: 
                     92:   /* Get the function's name, as described by its RTL.
                     93:      This may be different from the DECL_NAME name used in the source file.  */
                     94: 
                     95:   x = DECL_RTL (decl);
                     96:   if (GET_CODE (x) != MEM)
                     97:     abort ();
                     98:   n = XEXP (x, 0);
                     99:   if (GET_CODE (n) != SYMBOL_REF)
                    100:     abort ();
                    101:   fnname = XSTR (n, 0);
                    102: 
                    103:   /* The following code does not need preprocessing in the assembler.  */
                    104: 
                    105:   app_disable ();
                    106: 
                    107:   /* Tell assembler to switch to text segment.  */
                    108: 
                    109:   fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
                    110: 
                    111:   /* Tell assembler to move to target machine's alignment for functions.  */
                    112: 
                    113:   ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT));
                    114: 
                    115:   /* Make function name accessible from other files, if appropriate.  */
                    116: 
                    117:   if (TREE_PUBLIC (decl))
                    118:     ASM_GLOBALIZE_LABEL (asm_out_file, fnname);
                    119: 
                    120:   /* Do any machine/system dependent processing of the function name */
                    121: #ifdef ASM_DECLARE_FUNCTION_NAME
                    122:   ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname);
                    123: #else
                    124:   /* Standard thing is just output label for the function.  */
                    125:   ASM_OUTPUT_LABEL (asm_out_file, fnname);
                    126: #endif /* ASM_DECLARE_FUNCTION_NAME */
                    127: }
                    128: 
                    129: /* Assemble " .int 0\n" or whatever this assembler wants.  */
                    130: 
                    131: void
                    132: assemble_integer_zero ()
                    133: {
                    134:   ASM_OUTPUT_INT (asm_out_file, const0_rtx);
                    135: }
                    136: 
                    137: /* Create the rtx to represent a function in calls to it.
                    138:    DECL is a FUNCTION_DECL node which describes which function.
                    139:    The rtl is stored in DECL.  */
                    140: 
                    141: void
                    142: make_function_rtl (decl)
                    143:      tree decl;
                    144: {
                    145:   if (DECL_RTL (decl) == 0)
                    146:     DECL_RTL (decl)
                    147:       = gen_rtx (MEM, DECL_MODE (decl),
                    148:                 gen_rtx (SYMBOL_REF, Pmode,
                    149:                          IDENTIFIER_POINTER (DECL_NAME (decl))));
                    150: }
                    151: 
                    152: /* Assemble everything that is needed for a variable or function declaration.
                    153:    Not used for automatic variables, and not used for function definitions.
                    154:    Should not be called for variables of incomplete structure type.
                    155: 
                    156:    ASMSPEC is the user's specification of assembler symbol name to use.
                    157:    TOP_LEVEL is nonzero if this variable has file scope.
                    158:    WRITE_SYMBOLS is 2 if writing dbx symbol output.
                    159:    The dbx data for a file-scope variable is written here.
                    160:    AT_END is nonzero if this is the special handling, at end of compilation,
                    161:    to define things that have had only tentative definitions.  */
                    162: 
                    163: void
                    164: assemble_variable (decl, asmspec, top_level, write_symbols, at_end)
                    165:      tree decl;
                    166:      tree asmspec;
                    167:      int top_level;
                    168:      int write_symbols;
                    169:      int at_end;
                    170: {
                    171:   register char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
                    172:   register int i;
                    173: 
                    174:   if (asmspec != 0)
                    175:     {
                    176:       if (TREE_CODE (asmspec) != STRING_CST)
                    177:        abort ();
                    178:       name = (char *) oballoc (strlen (TREE_STRING_POINTER (asmspec)) + 2);
                    179:       name[0] = '*';
                    180:       strcpy (&name[1], TREE_STRING_POINTER (asmspec));
                    181:     }
                    182: 
                    183:   /* For a duplicate declaration, we can be called twice on the
                    184:      same DECL node.  Don't alter the RTL already made
                    185:      unless the old mode is wrong (which can happen when
                    186:      the previous rtl was made when the type was incomplete).  */
                    187:   if (DECL_RTL (decl) == 0
                    188:       || GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
                    189:     {
                    190:       if (DECL_RTL (decl) && asmspec == 0)
                    191:        name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
                    192: 
                    193:       /* Can't use just the variable's own name for a variable
                    194:         whose scope is less than the whole file.
                    195:         Concatenate a distinguishing number.  */
                    196:       else if (!top_level && !TREE_EXTERNAL (decl) && asmspec == 0)
                    197:        {
                    198:          char *label;
                    199: 
                    200:          ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
                    201:          name = obstack_copy0 (current_obstack, label, strlen (label));
                    202:          var_labelno++;
                    203:        }
                    204: 
                    205:       DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl),
                    206:                                 gen_rtx (SYMBOL_REF, Pmode, name));
                    207:       if (TREE_VOLATILE (decl))
                    208:        DECL_RTL (decl)->volatil = 1;
                    209:       if (TREE_READONLY (decl))
                    210:        DECL_RTL (decl)->unchanging = 1;
                    211:       DECL_RTL (decl)->in_struct
                    212:        = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
                    213:           || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
                    214:           || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE);
                    215:     }
                    216: 
                    217:   /* Output no assembler code for a function declaration.
                    218:      Only definitions of functions output anything.  */
                    219: 
                    220:   if (TREE_CODE (decl) == FUNCTION_DECL)
                    221:     return;
                    222: 
                    223:   /* Normally no need to say anything for external references,
                    224:      since assembler considers all undefined symbols external.  */
                    225: 
                    226:   if (TREE_EXTERNAL (decl))
                    227:     {
                    228: #ifdef ASM_OUTPUT_EXTERNAL
                    229:       /* Some systems do require some output.  */
                    230:       ASM_OUTPUT_EXTERNAL (asm_out_file, decl, name);
                    231: #endif
                    232:       return;
                    233:     }
                    234:   /* Don't output anything when a tentative file-scope definition is seen.
                    235:      But at end of compilation, do output code for them.  */
                    236:   if (! at_end && top_level
                    237:       && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
                    238:     return;
                    239: 
                    240:   /* If type was incomplete when the variable was declared,
                    241:      see if it is complete now.  */
                    242: 
                    243:   if (DECL_SIZE (decl) == 0)
                    244:     layout_decl (decl);
                    245: 
                    246:   /* Still incomplete => don't allocate it; treat the tentative defn
                    247:      (which is what it must have been) as an `extern' reference.  */
                    248: 
                    249:   if (DECL_SIZE (decl) == 0)
                    250:     {
                    251:       error_with_file_and_line (DECL_SOURCE_FILE (decl),
                    252:                                DECL_SOURCE_LINE (decl),
                    253:                                "storage size of static var `%s' isn't known",
                    254:                                IDENTIFIER_POINTER (DECL_NAME (decl)));
                    255:       return;
                    256:     }
                    257: 
                    258:   /* The first declaration of a variable that comes through this function
                    259:      decides whether it is global (in C, has external linkage)
                    260:      or local (in C, has internal linkage).  So do nothing more
                    261:      if this function has already run.  */
                    262: 
                    263:   if (TREE_ASM_WRITTEN (decl))
                    264:     return;
                    265: 
                    266:   TREE_ASM_WRITTEN (decl) = 1;
                    267: 
                    268:   if (write_symbols == 2)
                    269:     dbxout_symbol (decl, 0);
                    270:   else if (write_symbols != 0)
                    271:     /* Make sure the file is known to GDB even if it has no functions.  */
                    272:     set_current_gdbfile (DECL_SOURCE_FILE (decl));
                    273: 
                    274:   /* If storage size is erroneously variable, just continue.
                    275:      Error message was already made.  */
                    276: 
                    277:   if (! TREE_LITERAL (DECL_SIZE (decl)))
                    278:     return;
                    279: 
                    280:   app_disable ();
                    281: 
                    282:   /* Handle uninitialized definitions.  */
                    283: 
                    284:   if (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
                    285:     {
                    286:       int size = (TREE_INT_CST_LOW (DECL_SIZE (decl))
                    287:                  * DECL_SIZE_UNIT (decl)
                    288:                  / BITS_PER_UNIT);
                    289:       /* Round size up to multiple of BIGGEST_ALIGNMENT bits
                    290:         so that each uninitialized object starts on such a boundary.  */
                    291:       size = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
                    292:              / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
                    293:              * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
                    294:       if (TREE_PUBLIC (decl))
                    295:        ASM_OUTPUT_COMMON (asm_out_file, name, size);
                    296:       else
                    297:        ASM_OUTPUT_LOCAL (asm_out_file, name, size);
                    298:       return;
                    299:     }
                    300: 
                    301:   /* Handle initialized definitions.  */
                    302: 
                    303:   if (TREE_PUBLIC (decl))
                    304:     ASM_GLOBALIZE_LABEL (asm_out_file, name);
                    305: 
                    306:   output_addressed_constants (DECL_INITIAL (decl));
                    307: 
                    308:   if (TREE_READONLY (decl) && ! TREE_VOLATILE (decl))
                    309:     fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
                    310:   else
                    311:     fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
                    312: 
                    313:   for (i = 0; DECL_ALIGN (decl) >= BITS_PER_UNIT << (i + 1); i++);
                    314: 
                    315:   ASM_OUTPUT_ALIGN (asm_out_file, i);
                    316: 
                    317:   ASM_OUTPUT_LABEL (asm_out_file, name);
                    318:   output_constant (DECL_INITIAL (decl), int_size_in_bytes (TREE_TYPE (decl)));
                    319: }
                    320: 
                    321: /* Output to FILE a reference to the assembler name of a C-level name NAME.
                    322:    If NAME starts with a *, the rest of NAME is output verbatim.
                    323:    Otherwise NAME is transformed in an implementation-defined way
                    324:    (usually by the addition of an underscore).
                    325:    Many macros in the tm file are defined to call this function.  */
                    326: 
                    327: void
                    328: assemble_name (file, name)
                    329:      FILE *file;
                    330:      char *name;
                    331: {
                    332:   if (name[0] == '*')
                    333:     fputs (&name[1], file);
                    334:   else
                    335:     ASM_OUTPUT_LABELREF (file, name);
                    336: }
                    337: 
                    338: /* Here we combine duplicate floating constants to make
                    339:    CONST_DOUBLE rtx's, and force those out to memory when necessary.  */
                    340: 
                    341: /* Chain of all CONST_DOUBLE rtx's constructed for the current function.
                    342:    They are chained through the third operand slot.  */
                    343: 
                    344: extern rtx real_constant_chain;
                    345: 
                    346: /* Return a CONST_DOUBLE for a specified `double' value
                    347:    and machine mode.  */
                    348: 
                    349: rtx
                    350: immed_real_const_1 (d, mode)
                    351:      double d;
                    352:      enum machine_mode mode;
                    353: 
                    354: {
                    355:   register rtx r;
                    356:   union {double d; int i[2];} u;
                    357:   register int i0, i1;
                    358: 
                    359:   /* Get the desired `double' value as two ints
                    360:      since that is how they are stored in a CONST_DOUBLE.  */
                    361: 
                    362:   u.d = d;
                    363:   i0 = u.i[0];
                    364:   i1 = u.i[1];
                    365: 
                    366:   /* Search the chain for an existing CONST_DOUBLE with the right value.
                    367:      If one is found, return it.  */
                    368: 
                    369:   for (r = real_constant_chain; r; r = XEXP (r, 3))
                    370:     if (XINT (r, 0) == i0 && XINT (r, 1) == i1
                    371:        && GET_MODE (r) == mode)
                    372:       return r;
                    373: 
                    374:   /* No; make a new one and add it to the chain.  */
                    375: 
                    376:   r = gen_rtx (CONST_DOUBLE, mode, i0, i1, 0);
                    377:   XEXP (r, 3) = real_constant_chain;
                    378:   real_constant_chain = r;
                    379: 
                    380:   /* Store const0_rtx in slot 2 just so most things won't barf.
                    381:      Actual use of slot 2 is only through force_const_double_mem.  */
                    382: 
                    383:   XEXP (r, 2) = const0_rtx;
                    384: 
                    385:   return r;
                    386: }
                    387: 
                    388: /* Return a CONST_DOUBLE rtx for a value specified by EXP,
                    389:    which must be a REAL_CST tree node.  Make only one CONST_DOUBLE
                    390:    for each distinct value.  */
                    391: 
                    392: rtx
                    393: immed_real_const (exp)
                    394:      tree exp;
                    395: {
                    396:   register rtx r;
                    397:   r = immed_real_const_1 (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)));
                    398: 
                    399:   /* Associate exp and with this rtl value.  */
                    400:   TREE_CST_RTL (exp) = r;
                    401: 
                    402:   return r;
                    403: }
                    404: 
                    405: /* Given a CONST_DOUBLE, cause a constant in memory to be created
                    406:    (unless we already have one for the same value)
                    407:    and return a MEM rtx to refer to it.  */
                    408: 
                    409: rtx
                    410: force_const_double_mem (r)
                    411:      rtx r;
                    412: {
                    413:   if (XEXP (r, 2) == const0_rtx)
                    414:     {
                    415:       XEXP (r, 2) = force_const_mem (GET_MODE (r), r);
                    416:     }
                    417:   /* XEXP (r, 2) is now a MEM with a constant address.
                    418:      If that is legitimate, return it.
                    419:      Othewise it will need reloading, so return a copy of it.  */
                    420:   if (memory_address_p (GET_MODE (r), XEXP (XEXP (r, 2), 0)))
                    421:     return XEXP (r, 2);
                    422:   return gen_rtx (MEM, GET_MODE (r), XEXP (XEXP (r, 2), 0));
                    423: }
                    424: 
                    425: /* At the start of a function, forget the memory-constants
                    426:    previously made for CONST_DOUBLEs.  */
                    427: 
                    428: static void
                    429: clear_const_double_mem ()
                    430: {
                    431:   register rtx r;
                    432: 
                    433:   for (r = real_constant_chain; r; r = XEXP (r, 3))
                    434:     XEXP (r, 2) = 0;
                    435: }
                    436: 
                    437: /* Given an expression EXP with a constant value,
                    438:    reduce it to the sum of an assembler symbol and an integer.
                    439:    Store them both in the structure *VALUE.
                    440:    Abort if EXP does not reduce.  */
                    441: 
                    442: struct addr_const
                    443: {
                    444:   rtx base;
                    445:   int offset;
                    446: };
                    447: 
                    448: static void
                    449: decode_addr_const (exp, value)
                    450:      tree exp;
                    451:      struct addr_const *value;
                    452: {
                    453:   register tree target = TREE_OPERAND (exp, 0);
                    454:   register int offset = 0;
                    455:   register rtx x;
                    456: 
                    457:   while (1)
                    458:     {
                    459:       if (TREE_CODE (target) == COMPONENT_REF)
                    460:        {
                    461:          offset += DECL_OFFSET (TREE_OPERAND (target, 1)) / BITS_PER_UNIT;
                    462:          target = TREE_OPERAND (target, 0);
                    463:        }
                    464:       else if (TREE_CODE (target) == ARRAY_REF)
                    465:        {
                    466:          if (TREE_CODE (TREE_OPERAND (target, 1)) != INTEGER_CST
                    467:              || TREE_CODE (TYPE_SIZE (TREE_TYPE (target))) != INTEGER_CST)
                    468:            abort ();
                    469:          offset += ((TYPE_SIZE_UNIT (TREE_TYPE (target))
                    470:                      * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (target)))
                    471:                      * TREE_INT_CST_LOW (TREE_OPERAND (target, 1)))
                    472:                     / BITS_PER_UNIT);
                    473:          target = TREE_OPERAND (target, 0);
                    474:        }
                    475:       else break;
                    476:     }
                    477: 
                    478:   if (TREE_CODE (target) == VAR_DECL
                    479:       || TREE_CODE (target) == FUNCTION_DECL)
                    480:     x = DECL_RTL (target);
                    481:   else if (TREE_LITERAL (target))
                    482:     x = TREE_CST_RTL (target);
                    483:   else
                    484:     abort ();
                    485: 
                    486:   if (GET_CODE (x) != MEM)
                    487:     abort ();
                    488:   x = XEXP (x, 0);
                    489: 
                    490:   value->base = x;
                    491:   value->offset = offset;
                    492: }
                    493: 
                    494: /* Uniquize all constants that appear in memory.
                    495:    Each constant in memory thus far output is recorded
                    496:    in `const_hash_table' with a `struct constant_descriptor'
                    497:    that contains a polish representation of the value of
                    498:    the constant.
                    499: 
                    500:    We cannot store the trees in the hash table
                    501:    because the trees may be temporary.  */
                    502: 
                    503: struct constant_descriptor
                    504: {
                    505:   struct constant_descriptor *next;
                    506:   char *label;
                    507:   char contents[1];
                    508: };
                    509: 
                    510: #define HASHBITS 30
                    511: #define MAX_HASH_TABLE 1007
                    512: static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
                    513: 
                    514: /* Compute a hash code for a constant expression.  */
                    515: 
                    516: int
                    517: const_hash (exp)
                    518:      tree exp;
                    519: {
                    520:   register char *p;
                    521:   register int len, hi, i;
                    522:   register enum tree_code code = TREE_CODE (exp);
                    523: 
                    524:   if (code == INTEGER_CST)
                    525:     {
                    526:       p = (char *) &TREE_INT_CST_LOW (exp);
                    527:       len = 2 * sizeof TREE_INT_CST_LOW (exp);
                    528:     }
                    529:   else if (code == REAL_CST)
                    530:     {
                    531:       p = (char *) &TREE_REAL_CST (exp);
                    532:       len = sizeof TREE_REAL_CST (exp);
                    533:     }
                    534:   else if (code == STRING_CST)
                    535:     p = TREE_STRING_POINTER (exp), len = TREE_STRING_LENGTH (exp);
                    536:   else if (code == COMPLEX_CST)
                    537:     return const_hash (TREE_REALPART (exp)) * 5
                    538:       + const_hash (TREE_IMAGPART (exp));
                    539:   else if (code == CONSTRUCTOR)
                    540:     {
                    541:       register tree link;
                    542:       hi = 5;
                    543:       for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
                    544:        hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE;
                    545:       return hi;
                    546:     }
                    547:   else if (code == ADDR_EXPR)
                    548:     {
                    549:       struct addr_const value;
                    550:       decode_addr_const (exp, &value);
                    551:       p = (char *) &value;
                    552:       len = sizeof value;
                    553:     }
                    554:   else if (code == PLUS_EXPR || code == MINUS_EXPR)
                    555:     return const_hash (TREE_OPERAND (exp, 0)) * 9
                    556:       +  const_hash (TREE_OPERAND (exp, 1));
                    557:   else if (code == NOP_EXPR || code == CONVERT_EXPR)
                    558:     return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
                    559: 
                    560:   /* Compute hashing function */
                    561:   hi = len;
                    562:   for (i = 0; i < len; i++)
                    563:     hi = ((hi * 613) + (unsigned)(p[i]));
                    564: 
                    565:   hi &= (1 << HASHBITS) - 1;
                    566:   hi %= MAX_HASH_TABLE;
                    567:   return hi;
                    568: }
                    569: 
                    570: /* Compare a constant expression EXP with a constant-descriptor DESC.
                    571:    Return 1 if DESC describes a constant with the same value as EXP.  */
                    572: 
                    573: static int
                    574: compare_constant (exp, desc)
                    575:      tree exp;
                    576:      struct constant_descriptor *desc;
                    577: {
                    578:   return 0 != compare_constant_1 (exp, desc->contents);
                    579: }
                    580: 
                    581: /* Compare constant expression EXP with a substring P of a constant descriptor.
                    582:    If they match, return a pointer to the end of the substring matched.
                    583:    If they do not match, return 0.
                    584: 
                    585:    Since descriptors are written in polish prefix notation,
                    586:    this function can be used recursively to test one operand of EXP
                    587:    against a subdescriptor, and if it succeeds it returns the
                    588:    address of the subdescriptor for the next operand.  */
                    589: 
                    590: static char *
                    591: compare_constant_1 (exp, p)
                    592:      tree exp;
                    593:      char *p;
                    594: {
                    595:   register char *strp;
                    596:   register int len;
                    597:   register enum tree_code code = TREE_CODE (exp);
                    598: 
                    599:   if (code != (enum tree_code) *p++)
                    600:     return 0;
                    601: 
                    602:   if (code == INTEGER_CST)
                    603:     {
                    604:       strp = (char *) &TREE_INT_CST_LOW (exp);
                    605:       len = 2 * sizeof TREE_INT_CST_LOW (exp);
                    606:     }
                    607:   else if (code == REAL_CST)
                    608:     {
                    609:       /* Real constants are the same only if the same width of type.  */
                    610:       if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
                    611:        return 0;
                    612:       strp = (char *) &TREE_REAL_CST (exp);
                    613:       len = sizeof TREE_REAL_CST (exp);
                    614:     }
                    615:   else if (code == STRING_CST)
                    616:     {
                    617:       if (flag_writable_strings)
                    618:        return 0;
                    619:       strp = TREE_STRING_POINTER (exp);
                    620:       len = TREE_STRING_LENGTH (exp);
                    621:       if (bcmp (&TREE_STRING_LENGTH (exp), p,
                    622:                sizeof TREE_STRING_LENGTH (exp)))
                    623:        return 0;
                    624:       p += sizeof TREE_STRING_LENGTH (exp);
                    625:     }
                    626:   else if (code == COMPLEX_CST)
                    627:     {
                    628:       p = compare_constant_1 (TREE_REALPART (exp), p);
                    629:       if (p == 0) return 0;
                    630:       p = compare_constant_1 (TREE_IMAGPART (exp), p);
                    631:       return p;
                    632:     }
                    633:   else if (code == CONSTRUCTOR)
                    634:     {
                    635:       register tree link;
                    636:       int length = list_length (CONSTRUCTOR_ELTS (exp));
                    637:       if (bcmp (&length, p, sizeof length))
                    638:        return 0;
                    639:       p += sizeof length;
                    640:       for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
                    641:        if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0)
                    642:          return 0;
                    643:       return p;
                    644:     }
                    645:   else if (code == ADDR_EXPR)
                    646:     {
                    647:       struct addr_const value;
                    648:       decode_addr_const (exp, &value);
                    649:       strp = (char *) &value;
                    650:       len = sizeof value;
                    651:     }
                    652:   else if (code == PLUS_EXPR || code == MINUS_EXPR)
                    653:     {
                    654:       if (*p++ != (char) code)
                    655:        return 0;
                    656:       p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
                    657:       if (p == 0) return 0;
                    658:       p = compare_constant_1 (TREE_OPERAND (exp, 1), p);
                    659:       return p;
                    660:     }
                    661:   else if (code == NOP_EXPR || code == CONVERT_EXPR)
                    662:     {
                    663:       if (*p++ != (char) code)
                    664:        return 0;
                    665:       p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
                    666:       return p;
                    667:     }
                    668: 
                    669:   /* Compare constant contents.  */
                    670:   while (--len >= 0)
                    671:     if (*p++ != *strp++)
                    672:       return 0;
                    673: 
                    674:   return p;
                    675: }
                    676: 
                    677: /* Construct a constant descriptor for the expression EXP.
                    678:    It is up to the caller to enter the descriptor in the hash table.  */
                    679: 
                    680: static struct constant_descriptor *
                    681: record_constant (exp)
                    682:      tree exp;
                    683: {
                    684:   struct constant_descriptor *ptr = 0;
                    685:   int buf;
                    686: 
                    687:   obstack_grow (&permanent_obstack, &ptr, sizeof ptr);
                    688:   obstack_grow (&permanent_obstack, &buf, sizeof buf);
                    689:   record_constant_1 (exp);
                    690:   return (struct constant_descriptor *) obstack_finish (&permanent_obstack);
                    691: }
                    692: 
                    693: /* Add a description of constant expression EXP
                    694:    to the object growing in `permanent_obstack'.
                    695:    No need to return its address; the caller will get that
                    696:    from the obstack when the object is complete.  */
                    697: 
                    698: static void
                    699: record_constant_1 (exp)
                    700:      tree exp;
                    701: {
                    702:   register char *strp;
                    703:   register int len;
                    704:   register enum tree_code code = TREE_CODE (exp);
                    705: 
                    706:   obstack_1grow (&permanent_obstack, (unsigned char) code);
                    707: 
                    708:   if (code == INTEGER_CST)
                    709:     {
                    710:       strp = (char *) &TREE_INT_CST_LOW (exp);
                    711:       len = 2 * sizeof TREE_INT_CST_LOW (exp);
                    712:     }
                    713:   else if (code == REAL_CST)
                    714:     {
                    715:       obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
                    716:       strp = (char *) &TREE_REAL_CST (exp);
                    717:       len = sizeof TREE_REAL_CST (exp);
                    718:     }
                    719:   else if (code == STRING_CST)
                    720:     {
                    721:       if (flag_writable_strings)
                    722:        return;
                    723:       strp = TREE_STRING_POINTER (exp);
                    724:       len = TREE_STRING_LENGTH (exp);
                    725:       obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp),
                    726:                    sizeof TREE_STRING_LENGTH (exp));
                    727:     }
                    728:   else if (code == COMPLEX_CST)
                    729:     {
                    730:       record_constant_1 (TREE_REALPART (exp));
                    731:       record_constant_1 (TREE_IMAGPART (exp));
                    732:       return;
                    733:     }
                    734:   else if (code == CONSTRUCTOR)
                    735:     {
                    736:       register tree link;
                    737:       int length = list_length (CONSTRUCTOR_ELTS (exp));
                    738:       obstack_grow (&permanent_obstack, (char *) &length, sizeof length);
                    739: 
                    740:       for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
                    741:        record_constant_1 (TREE_VALUE (link));
                    742:       return;
                    743:     }
                    744:   else if (code == ADDR_EXPR)
                    745:     {
                    746:       struct addr_const value;
                    747:       decode_addr_const (exp, &value);
                    748:       strp = (char *) &value;
                    749:       len = sizeof value;
                    750:     }
                    751:   else if (code == PLUS_EXPR || code == MINUS_EXPR)
                    752:     {
                    753:       obstack_1grow (&permanent_obstack, (char) code);
                    754:       record_constant_1 (TREE_OPERAND (exp, 0));
                    755:       record_constant_1 (TREE_OPERAND (exp, 1));
                    756:       return;
                    757:     }
                    758:   else if (code == NOP_EXPR || code == CONVERT_EXPR)
                    759:     {
                    760:       obstack_1grow (&permanent_obstack, (char) code);
                    761:       record_constant_1 (TREE_OPERAND (exp, 0));
                    762:       return;
                    763:     }
                    764: 
                    765:   /* Record constant contents.  */
                    766:   obstack_grow (&permanent_obstack, strp, len);
                    767: }
                    768: 
                    769: /* Return the constant-label-string for constant value EXP.
                    770:    If no constant equal to EXP has yet been output,
                    771:    define a new label and output assembler code for it.
                    772:    The const_hash_table records which constants already have label strings.  */
                    773: 
                    774: static char *
                    775: get_or_assign_label (exp)
                    776:      tree exp;
                    777: {
                    778:   register int hash, i;
                    779:   register struct constant_descriptor *desc;
                    780:   char label[10];
                    781: 
                    782:   /* Make sure any other constants whose addresses appear in EXP
                    783:      are assigned label numbers.  */
                    784: 
                    785:   output_addressed_constants (exp);
                    786: 
                    787:   /* Compute hash code of EXP.  Search the descriptors for that hash code
                    788:      to see if any of them describes EXP.  If yes, the descriptor records
                    789:      the label number already assigned.  */
                    790: 
                    791:   hash = const_hash (exp) % MAX_HASH_TABLE;
                    792: 
                    793:   for (desc = const_hash_table[hash]; desc; desc = desc->next)
                    794:     if (compare_constant (exp, desc))
                    795:       return desc->label;
                    796: 
                    797:   /* No constant equal to EXP is known to have been output.
                    798:      Make a constant descriptor to enter EXP in the hash table.
                    799:      Assign the label number and record it in the descriptor for
                    800:      future calls to this function to find.  */
                    801: 
                    802:   desc = record_constant (exp);
                    803:   desc->next = const_hash_table[hash];
                    804:   const_hash_table[hash] = desc;
                    805: 
                    806:   /* Now output assembler code to define that label
                    807:      and follow it with the data of EXP.  */
                    808: 
                    809:   /* First switch to text segment, except for writable strings.  */
                    810:   if ((TREE_CODE (exp) == STRING_CST) && flag_writable_strings)
                    811:     fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
                    812:   else
                    813:     fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
                    814: 
                    815:   /* Align the location counter as required by EXP's data type.  */
                    816:   for (i = 0; TYPE_ALIGN (TREE_TYPE (exp)) >= BITS_PER_UNIT << (i + 1); i++);
                    817:   ASM_OUTPUT_ALIGN (asm_out_file, i);
                    818: 
                    819:   /* Output the label itself.  */
                    820:   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", const_labelno);
                    821: 
                    822:   /* Output the value of EXP.  */
                    823:   output_constant (exp,
                    824:                   (TREE_CODE (exp) == STRING_CST
                    825:                    ? TREE_STRING_LENGTH (exp)
                    826:                    : int_size_in_bytes (TREE_TYPE (exp))));
                    827: 
                    828:   /* Create a string containing the label name, in LABEL.  */
                    829:   ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
                    830: 
                    831:   ++const_labelno;
                    832: 
                    833:   desc->label
                    834:     = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
                    835: 
                    836:   return desc->label;
                    837: }
                    838: 
                    839: /* Return an rtx representing a reference to constant data in memory
                    840:    for the constant expression EXP.
                    841:    If assembler code for such a constant has already been output,
                    842:    return an rtx to refer to it.
                    843:    Otherwise, output such a constant in memory and generate
                    844:    an rtx for it.  The TREE_CST_RTL of EXP is set up to point to that rtx.  */
                    845: 
                    846: rtx
                    847: output_constant_def (exp)
                    848:      tree exp;
                    849: {
                    850:   register rtx def;
                    851:   char label[10];
                    852: 
                    853:   if (TREE_CST_RTL (exp))
                    854:     return TREE_CST_RTL (exp);
                    855: 
                    856:   def = gen_rtx (SYMBOL_REF, Pmode, get_or_assign_label (exp));
                    857: 
                    858:   TREE_CST_RTL (exp)
                    859:     = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), def);
                    860:   TREE_CST_RTL (exp)->unchanging = 1;
                    861: 
                    862:   return TREE_CST_RTL (exp);
                    863: }
                    864: 
                    865: /* Similar hash facility for making memory-constants
                    866:    from constant rtl-expressions.  It is used on RISC machines
                    867:    where immediate integer arguments and constant addresses are restricted
                    868:    so that such constants must be stored in memory.
                    869: 
                    870:    This pool of constants is reinitialized for each function
                    871:    so each function gets its own constants-pool that comes right before it.  */
                    872: 
                    873: #define MAX_RTX_HASH_TABLE 61
                    874: static struct constant_descriptor *const_rtx_hash_table[MAX_RTX_HASH_TABLE];
                    875: 
                    876: void
                    877: init_const_rtx_hash_table ()
                    878: {
                    879:   bzero (const_rtx_hash_table, sizeof const_rtx_hash_table);
                    880:   clear_const_double_mem ();
                    881: }
                    882: 
                    883: struct rtx_const
                    884: {
                    885:   enum kind { RTX_DOUBLE, RTX_INT } kind : 16;
                    886:   enum machine_mode mode : 16;
                    887:   union {
                    888:     int d[2];
                    889:     struct addr_const addr;
                    890:   } un;
                    891: };
                    892: 
                    893: /* Express an rtx for a constant integer (perhaps symbolic)
                    894:    as the sum of a symbol or label plus an explicit integer.
                    895:    They are stored into VALUE.  */
                    896: 
                    897: static void
                    898: decode_rtx_const (x, value)
                    899:      rtx x;
                    900:      struct rtx_const *value;
                    901: {
                    902:   value->kind = RTX_INT;       /* Most usual kind. */
                    903:   value->mode = GET_MODE (x);
                    904:   value->un.addr.base = 0;
                    905:   value->un.addr.offset = 0;
                    906: 
                    907:   switch (GET_CODE (x))
                    908:     {
                    909:     case CONST_DOUBLE:
                    910:       value->kind = RTX_DOUBLE;
                    911:       value->mode = GET_MODE (x);
                    912:       value->un.d[0] = XINT (x, 0);
                    913:       value->un.d[1] = XINT (x, 1);
                    914:       break;
                    915: 
                    916:     case CONST_INT:
                    917:       value->un.addr.offset = INTVAL (x);
                    918:       break;
                    919: 
                    920:     case SYMBOL_REF:
                    921:       /* Use the string's address, not the SYMBOL_REF's address,
                    922:         for the sake of addresses of library routines.  */
                    923:       value->un.addr.base = XEXP (x, 0);
                    924:       break;
                    925: 
                    926:     case LABEL_REF:
                    927:       /* Return the CODE_LABEL, not the LABEL_REF.  */
                    928:       value->un.addr.base = XEXP (x, 0);
                    929:       break;
                    930:     
                    931:     case CONST:
                    932:       x = XEXP (x, 0);
                    933:       if (GET_CODE (x) == PLUS)
                    934:        {
                    935:          value->un.addr.base = XEXP (x, 0);
                    936:          if (GET_CODE (XEXP (x, 1)) != CONST_INT)
                    937:            abort ();
                    938:          value->un.addr.offset = INTVAL (XEXP (x, 1));
                    939:        }
                    940:       else if (GET_CODE (x) == MINUS)
                    941:        {
                    942:          value->un.addr.base = XEXP (x, 0);
                    943:          if (GET_CODE (XEXP (x, 1)) != CONST_INT)
                    944:            abort ();
                    945:          value->un.addr.offset = - INTVAL (XEXP (x, 1));
                    946:        }
                    947:       else
                    948:        abort ();
                    949:       break;
                    950: 
                    951:     default:
                    952:       abort ();
                    953:     }
                    954: }
                    955: 
                    956: /* Compute a hash code for a constant RTL expression.  */
                    957: 
                    958: int
                    959: const_hash_rtx (x)
                    960:      rtx x;
                    961: {
                    962:   register int hi, i, len;
                    963:   register char *p;
                    964: 
                    965:   struct rtx_const value;
                    966:   decode_rtx_const (x, &value);
                    967: 
                    968:   /* Compute hashing function */
                    969:   hi = 0;
                    970:   for (i = 0; i < sizeof value / sizeof (int); i++)
                    971:     hi += ((int *) &value)[i];
                    972: 
                    973:   hi &= (1 << HASHBITS) - 1;
                    974:   hi %= MAX_RTX_HASH_TABLE;
                    975:   return hi;
                    976: }
                    977: 
                    978: /* Compare a constant rtl object X with a constant-descriptor DESC.
                    979:    Return 1 if DESC describes a constant with the same value as X.  */
                    980: 
                    981: static int
                    982: compare_constant_rtx (x, desc)
                    983:      rtx x;
                    984:      struct constant_descriptor *desc;
                    985: {
                    986:   register int *p = (int *) desc->contents;
                    987:   register int *strp;
                    988:   register int len;
                    989:   struct rtx_const value;
                    990: 
                    991:   decode_rtx_const (x, &value);
                    992:   strp = (int *) &value;
                    993:   len = sizeof value / sizeof (int);
                    994: 
                    995:   /* Compare constant contents.  */
                    996:   while (--len >= 0)
                    997:     if (*p++ != *strp++)
                    998:       return 0;
                    999: 
                   1000:   return 1;
                   1001: }
                   1002: 
                   1003: /* Construct a constant descriptor for the rtl-expression X.
                   1004:    It is up to the caller to enter the descriptor in the hash table.  */
                   1005: 
                   1006: static struct constant_descriptor *
                   1007: record_constant_rtx (x)
                   1008:      rtx x;
                   1009: {
                   1010:   struct constant_descriptor *ptr = 0;
                   1011:   int buf;
                   1012:   struct rtx_const value;
                   1013: 
                   1014:   decode_rtx_const (x, &value);
                   1015: 
                   1016:   obstack_grow (saveable_obstack, &ptr, sizeof ptr);
                   1017:   obstack_grow (saveable_obstack, &buf, sizeof buf);
                   1018: 
                   1019:   /* Record constant contents.  */
                   1020:   obstack_grow (saveable_obstack, &value, sizeof value);
                   1021: 
                   1022:   return (struct constant_descriptor *) obstack_finish (saveable_obstack);
                   1023: }
                   1024: 
                   1025: /* Given a constant rtx X, make (or find) a memory constant for its value
                   1026:    and return a MEM rtx to refer to it in memory.  */
                   1027: 
                   1028: rtx
                   1029: force_const_mem (mode, x)
                   1030:      enum machine_mode mode;
                   1031:      rtx x;
                   1032: {
                   1033:   register int hash, i;
                   1034:   register struct constant_descriptor *desc;
                   1035:   char label[10];
                   1036:   char *found = 0;
                   1037:   rtx def;
                   1038: 
                   1039:   /* Compute hash code of X.  Search the descriptors for that hash code
                   1040:      to see if any of them describes X.  If yes, the descriptor records
                   1041:      the label number already assigned.  */
                   1042: 
                   1043:   hash = const_hash_rtx (x);
                   1044: 
                   1045:   for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next)
                   1046:     if (compare_constant_rtx (x, desc))
                   1047:       {
                   1048:        found = desc->label;
                   1049:        break;
                   1050:       }
                   1051: 
                   1052:   if (found == 0)
                   1053:     {
                   1054:       /* No constant equal to X is known to have been output.
                   1055:         Make a constant descriptor to enter X in the hash table.
                   1056:         Assign the label number and record it in the descriptor for
                   1057:         future calls to this function to find.  */
                   1058: 
                   1059:       desc = record_constant_rtx (x);
                   1060:       desc->next = const_rtx_hash_table[hash];
                   1061:       const_rtx_hash_table[hash] = desc;
                   1062: 
                   1063:       /* Now output assembler code to define that label
                   1064:         and follow it with the data of EXP.  */
                   1065: 
                   1066:       /* First switch to text segment.  */
                   1067:       fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
                   1068: 
                   1069:       /* Align the location counter as required by EXP's data type.  */
                   1070:       ASM_OUTPUT_ALIGN (asm_out_file, exact_log2 (UNITS_PER_WORD));
                   1071: 
                   1072:       /* Output the label itself.  */
                   1073:       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", const_labelno);
                   1074: 
                   1075:       /* Output the value of EXP.  */
                   1076:       if (GET_CODE (x) == CONST_DOUBLE)
                   1077:        {
                   1078:          union {double d; int i[2];} u;
                   1079: 
                   1080:          u.i[0] = XINT (x, 0);
                   1081:          u.i[1] = XINT (x, 1);
                   1082:          if (GET_MODE_SIZE (GET_MODE (x)) == GET_MODE_SIZE (DFmode))
                   1083:            ASM_OUTPUT_DOUBLE (asm_out_file, u.d);
                   1084:          else
                   1085:            ASM_OUTPUT_FLOAT (asm_out_file, u.d);
                   1086:        }
                   1087:       else
                   1088:        ASM_OUTPUT_INT (asm_out_file, x);
                   1089: 
                   1090:       /* Create a string containing the label name, in LABEL.  */
                   1091:       ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
                   1092: 
                   1093:       ++const_labelno;
                   1094: 
                   1095:       desc->label = found
                   1096:        = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
                   1097:     }
                   1098: 
                   1099:   /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
                   1100: 
                   1101:   def = gen_rtx (MEM, mode, gen_rtx (SYMBOL_REF, Pmode, desc->label));
                   1102: 
                   1103:   def->unchanging = 1;
                   1104:   /* Mark the symbol_ref as belonging to this constants pool.  */
                   1105:   XEXP (def, 0)->unchanging = 1;
                   1106: 
                   1107:   return def;
                   1108: }
                   1109: 
                   1110: /* Find all the constants whose addresses are referenced inside of EXP,
                   1111:    and make sure assembler code with a label has been output for each one.  */
                   1112: 
                   1113: void
                   1114: output_addressed_constants (exp)
                   1115:      tree exp;
                   1116: {
                   1117:   switch (TREE_CODE (exp))
                   1118:     {
                   1119:     case ADDR_EXPR:
                   1120:       {
                   1121:        register tree constant = TREE_OPERAND (exp, 0);
                   1122: 
                   1123:        while (TREE_CODE (constant) == COMPONENT_REF)
                   1124:          {
                   1125:            constant = TREE_OPERAND (constant, 0);
                   1126:          }
                   1127: 
                   1128:        if (TREE_LITERAL (constant))
                   1129:          /* No need to do anything here
                   1130:             for addresses of variables or functions.  */
                   1131:          output_constant_def (constant);
                   1132:       }
                   1133:       break;
                   1134: 
                   1135:     case PLUS_EXPR:
                   1136:     case MINUS_EXPR:
                   1137:       output_addressed_constants (TREE_OPERAND (exp, 0));
                   1138:       output_addressed_constants (TREE_OPERAND (exp, 1));
                   1139:       break;
                   1140: 
                   1141:     case NOP_EXPR:
                   1142:     case CONVERT_EXPR:
                   1143:       output_addressed_constants (TREE_OPERAND (exp, 0));
                   1144:       break;
                   1145: 
                   1146:     case CONSTRUCTOR:
                   1147:       {
                   1148:        register tree link;
                   1149:        for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
                   1150:          output_addressed_constants (TREE_VALUE (link));
                   1151:       }
                   1152:       break;
                   1153: 
                   1154:     case ERROR_MARK:
                   1155:       break;
                   1156: 
                   1157:     default:
                   1158:       if (! TREE_LITERAL (exp))
                   1159:        abort ();
                   1160:     }
                   1161: }
                   1162: 
                   1163: /* Output assembler code for constant EXP to FILE, with no label.
                   1164:    This includes the pseudo-op such as ".int" or ".byte", and a newline.
                   1165:    Assumes output_addressed_constants has been done on EXP already.
                   1166: 
                   1167:    Generate exactly SIZE bytes of assembler data, padding at the end
                   1168:    with zeros if necessary.  SIZE must always be specified.
                   1169: 
                   1170:    SIZE is important for structure constructors,
                   1171:    since trailing members may have been omitted from the constructor.
                   1172:    It is also important for initialization of arrays from string constants
                   1173:    since the full length of the string constant might not be wanted.
                   1174:    It is also needed for initialization of unions, where the initializer's
                   1175:    type is just one member, and that may not be as long as the union.
                   1176: 
                   1177:    There a case in which we would fail to output exactly SIZE bytes:
                   1178:    for a structure constructor that wants to produce more than SIZE bytes.
                   1179:    But such constructors will never be generated for any possible input.  */
                   1180: 
                   1181: void
                   1182: output_constant (exp, size)
                   1183:      register tree exp;
                   1184:      register int size;
                   1185: {
                   1186:   register enum tree_code code = TREE_CODE (TREE_TYPE (exp));
                   1187:   rtx x;
                   1188: 
                   1189:   if (size == 0)
                   1190:     return;
                   1191: 
                   1192:   switch (code)
                   1193:     {
                   1194:     case INTEGER_TYPE:
                   1195:     case ENUMERAL_TYPE:
                   1196:     case POINTER_TYPE:
                   1197:       x = expand_expr (exp, 0, VOIDmode, EXPAND_SUM);
                   1198: 
                   1199:       if (size == 1)
                   1200:        {
                   1201:          ASM_OUTPUT_CHAR (asm_out_file, x);
                   1202:          size -= 1;
                   1203:        }
                   1204:       else if (size == 2)
                   1205:        {
                   1206:          ASM_OUTPUT_SHORT (asm_out_file, x);
                   1207:          size -= 2;
                   1208:        }
                   1209:       else if (size == 4)
                   1210:        {
                   1211:          ASM_OUTPUT_INT (asm_out_file, x);
                   1212:          size -= 4;
                   1213:        }
                   1214:       else
                   1215:        abort ();
                   1216: 
                   1217:       break;
                   1218: 
                   1219:     case REAL_TYPE:
                   1220:       if (TREE_CODE (exp) != REAL_CST)
                   1221:        error ("initializer for floating value is not a floating constant");
                   1222: 
                   1223:       if (size < 4)
                   1224:        break;
                   1225:       else if (size < 8)
                   1226:        {
                   1227:          ASM_OUTPUT_FLOAT (asm_out_file, TREE_REAL_CST (exp));
                   1228:          size -= 4;
                   1229:        }
                   1230:       else
                   1231:        {
                   1232:          ASM_OUTPUT_DOUBLE (asm_out_file, TREE_REAL_CST (exp));
                   1233:          size -= 8;
                   1234:        }
                   1235:       break;
                   1236: 
                   1237:     case COMPLEX_TYPE:
                   1238:       output_constant (TREE_REALPART (exp), size / 2);
                   1239:       output_constant (TREE_IMAGPART (exp), size / 2);
                   1240:       size -= (size / 2) * 2;
                   1241:       break;
                   1242: 
                   1243:     case ARRAY_TYPE:
                   1244:       if (TREE_CODE (exp) == CONSTRUCTOR)
                   1245:        {
                   1246:          output_constructor (exp, size);
                   1247:          return;
                   1248:        }
                   1249:       else if (TREE_CODE (exp) == STRING_CST)
                   1250:        {
                   1251:          register int i;
                   1252:          register unsigned char *p
                   1253:            = (unsigned char *) TREE_STRING_POINTER (exp);
                   1254:          int excess = 0;
                   1255: 
                   1256:          if (size > TREE_STRING_LENGTH (exp))
                   1257:            {
                   1258:              excess = size - TREE_STRING_LENGTH (exp);
                   1259:              size = TREE_STRING_LENGTH (exp);
                   1260:            }
                   1261: 
                   1262: #ifdef ASM_OUTPUT_ASCII
                   1263:          ASM_OUTPUT_ASCII (asm_out_file, p, size);
                   1264: #else
                   1265:          fprintf (asm_out_file, "\t.ascii \"");
                   1266: 
                   1267:          for (i = 0; i < size; i++)
                   1268:            {
                   1269:              register int c = p[i];
                   1270:              if (c == '\"' || c == '\\')
                   1271:                putc ('\\', asm_out_file);
                   1272:              if (c >= ' ' && c < 0177)
                   1273:                putc (c, asm_out_file);
                   1274:              else
                   1275:                {
                   1276:                  fprintf (asm_out_file, "\\%o", c);
                   1277:                  /* After an octal-escape, if a digit follows,
                   1278:                     terminate one string constant and start another.
                   1279:                     The Vax assembler fails to stop reading the escape
                   1280:                     after three digits, so this is the only way we
                   1281:                     can get it to parse the data properly.  */
                   1282:                  if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
                   1283:                    fprintf (asm_out_file, "\"\n\t.ascii \"");
                   1284:                }
                   1285:            }
                   1286:          fprintf (asm_out_file, "\"\n");
                   1287: #endif /* no ASM_OUTPUT_ASCII */
                   1288: 
                   1289:          size = excess;
                   1290:        }
                   1291:       else
                   1292:        abort ();
                   1293:       break;
                   1294: 
                   1295:     case RECORD_TYPE:
                   1296:     case UNION_TYPE:
                   1297:       if (TREE_CODE (exp) == CONSTRUCTOR)
                   1298:        output_constructor (exp, size);
                   1299:       else
                   1300:        abort ();
                   1301:       return;
                   1302:     }
                   1303: 
                   1304:   if (size > 0)
                   1305:     ASM_OUTPUT_SKIP (asm_out_file, size);
                   1306: }
                   1307: 
                   1308: /* Subroutine of output_constant, used for CONSTRUCTORs
                   1309:    (aggregate constants).
                   1310:    Generate at least SIZE bytes, padding if necessary.  */
                   1311: 
                   1312: void
                   1313: output_constructor (exp, size)
                   1314:      tree exp;
                   1315:      int size;
                   1316: {
                   1317:   register tree link, field = 0;
                   1318:   register int byte;
                   1319:   int total_bytes = 0;
                   1320:   int byte_offset = -1;
                   1321: 
                   1322:   if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
                   1323:       || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)
                   1324:     field = TYPE_FIELDS (TREE_TYPE (exp));
                   1325: 
                   1326:   /* As LINK goes through the elements of the constant,
                   1327:      FIELD goes through the structure fields, if the constant is a structure.
                   1328:      But the constant could also be an array.  Then FIELD is zero.  */
                   1329:   for (link = CONSTRUCTOR_ELTS (exp);
                   1330:        link;
                   1331:        link = TREE_CHAIN (link),
                   1332:        field = field ? TREE_CHAIN (field) : 0)
                   1333:     {
                   1334:       if (field == 0
                   1335:          || (DECL_MODE (field) != BImode))
                   1336:        {
                   1337:          register int fieldsize;
                   1338: 
                   1339:          /* An element that is not a bit-field.
                   1340:             Output any buffered-up bit-fields preceding it.  */
                   1341:          if (byte_offset >= 0)
                   1342:            {
                   1343:              ASM_OUTPUT_BYTE (asm_out_file, byte);
                   1344:              total_bytes++;
                   1345:              byte_offset = -1;
                   1346:            }
                   1347: 
                   1348:          /* Align to this element's alignment,
                   1349:             if it isn't aligned properly by its predecessors.  */
                   1350:          if (field && (total_bytes * BITS_PER_UNIT) % DECL_ALIGN (field) != 0)
                   1351:            {
                   1352:              int byte_align = DECL_ALIGN (field) / BITS_PER_UNIT;
                   1353:              int to_byte = (((total_bytes + byte_align - 1) / byte_align)
                   1354:                             * byte_align);
                   1355:              ASM_OUTPUT_SKIP (asm_out_file, to_byte - total_bytes);
                   1356:              total_bytes = to_byte;
                   1357:            }
                   1358: 
                   1359:          /* Output the element's initial value.  */
                   1360:          if (field)
                   1361:            {
                   1362:              if (! TREE_LITERAL (DECL_SIZE (field)))
                   1363:                abort ();
                   1364:              fieldsize = TREE_INT_CST_LOW (DECL_SIZE (field))
                   1365:                * DECL_SIZE_UNIT (field);
                   1366:              fieldsize = (fieldsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
                   1367:            }
                   1368:          else
                   1369:            fieldsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
                   1370: 
                   1371:          output_constant (TREE_VALUE (link), fieldsize);
                   1372: 
                   1373:          /* Count its size.  */
                   1374:          total_bytes += fieldsize;
                   1375:        }
                   1376:       else if (TREE_CODE (TREE_VALUE (link)) != INTEGER_CST)
                   1377:        error ("invalid initial value for member `%s'",
                   1378:               IDENTIFIER_POINTER (DECL_NAME (field)));
                   1379:       else
                   1380:        {
                   1381:          /* Element that is a bit-field.  */
                   1382: 
                   1383:          int next_offset = DECL_OFFSET (field);
                   1384:          int end_offset
                   1385:            = (next_offset
                   1386:               + (TREE_INT_CST_LOW (DECL_SIZE (field))
                   1387:                  * DECL_SIZE_UNIT (field)));
                   1388: 
                   1389:          /* We must split the element into pieces that fall within
                   1390:             separate bytes, and combine each byte with previous or
                   1391:             following bit-fields.  */
                   1392: 
                   1393:          /* next_offset is the offset n fbits from the begining of
                   1394:             the structure to the next bit of this element to be processed.
                   1395:             end_offset is the offset of the first bit past the end of
                   1396:             this element.  */
                   1397:          while (next_offset < end_offset)
                   1398:            {
                   1399:              int this_time;
                   1400:              int next_byte = next_offset / BITS_PER_UNIT;
                   1401:              int next_bit = next_offset % BITS_PER_UNIT;
                   1402:              if (byte_offset < 0)
                   1403:                {
                   1404:                  byte_offset = next_byte;
                   1405:                  byte = 0;
                   1406:                }
                   1407:              else
                   1408:                while (next_byte != byte_offset)
                   1409:                  {
                   1410:                    ASM_OUTPUT_BYTE (asm_out_file, byte);
                   1411:                    byte_offset++;
                   1412:                    total_bytes++;
                   1413:                    byte = 0;
                   1414:                  }
                   1415:              /* Number of bits we can process at once
                   1416:                 (all part of the same byte).  */
                   1417:              this_time = MIN (end_offset - next_offset,
                   1418:                               BITS_PER_UNIT - next_bit);
                   1419: #ifdef BYTES_BIG_ENDIAN
                   1420:              /* On big-endian machine, take the most significant bits
                   1421:                 first (of the bits that are significant)
                   1422:                 and put them into bytes from the most significant end.  */
                   1423:              byte |= (((TREE_INT_CST_LOW (TREE_VALUE (link))
                   1424:                         >> (end_offset - next_offset - this_time))
                   1425:                        & ((1 << this_time) - 1))
                   1426:                       << (BITS_PER_UNIT - this_time - next_bit));
                   1427: #else
                   1428:              /* On little-endian machines,
                   1429:                 take first the least significant bits of the value
                   1430:                 and pack them starting at the least significant
                   1431:                 bits of the bytes.  */
                   1432:              byte |= ((TREE_INT_CST_LOW (TREE_VALUE (link))
                   1433:                        >> (next_offset - DECL_OFFSET (field)))
                   1434:                       & ((1 << this_time) - 1)) << next_bit;
                   1435: #endif
                   1436:              next_offset += this_time;
                   1437:            }
                   1438:        }
                   1439:     }
                   1440:   if (byte_offset >= 0)
                   1441:     {
                   1442:       ASM_OUTPUT_BYTE (asm_out_file, byte);
                   1443:       byte_offset = -1;
                   1444:       total_bytes++;
                   1445:     }
                   1446:   if (total_bytes < size)
                   1447:     ASM_OUTPUT_SKIP (asm_out_file, size - total_bytes);
                   1448: }

unix.superglobalmegacorp.com

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