|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.