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