00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "config.h"
00035 #include "system.h"
00036 #include "coretypes.h"
00037 #include "tm.h"
00038 #include "rtl.h"
00039 #include "tree.h"
00040 #include "flags.h"
00041 #include "function.h"
00042 #include "expr.h"
00043 #include "hard-reg-set.h"
00044 #include "regs.h"
00045 #include "real.h"
00046 #include "output.h"
00047 #include "toplev.h"
00048 #include "hashtab.h"
00049 #include "c-pragma.h"
00050 #include "ggc.h"
00051 #include "langhooks.h"
00052 #include "tm_p.h"
00053 #include "debug.h"
00054 #include "target.h"
00055 #include "tree-mudflap.h"
00056 #include "cgraph.h"
00057 #include "cfglayout.h"
00058 #include "basic-block.h"
00059
00060 #ifdef XCOFF_DEBUGGING_INFO
00061 #include "xcoffout.h"
00062
00063 #endif
00064
00065 #ifdef KEY
00066 #include "gspin-gcc-interface.h"
00067 #include "diagnostic.h"
00068 extern void gspin_gxx_emits_decl (tree);
00069 extern void gspin_gxx_emits_asm (char *);
00070
00071 extern int flag_spin_file;
00072 #endif
00073
00074
00075 extern GTY(()) const char *first_global_object_name;
00076 extern GTY(()) const char *weak_global_object_name;
00077
00078 const char *first_global_object_name;
00079 const char *weak_global_object_name;
00080
00081 struct addr_const;
00082 struct constant_descriptor_rtx;
00083 struct rtx_constant_pool;
00084
00085 struct varasm_status GTY(())
00086 {
00087
00088 struct rtx_constant_pool *pool;
00089
00090
00091
00092 unsigned int deferred_constants;
00093 };
00094
00095 #define n_deferred_constants (cfun->varasm->deferred_constants)
00096
00097
00098
00099
00100 static GTY(()) int const_labelno;
00101
00102
00103
00104
00105 int size_directive_output;
00106
00107
00108
00109
00110
00111
00112 tree last_assemble_variable_decl;
00113
00114
00115
00116
00117 bool first_function_block_is_cold;
00118
00119
00120
00121
00122 static HOST_WIDE_INT const_alias_set;
00123
00124 static const char *strip_reg_name (const char *);
00125 static int contains_pointers_p (tree);
00126 #ifdef ASM_OUTPUT_EXTERNAL
00127 static bool incorporeal_function_p (tree);
00128 #endif
00129 static void decode_addr_const (tree, struct addr_const *);
00130 static hashval_t const_desc_hash (const void *);
00131 static int const_desc_eq (const void *, const void *);
00132 static hashval_t const_hash_1 (const tree);
00133 static int compare_constant (const tree, const tree);
00134 static tree copy_constant (tree);
00135 static void output_constant_def_contents (rtx);
00136 static void output_addressed_constants (tree);
00137 static unsigned HOST_WIDE_INT array_size_for_constructor (tree);
00138 static unsigned min_align (unsigned, unsigned);
00139 static void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int);
00140 static void globalize_decl (tree);
00141 static void maybe_assemble_visibility (tree);
00142 #ifdef BSS_SECTION_ASM_OP
00143 #ifdef ASM_OUTPUT_BSS
00144 static void asm_output_bss (FILE *, tree, const char *,
00145 unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT);
00146 #endif
00147 #ifdef ASM_OUTPUT_ALIGNED_BSS
00148 static void asm_output_aligned_bss (FILE *, tree, const char *,
00149 unsigned HOST_WIDE_INT, int)
00150 ATTRIBUTE_UNUSED;
00151 #endif
00152 #endif
00153 static void mark_weak (tree);
00154 static void output_constant_pool (const char *, tree);
00155
00156
00157 section *text_section;
00158 section *data_section;
00159 section *readonly_data_section;
00160 section *sdata_section;
00161 section *ctors_section;
00162 section *dtors_section;
00163 section *bss_section;
00164 section *sbss_section;
00165
00166
00167 section *tls_comm_section;
00168 section *comm_section;
00169 section *lcomm_section;
00170
00171
00172
00173 section *bss_noswitch_section;
00174
00175
00176
00177
00178 section *exception_section;
00179
00180
00181
00182
00183 section *eh_frame_section;
00184
00185
00186
00187 section *in_section;
00188
00189
00190
00191 bool in_cold_section_p;
00192
00193
00194 static GTY(()) section *unnamed_sections;
00195
00196
00197 #ifndef IN_NAMED_SECTION
00198 #define IN_NAMED_SECTION(DECL) \
00199 ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
00200 && DECL_SECTION_NAME (DECL) != NULL_TREE)
00201 #endif
00202
00203
00204 static GTY((param_is (section))) htab_t section_htab;
00205
00206
00207 static GTY((param_is (struct object_block))) htab_t object_block_htab;
00208
00209
00210 static GTY(()) int anchor_labelno;
00211
00212
00213 static GTY(()) struct rtx_constant_pool *shared_constant_pool;
00214
00215
00216
00217 static int
00218 section_entry_eq (const void *p1, const void *p2)
00219 {
00220 const section *old = p1;
00221 const char *new = p2;
00222
00223 return strcmp (old->named.name, new) == 0;
00224 }
00225
00226 static hashval_t
00227 section_entry_hash (const void *p)
00228 {
00229 const section *old = p;
00230 return htab_hash_string (old->named.name);
00231 }
00232
00233
00234
00235 static hashval_t
00236 hash_section (section *sect)
00237 {
00238 if (sect->common.flags & SECTION_NAMED)
00239 return htab_hash_string (sect->named.name);
00240 return sect->common.flags;
00241 }
00242
00243
00244
00245 static int
00246 object_block_entry_eq (const void *p1, const void *p2)
00247 {
00248 const struct object_block *old = p1;
00249 const section *new = p2;
00250
00251 return old->sect == new;
00252 }
00253
00254 static hashval_t
00255 object_block_entry_hash (const void *p)
00256 {
00257 const struct object_block *old = p;
00258 return hash_section (old->sect);
00259 }
00260
00261
00262
00263 section *
00264 get_unnamed_section (unsigned int flags, void (*callback) (const void *),
00265 const void *data)
00266 {
00267 section *sect;
00268
00269 sect = ggc_alloc (sizeof (struct unnamed_section));
00270 sect->unnamed.common.flags = flags | SECTION_UNNAMED;
00271 sect->unnamed.callback = callback;
00272 sect->unnamed.data = data;
00273 sect->unnamed.next = unnamed_sections;
00274
00275 unnamed_sections = sect;
00276 return sect;
00277 }
00278
00279
00280
00281 static section *
00282 get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
00283 {
00284 section *sect;
00285
00286 sect = ggc_alloc (sizeof (struct unnamed_section));
00287 sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
00288 sect->noswitch.callback = callback;
00289
00290 return sect;
00291 }
00292
00293
00294
00295
00296 section *
00297 get_section (const char *name, unsigned int flags, tree decl)
00298 {
00299 section *sect, **slot;
00300
00301 slot = (section **)
00302 htab_find_slot_with_hash (section_htab, name,
00303 htab_hash_string (name), INSERT);
00304 flags |= SECTION_NAMED;
00305 if (*slot == NULL)
00306 {
00307 sect = ggc_alloc (sizeof (struct named_section));
00308 sect->named.common.flags = flags;
00309 sect->named.name = ggc_strdup (name);
00310 sect->named.decl = decl;
00311 *slot = sect;
00312 }
00313 else
00314 {
00315 sect = *slot;
00316 if ((sect->common.flags & ~SECTION_DECLARED) != flags
00317 && ((sect->common.flags | flags) & SECTION_OVERRIDE) == 0)
00318 {
00319
00320 if (decl == 0)
00321 decl = sect->named.decl;
00322 gcc_assert (decl);
00323 error ("%+D causes a section type conflict", decl);
00324 }
00325 }
00326 return sect;
00327 }
00328
00329
00330
00331
00332 static bool
00333 use_object_blocks_p (void)
00334 {
00335 return flag_section_anchors;
00336 }
00337
00338
00339
00340
00341
00342 static struct object_block *
00343 get_block_for_section (section *sect)
00344 {
00345 struct object_block *block;
00346 void **slot;
00347
00348 if (sect == NULL)
00349 return NULL;
00350
00351 slot = htab_find_slot_with_hash (object_block_htab, sect,
00352 hash_section (sect), INSERT);
00353 block = (struct object_block *) *slot;
00354 if (block == NULL)
00355 {
00356 block = (struct object_block *)
00357 ggc_alloc_cleared (sizeof (struct object_block));
00358 block->sect = sect;
00359 *slot = block;
00360 }
00361 return block;
00362 }
00363
00364
00365
00366
00367
00368 static rtx
00369 create_block_symbol (const char *label, struct object_block *block,
00370 HOST_WIDE_INT offset)
00371 {
00372 rtx symbol;
00373 unsigned int size;
00374
00375
00376 size = RTX_HDR_SIZE + sizeof (struct block_symbol);
00377 symbol = ggc_alloc_zone (size, &rtl_zone);
00378
00379
00380 memset (symbol, 0, size);
00381 PUT_CODE (symbol, SYMBOL_REF);
00382 PUT_MODE (symbol, Pmode);
00383 XSTR (symbol, 0) = label;
00384 SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_HAS_BLOCK_INFO;
00385
00386
00387 SYMBOL_REF_BLOCK (symbol) = block;
00388 SYMBOL_REF_BLOCK_OFFSET (symbol) = offset;
00389
00390 return symbol;
00391 }
00392
00393 static void
00394 initialize_cold_section_name (void)
00395 {
00396 const char *stripped_name;
00397 char *name, *buffer;
00398 tree dsn;
00399
00400 gcc_assert (cfun && current_function_decl);
00401 if (cfun->unlikely_text_section_name)
00402 return;
00403
00404 dsn = DECL_SECTION_NAME (current_function_decl);
00405 if (flag_function_sections && dsn)
00406 {
00407 name = alloca (TREE_STRING_LENGTH (dsn) + 1);
00408 memcpy (name, TREE_STRING_POINTER (dsn), TREE_STRING_LENGTH (dsn) + 1);
00409
00410 stripped_name = targetm.strip_name_encoding (name);
00411
00412 buffer = ACONCAT ((stripped_name, "_unlikely", NULL));
00413 cfun->unlikely_text_section_name = ggc_strdup (buffer);
00414 }
00415 else
00416 cfun->unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
00417 }
00418
00419
00420
00421 section *
00422 unlikely_text_section (void)
00423 {
00424 if (cfun)
00425 {
00426 if (!cfun->unlikely_text_section_name)
00427 initialize_cold_section_name ();
00428
00429 return get_named_section (NULL, cfun->unlikely_text_section_name, 0);
00430 }
00431 else
00432 return get_named_section (NULL, UNLIKELY_EXECUTED_TEXT_SECTION_NAME, 0);
00433 }
00434
00435
00436
00437
00438
00439
00440 bool
00441 unlikely_text_section_p (section *sect)
00442 {
00443 const char *name;
00444
00445 if (cfun)
00446 name = cfun->unlikely_text_section_name;
00447 else
00448 name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
00449
00450 return (name
00451 && sect
00452 && SECTION_STYLE (sect) == SECTION_NAMED
00453 && strcmp (name, sect->named.name) == 0);
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463 section *
00464 get_named_section (tree decl, const char *name, int reloc)
00465 {
00466 unsigned int flags;
00467
00468 gcc_assert (!decl || DECL_P (decl));
00469 if (name == NULL)
00470 name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
00471
00472 flags = targetm.section_type_flags (decl, name, reloc);
00473
00474 return get_section (name, flags, decl);
00475 }
00476
00477
00478
00479 void
00480 resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
00481 int flag_function_or_data_sections)
00482 {
00483 if (DECL_SECTION_NAME (decl) == NULL_TREE
00484 && targetm.have_named_sections
00485 && (flag_function_or_data_sections
00486 || DECL_ONE_ONLY (decl)))
00487 targetm.asm_out.unique_section (decl, reloc);
00488 }
00489
00490 #ifdef BSS_SECTION_ASM_OP
00491
00492 #ifdef ASM_OUTPUT_BSS
00493
00494
00495
00496
00497
00498
00499 static void
00500 asm_output_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
00501 const char *name,
00502 unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
00503 unsigned HOST_WIDE_INT rounded)
00504 {
00505 targetm.asm_out.globalize_label (file, name);
00506 switch_to_section (bss_section);
00507 #ifdef ASM_DECLARE_OBJECT_NAME
00508 last_assemble_variable_decl = decl;
00509 ASM_DECLARE_OBJECT_NAME (file, name, decl);
00510 #ifdef KEY
00511 if (flag_spin_file) {
00512 We do not reach here, this comment intentionally does not have the
00513 comment sign.
00514
00515 gs_bv(cp_decl_flags, GS_DECL_EMITTED_BY_GXX, 1);
00516 gspin_gxx_emits_decl (decl);
00517 }
00518 #endif
00519 #else
00520
00521 ASM_OUTPUT_LABEL (file, name);
00522 #endif
00523 ASM_OUTPUT_SKIP (file, rounded ? rounded : 1);
00524 }
00525
00526 #endif
00527
00528 #ifdef ASM_OUTPUT_ALIGNED_BSS
00529
00530
00531
00532
00533
00534
00535 static void
00536 asm_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
00537 const char *name, unsigned HOST_WIDE_INT size,
00538 int align)
00539 {
00540 switch_to_section (bss_section);
00541 ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
00542 #ifdef ASM_DECLARE_OBJECT_NAME
00543 last_assemble_variable_decl = decl;
00544 ASM_DECLARE_OBJECT_NAME (file, name, decl);
00545 #ifdef KEY
00546 if (flag_spin_file) {
00547 DECL_EMITTED_BY_GXX(decl) = 1;
00548 gspin_gxx_emits_decl (decl);
00549 }
00550 #endif
00551 #else
00552
00553 ASM_OUTPUT_LABEL (file, name);
00554 #endif
00555 ASM_OUTPUT_SKIP (file, size ? size : 1);
00556 }
00557
00558 #endif
00559
00560 #endif
00561
00562 #ifndef USE_SELECT_SECTION_FOR_FUNCTIONS
00563
00564
00565
00566 static section *
00567 hot_function_section (tree decl)
00568 {
00569 if (decl != NULL_TREE
00570 && DECL_SECTION_NAME (decl) != NULL_TREE
00571 && targetm.have_named_sections)
00572 return get_named_section (decl, NULL, 0);
00573 else
00574 return text_section;
00575 }
00576 #endif
00577
00578
00579
00580
00581
00582
00583 section *
00584 function_section (tree decl)
00585 {
00586 int reloc = 0;
00587
00588 if (first_function_block_is_cold)
00589 reloc = 1;
00590
00591 #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
00592 if (decl != NULL_TREE
00593 && DECL_SECTION_NAME (decl) != NULL_TREE)
00594 return reloc ? unlikely_text_section ()
00595 : get_named_section (decl, NULL, 0);
00596 else
00597 return targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));
00598 #else
00599 return reloc ? unlikely_text_section () : hot_function_section (decl);
00600 #endif
00601 }
00602
00603 section *
00604 current_function_section (void)
00605 {
00606 #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
00607 if (current_function_decl != NULL_TREE
00608 && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
00609 return in_cold_section_p ? unlikely_text_section ()
00610 : get_named_section (current_function_decl,
00611 NULL, 0);
00612 else
00613 return targetm.asm_out.select_section (current_function_decl,
00614 in_cold_section_p,
00615 DECL_ALIGN (current_function_decl));
00616 #else
00617 return (in_cold_section_p
00618 ? unlikely_text_section ()
00619 : hot_function_section (current_function_decl));
00620 #endif
00621 }
00622
00623
00624
00625 section *
00626 default_function_rodata_section (tree decl)
00627 {
00628 if (decl != NULL_TREE && DECL_SECTION_NAME (decl))
00629 {
00630 const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
00631
00632 if (DECL_ONE_ONLY (decl) && HAVE_COMDAT_GROUP)
00633 {
00634 size_t len = strlen (name) + 3;
00635 char* rname = alloca (len);
00636
00637 strcpy (rname, ".rodata");
00638 strcat (rname, name + 5);
00639 return get_section (rname, SECTION_LINKONCE, decl);
00640 }
00641
00642 else if (DECL_ONE_ONLY (decl)
00643 && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
00644 {
00645 size_t len = strlen (name) + 1;
00646 char *rname = alloca (len);
00647
00648 memcpy (rname, name, len);
00649 rname[14] = 'r';
00650 return get_section (rname, SECTION_LINKONCE, decl);
00651 }
00652
00653 else if (flag_function_sections && flag_data_sections
00654 && strncmp (name, ".text.", 6) == 0)
00655 {
00656 size_t len = strlen (name) + 1;
00657 char *rname = alloca (len + 2);
00658
00659 memcpy (rname, ".rodata", 7);
00660 memcpy (rname + 7, name + 5, len - 5);
00661 return get_section (rname, 0, decl);
00662 }
00663 }
00664
00665 return readonly_data_section;
00666 }
00667
00668
00669
00670
00671
00672 section *
00673 default_no_function_rodata_section (tree decl ATTRIBUTE_UNUSED)
00674 {
00675 return readonly_data_section;
00676 }
00677
00678
00679
00680 static section *
00681 mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
00682 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
00683 unsigned int flags ATTRIBUTE_UNUSED)
00684 {
00685 HOST_WIDE_INT len;
00686
00687 if (HAVE_GAS_SHF_MERGE && flag_merge_constants
00688 && TREE_CODE (decl) == STRING_CST
00689 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
00690 && align <= 256
00691 && (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
00692 && TREE_STRING_LENGTH (decl) >= len)
00693 {
00694 enum machine_mode mode;
00695 unsigned int modesize;
00696 const char *str;
00697 HOST_WIDE_INT i;
00698 int j, unit;
00699 char name[30];
00700
00701 mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (decl)));
00702 modesize = GET_MODE_BITSIZE (mode);
00703 if (modesize >= 8 && modesize <= 256
00704 && (modesize & (modesize - 1)) == 0)
00705 {
00706 if (align < modesize)
00707 align = modesize;
00708
00709 str = TREE_STRING_POINTER (decl);
00710 unit = GET_MODE_SIZE (mode);
00711
00712
00713 for (i = 0; i < len; i += unit)
00714 {
00715 for (j = 0; j < unit; j++)
00716 if (str[i + j] != '\0')
00717 break;
00718 if (j == unit)
00719 break;
00720 }
00721 if (i == len - unit)
00722 {
00723 sprintf (name, ".rodata.str%d.%d", modesize / 8,
00724 (int) (align / 8));
00725 flags |= (modesize / 8) | SECTION_MERGE | SECTION_STRINGS;
00726 return get_section (name, flags, NULL);
00727 }
00728 }
00729 }
00730
00731 return readonly_data_section;
00732 }
00733
00734
00735
00736 section *
00737 mergeable_constant_section (enum machine_mode mode ATTRIBUTE_UNUSED,
00738 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
00739 unsigned int flags ATTRIBUTE_UNUSED)
00740 {
00741 unsigned int modesize = GET_MODE_BITSIZE (mode);
00742
00743 if (HAVE_GAS_SHF_MERGE && flag_merge_constants
00744 && mode != VOIDmode
00745 && mode != BLKmode
00746 && modesize <= align
00747 && align >= 8
00748 && align <= 256
00749 && (align & (align - 1)) == 0)
00750 {
00751 char name[24];
00752
00753 sprintf (name, ".rodata.cst%d", (int) (align / 8));
00754 flags |= (align / 8) | SECTION_MERGE;
00755 return get_section (name, flags, NULL);
00756 }
00757 return readonly_data_section;
00758 }
00759
00760
00761
00762 static const char *
00763 strip_reg_name (const char *name)
00764 {
00765 #ifdef REGISTER_PREFIX
00766 if (!strncmp (name, REGISTER_PREFIX, strlen (REGISTER_PREFIX)))
00767 name += strlen (REGISTER_PREFIX);
00768 #endif
00769 if (name[0] == '%' || name[0] == '#')
00770 name++;
00771 return name;
00772 }
00773
00774
00775
00776
00777 void
00778 set_user_assembler_name (tree decl, const char *name)
00779 {
00780 char *starred = alloca (strlen (name) + 2);
00781 starred[0] = '*';
00782 strcpy (starred + 1, name);
00783 change_decl_assembler_name (decl, get_identifier (starred));
00784 SET_DECL_RTL (decl, NULL_RTX);
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 int
00796 decode_reg_name (const char *asmspec)
00797 {
00798 if (asmspec != 0)
00799 {
00800 int i;
00801
00802
00803 asmspec = strip_reg_name (asmspec);
00804
00805
00806 for (i = strlen (asmspec) - 1; i >= 0; i--)
00807 if (! ISDIGIT (asmspec[i]))
00808 break;
00809 if (asmspec[0] != 0 && i < 0)
00810 {
00811 i = atoi (asmspec);
00812 if (i < FIRST_PSEUDO_REGISTER && i >= 0)
00813 return i;
00814 else
00815 return -2;
00816 }
00817
00818 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00819 if (reg_names[i][0]
00820 && ! strcmp (asmspec, strip_reg_name (reg_names[i])))
00821 return i;
00822
00823 #ifdef ADDITIONAL_REGISTER_NAMES
00824 {
00825 static const struct { const char *const name; const int number; } table[]
00826 = ADDITIONAL_REGISTER_NAMES;
00827
00828 for (i = 0; i < (int) ARRAY_SIZE (table); i++)
00829 if (table[i].name[0]
00830 && ! strcmp (asmspec, table[i].name))
00831 return table[i].number;
00832 }
00833 #endif
00834
00835 if (!strcmp (asmspec, "memory"))
00836 return -4;
00837
00838 if (!strcmp (asmspec, "cc"))
00839 return -3;
00840
00841 return -2;
00842 }
00843
00844 return -1;
00845 }
00846
00847
00848
00849 static bool
00850 bss_initializer_p (tree decl)
00851 {
00852 return (DECL_INITIAL (decl) == NULL
00853 || DECL_INITIAL (decl) == error_mark_node
00854 || (flag_zero_initialized_in_bss
00855
00856
00857 && !TREE_READONLY (decl)
00858 && initializer_zerop (DECL_INITIAL (decl))));
00859 }
00860
00861
00862
00863
00864 void
00865 align_variable (tree decl, bool dont_output_data)
00866 {
00867 unsigned int align = DECL_ALIGN (decl);
00868
00869
00870
00871
00872 if (dont_output_data && DECL_SIZE (decl) == 0
00873 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
00874 align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
00875
00876
00877
00878 if (align > MAX_OFILE_ALIGNMENT)
00879 {
00880 warning (0, "alignment of %q+D is greater than maximum object "
00881 "file alignment. Using %d", decl,
00882 MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
00883 align = MAX_OFILE_ALIGNMENT;
00884 }
00885
00886
00887 if (! DECL_USER_ALIGN (decl))
00888 {
00889 #ifdef DATA_ALIGNMENT
00890 align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
00891 #endif
00892 #ifdef CONSTANT_ALIGNMENT
00893 if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
00894 align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
00895 #endif
00896 }
00897
00898
00899
00900 DECL_ALIGN (decl) = align;
00901 }
00902
00903
00904
00905
00906
00907 static section *
00908 get_variable_section (tree decl, bool prefer_noswitch_p)
00909 {
00910 int reloc;
00911
00912
00913
00914 if (DECL_COMMON (decl) && DECL_SECTION_NAME (decl) == NULL)
00915 {
00916 if (DECL_THREAD_LOCAL_P (decl))
00917 return tls_comm_section;
00918 if (TREE_PUBLIC (decl) && bss_initializer_p (decl))
00919 return comm_section;
00920 }
00921
00922 if (DECL_INITIAL (decl) == error_mark_node)
00923 reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
00924 else if (DECL_INITIAL (decl))
00925 reloc = compute_reloc_for_constant (DECL_INITIAL (decl));
00926 else
00927 reloc = 0;
00928
00929 resolve_unique_section (decl, reloc, flag_data_sections);
00930 if (IN_NAMED_SECTION (decl))
00931 return get_named_section (decl, NULL, reloc);
00932
00933 if (!DECL_THREAD_LOCAL_P (decl)
00934 && !(prefer_noswitch_p && targetm.have_switchable_bss_sections)
00935 && bss_initializer_p (decl))
00936 {
00937 if (!TREE_PUBLIC (decl))
00938 return lcomm_section;
00939 if (bss_noswitch_section)
00940 return bss_noswitch_section;
00941 }
00942
00943 return targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));
00944 }
00945
00946
00947
00948 static struct object_block *
00949 get_block_for_decl (tree decl)
00950 {
00951 section *sect;
00952
00953 if (TREE_CODE (decl) == VAR_DECL)
00954 {
00955
00956 if (DECL_EXTERNAL (decl))
00957 return NULL;
00958
00959
00960
00961 if (DECL_ONE_ONLY (decl))
00962 return NULL;
00963 }
00964
00965
00966
00967 if (DECL_SIZE_UNIT (decl) == NULL)
00968 return NULL;
00969 if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
00970 return NULL;
00971
00972
00973
00974 if (TREE_CODE (decl) == VAR_DECL)
00975 align_variable (decl, 0);
00976 sect = get_variable_section (decl, true);
00977 if (SECTION_STYLE (sect) == SECTION_NOSWITCH)
00978 return NULL;
00979
00980 return get_block_for_section (sect);
00981 }
00982
00983
00984
00985 static void
00986 change_symbol_block (rtx symbol, struct object_block *block)
00987 {
00988 if (block != SYMBOL_REF_BLOCK (symbol))
00989 {
00990 gcc_assert (SYMBOL_REF_BLOCK_OFFSET (symbol) < 0);
00991 SYMBOL_REF_BLOCK (symbol) = block;
00992 }
00993 }
00994
00995
00996
00997 static bool
00998 use_blocks_for_decl_p (tree decl)
00999 {
01000
01001 if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != CONST_DECL)
01002 return false;
01003
01004
01005
01006
01007
01008 if (DECL_INITIAL (decl) == decl)
01009 return false;
01010
01011
01012 if (lookup_attribute ("alias", DECL_ATTRIBUTES (decl)))
01013 return false;
01014
01015 return true;
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027 void
01028 make_decl_rtl (tree decl)
01029 {
01030 const char *name = 0;
01031 int reg_number;
01032 rtx x;
01033
01034
01035 gcc_assert (TREE_CODE (decl) != PARM_DECL
01036 && TREE_CODE (decl) != RESULT_DECL);
01037
01038
01039 gcc_assert (TREE_CODE (decl) != VAR_DECL
01040 || TREE_STATIC (decl)
01041 || TREE_PUBLIC (decl)
01042 || DECL_EXTERNAL (decl)
01043 || DECL_REGISTER (decl));
01044
01045
01046 gcc_assert (TREE_CODE (decl) != TYPE_DECL
01047 && TREE_CODE (decl) != LABEL_DECL);
01048
01049
01050
01051 if (DECL_RTL_SET_P (decl))
01052 {
01053
01054 x = DECL_RTL (decl);
01055 if (GET_MODE (x) != DECL_MODE (decl))
01056 SET_DECL_RTL (decl, adjust_address_nv (x, DECL_MODE (decl), 0));
01057
01058 if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
01059 return;
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 targetm.encode_section_info (decl, DECL_RTL (decl), false);
01070
01071
01072
01073 if (MEM_P (x)
01074 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
01075 && SYMBOL_REF_HAS_BLOCK_INFO_P (XEXP (x, 0)))
01076 change_symbol_block (XEXP (x, 0), get_block_for_decl (decl));
01077
01078
01079 if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
01080 mudflap_enqueue_decl (decl);
01081
01082 return;
01083 }
01084
01085 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
01086
01087 if (name[0] != '*' && TREE_CODE (decl) != FUNCTION_DECL
01088 && DECL_REGISTER (decl))
01089 {
01090 error ("register name not specified for %q+D", decl);
01091 }
01092 else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
01093 {
01094 const char *asmspec = name+1;
01095 reg_number = decode_reg_name (asmspec);
01096
01097 if (reg_number == -1)
01098 error ("register name not specified for %q+D", decl);
01099 else if (reg_number < 0)
01100 error ("invalid register name for %q+D", decl);
01101 else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
01102 error ("data type of %q+D isn%'t suitable for a register",
01103 decl);
01104 else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl))))
01105 error ("register specified for %q+D isn%'t suitable for data type",
01106 decl);
01107
01108 else
01109 {
01110 int nregs;
01111
01112 if (DECL_INITIAL (decl) != 0 && TREE_STATIC (decl))
01113 {
01114 DECL_INITIAL (decl) = 0;
01115 error ("global register variable has initial value");
01116 }
01117 if (TREE_THIS_VOLATILE (decl))
01118 warning (OPT_Wvolatile_register_var,
01119 "optimization may eliminate reads and/or "
01120 "writes to register variables");
01121
01122
01123
01124
01125
01126
01127 SET_DECL_RTL (decl, gen_rtx_raw_REG (DECL_MODE (decl), reg_number));
01128 ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number;
01129 REG_USERVAR_P (DECL_RTL (decl)) = 1;
01130
01131 #ifdef KEY
01132 if (flag_spin_file)
01133 DECL_ASMREG(decl) = reg_number;
01134 #endif
01135
01136 if (TREE_STATIC (decl))
01137 {
01138
01139
01140 #ifdef ASM_DECLARE_REGISTER_GLOBAL
01141 name = IDENTIFIER_POINTER (DECL_NAME (decl));
01142 ASM_DECLARE_REGISTER_GLOBAL (asm_out_file, decl, reg_number, name);
01143 #endif
01144 nregs = hard_regno_nregs[reg_number][DECL_MODE (decl)];
01145 while (nregs > 0)
01146 globalize_reg (reg_number + --nregs);
01147 }
01148
01149
01150 return;
01151 }
01152 }
01153
01154
01155 else if (name[0] == '*')
01156 {
01157 #ifdef REGISTER_PREFIX
01158 if (strlen (REGISTER_PREFIX) != 0)
01159 {
01160 reg_number = decode_reg_name (name);
01161 if (reg_number >= 0 || reg_number == -3)
01162 error ("register name given for non-register variable %q+D", decl);
01163 }
01164 #endif
01165 }
01166
01167
01168
01169 if (TREE_CODE (decl) == VAR_DECL
01170 && DECL_SECTION_NAME (decl) != NULL_TREE
01171 && DECL_INITIAL (decl) == NULL_TREE
01172 && DECL_COMMON (decl))
01173 DECL_COMMON (decl) = 0;
01174
01175
01176 if (TREE_CODE (decl) == VAR_DECL && DECL_WEAK (decl))
01177 DECL_COMMON (decl) = 0;
01178
01179 if (use_object_blocks_p () && use_blocks_for_decl_p (decl))
01180 x = create_block_symbol (name, get_block_for_decl (decl), -1);
01181 else
01182 x = gen_rtx_SYMBOL_REF (Pmode, name);
01183 SYMBOL_REF_WEAK (x) = DECL_WEAK (decl);
01184 SET_SYMBOL_REF_DECL (x, decl);
01185
01186 x = gen_rtx_MEM (DECL_MODE (decl), x);
01187 if (TREE_CODE (decl) != FUNCTION_DECL)
01188 set_mem_attributes (x, decl, 1);
01189 SET_DECL_RTL (decl, x);
01190
01191
01192
01193
01194
01195 targetm.encode_section_info (decl, DECL_RTL (decl), true);
01196
01197
01198 if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
01199 mudflap_enqueue_decl (decl);
01200 }
01201
01202
01203
01204
01205 void
01206 assemble_asm (tree string)
01207 {
01208 app_enable ();
01209
01210 if (TREE_CODE (string) == ADDR_EXPR)
01211 string = TREE_OPERAND (string, 0);
01212
01213 #ifdef KEY
01214 if (flag_spin_file)
01215 gspin_gxx_emits_asm ((char *)TREE_STRING_POINTER (string));
01216 #endif
01217
01218 fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));
01219 }
01220
01221
01222
01223
01224
01225 void
01226 default_stabs_asm_out_destructor (rtx symbol ATTRIBUTE_UNUSED,
01227 int priority ATTRIBUTE_UNUSED)
01228 {
01229 #if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO
01230
01231
01232
01233 dbxout_begin_simple_stabs ("___DTOR_LIST__", 22 );
01234 dbxout_stab_value_label (XSTR (symbol, 0));
01235 #else
01236 sorry ("global destructors not supported on this target");
01237 #endif
01238 }
01239
01240 void
01241 default_named_section_asm_out_destructor (rtx symbol, int priority)
01242 {
01243 const char *section = ".dtors";
01244 char buf[16];
01245
01246
01247 if (priority != DEFAULT_INIT_PRIORITY)
01248 {
01249 sprintf (buf, ".dtors.%.5u",
01250
01251
01252
01253 MAX_INIT_PRIORITY - priority);
01254 section = buf;
01255 }
01256
01257 switch_to_section (get_section (section, SECTION_WRITE, NULL));
01258 assemble_align (POINTER_SIZE);
01259 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
01260 }
01261
01262 #ifdef DTORS_SECTION_ASM_OP
01263 void
01264 default_dtor_section_asm_out_destructor (rtx symbol,
01265 int priority ATTRIBUTE_UNUSED)
01266 {
01267 switch_to_section (dtors_section);
01268 assemble_align (POINTER_SIZE);
01269 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
01270 }
01271 #endif
01272
01273
01274
01275 void
01276 default_stabs_asm_out_constructor (rtx symbol ATTRIBUTE_UNUSED,
01277 int priority ATTRIBUTE_UNUSED)
01278 {
01279 #if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO
01280
01281
01282
01283 dbxout_begin_simple_stabs ("___CTOR_LIST__", 22 );
01284 dbxout_stab_value_label (XSTR (symbol, 0));
01285 #else
01286 sorry ("global constructors not supported on this target");
01287 #endif
01288 }
01289
01290 void
01291 default_named_section_asm_out_constructor (rtx symbol, int priority)
01292 {
01293 const char *section = ".ctors";
01294 char buf[16];
01295
01296
01297 if (priority != DEFAULT_INIT_PRIORITY)
01298 {
01299 sprintf (buf, ".ctors.%.5u",
01300
01301
01302
01303 MAX_INIT_PRIORITY - priority);
01304 section = buf;
01305 }
01306
01307 switch_to_section (get_section (section, SECTION_WRITE, NULL));
01308 assemble_align (POINTER_SIZE);
01309 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
01310 }
01311
01312 #ifdef CTORS_SECTION_ASM_OP
01313 void
01314 default_ctor_section_asm_out_constructor (rtx symbol,
01315 int priority ATTRIBUTE_UNUSED)
01316 {
01317 switch_to_section (ctors_section);
01318 assemble_align (POINTER_SIZE);
01319 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
01320 }
01321 #endif
01322
01323
01324
01325
01326
01327
01328
01329 #ifndef CONSTANT_POOL_BEFORE_FUNCTION
01330 #define CONSTANT_POOL_BEFORE_FUNCTION 1
01331 #endif
01332
01333
01334
01335
01336
01337 void
01338 notice_global_symbol (tree decl)
01339 {
01340 const char **type = &first_global_object_name;
01341
01342 if (first_global_object_name
01343 || !TREE_PUBLIC (decl)
01344 || DECL_EXTERNAL (decl)
01345 || !DECL_NAME (decl)
01346 || (TREE_CODE (decl) != FUNCTION_DECL
01347 && (TREE_CODE (decl) != VAR_DECL
01348 || (DECL_COMMON (decl)
01349 && (DECL_INITIAL (decl) == 0
01350 || DECL_INITIAL (decl) == error_mark_node))))
01351 || !MEM_P (DECL_RTL (decl)))
01352 return;
01353
01354
01355
01356 if (DECL_WEAK (decl) || DECL_ONE_ONLY (decl))
01357 type = &weak_global_object_name;
01358
01359 if (!*type)
01360 {
01361 const char *p;
01362 const char *name;
01363 rtx decl_rtl = DECL_RTL (decl);
01364
01365 p = targetm.strip_name_encoding (XSTR (XEXP (decl_rtl, 0), 0));
01366 name = ggc_strdup (p);
01367
01368 *type = name;
01369 }
01370 }
01371
01372
01373
01374
01375
01376
01377 void
01378 assemble_start_function (tree decl, const char *fnname)
01379 {
01380 int align;
01381 char tmp_label[100];
01382 bool hot_label_written = false;
01383
01384 cfun->unlikely_text_section_name = NULL;
01385
01386 first_function_block_is_cold = false;
01387 if (flag_reorder_blocks_and_partition)
01388 {
01389 ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTB", const_labelno);
01390 cfun->hot_section_label = ggc_strdup (tmp_label);
01391 ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDB", const_labelno);
01392 cfun->cold_section_label = ggc_strdup (tmp_label);
01393 ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTE", const_labelno);
01394 cfun->hot_section_end_label = ggc_strdup (tmp_label);
01395 ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDE", const_labelno);
01396 cfun->cold_section_end_label = ggc_strdup (tmp_label);
01397 const_labelno++;
01398 }
01399 else
01400 {
01401 cfun->hot_section_label = NULL;
01402 cfun->cold_section_label = NULL;
01403 cfun->hot_section_end_label = NULL;
01404 cfun->cold_section_end_label = NULL;
01405 }
01406
01407
01408
01409 app_disable ();
01410
01411 if (CONSTANT_POOL_BEFORE_FUNCTION)
01412 output_constant_pool (fnname, decl);
01413
01414 resolve_unique_section (decl, 0, flag_function_sections);
01415
01416
01417
01418
01419
01420
01421 if (flag_reorder_blocks_and_partition)
01422 {
01423 switch_to_section (unlikely_text_section ());
01424 assemble_align (FUNCTION_BOUNDARY);
01425 ASM_OUTPUT_LABEL (asm_out_file, cfun->cold_section_label);
01426
01427
01428
01429
01430 if (!current_function_is_thunk
01431 && BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION)
01432 {
01433 switch_to_section (text_section);
01434 assemble_align (FUNCTION_BOUNDARY);
01435 ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_label);
01436 hot_label_written = true;
01437 first_function_block_is_cold = true;
01438 }
01439 }
01440 else if (DECL_SECTION_NAME (decl))
01441 {
01442
01443
01444
01445
01446
01447 initialize_cold_section_name ();
01448
01449 if (cfun->unlikely_text_section_name
01450 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
01451 cfun->unlikely_text_section_name) == 0)
01452 first_function_block_is_cold = true;
01453 }
01454
01455 in_cold_section_p = first_function_block_is_cold;
01456
01457
01458
01459 switch_to_section (function_section (decl));
01460 if (flag_reorder_blocks_and_partition
01461 && !hot_label_written)
01462 ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_label);
01463
01464
01465 align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
01466 if (align < force_align_functions_log)
01467 align = force_align_functions_log;
01468 if (align > 0)
01469 {
01470 ASM_OUTPUT_ALIGN (asm_out_file, align);
01471 }
01472
01473
01474
01475
01476 if (align_functions_log > align
01477 && cfun->function_frequency != FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
01478 {
01479 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
01480 ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file,
01481 align_functions_log, align_functions - 1);
01482 #else
01483 ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log);
01484 #endif
01485 }
01486
01487 #ifdef ASM_OUTPUT_FUNCTION_PREFIX
01488 ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname);
01489 #endif
01490
01491 (*debug_hooks->begin_function) (decl);
01492
01493
01494
01495 if (TREE_PUBLIC (decl))
01496 {
01497 notice_global_symbol (decl);
01498
01499 globalize_decl (decl);
01500
01501 maybe_assemble_visibility (decl);
01502 }
01503
01504 if (DECL_PRESERVE_P (decl))
01505 targetm.asm_out.mark_decl_preserved (fnname);
01506
01507
01508 #ifdef ASM_DECLARE_FUNCTION_NAME
01509 ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
01510 #else
01511
01512 ASM_OUTPUT_LABEL (asm_out_file, fnname);
01513 #endif
01514 }
01515
01516
01517
01518
01519 void
01520 assemble_end_function (tree decl, const char *fnname ATTRIBUTE_UNUSED)
01521 {
01522 #ifdef ASM_DECLARE_FUNCTION_SIZE
01523
01524 if (flag_reorder_blocks_and_partition)
01525 switch_to_section (function_section (decl));
01526 ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);
01527 #endif
01528 if (! CONSTANT_POOL_BEFORE_FUNCTION)
01529 {
01530 output_constant_pool (fnname, decl);
01531 switch_to_section (function_section (decl));
01532 }
01533
01534
01535 if (flag_reorder_blocks_and_partition)
01536 {
01537 section *save_text_section;
01538
01539 save_text_section = in_section;
01540 switch_to_section (unlikely_text_section ());
01541 ASM_OUTPUT_LABEL (asm_out_file, cfun->cold_section_end_label);
01542 if (first_function_block_is_cold)
01543 switch_to_section (text_section);
01544 else
01545 switch_to_section (function_section (decl));
01546 ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_end_label);
01547 switch_to_section (save_text_section);
01548 }
01549 }
01550
01551
01552
01553 void
01554 assemble_zeros (unsigned HOST_WIDE_INT size)
01555 {
01556
01557 if (flag_syntax_only)
01558 return;
01559
01560 #ifdef ASM_NO_SKIP_IN_TEXT
01561
01562
01563 if (ASM_NO_SKIP_IN_TEXT && (in_section->common.flags & SECTION_CODE) != 0)
01564 {
01565 unsigned HOST_WIDE_INT i;
01566 for (i = 0; i < size; i++)
01567 assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
01568 }
01569 else
01570 #endif
01571 if (size > 0)
01572 ASM_OUTPUT_SKIP (asm_out_file, size);
01573 }
01574
01575
01576
01577 void
01578 assemble_align (int align)
01579 {
01580 if (align > BITS_PER_UNIT)
01581 {
01582 ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
01583 }
01584 }
01585
01586
01587
01588 void
01589 assemble_string (const char *p, int size)
01590 {
01591 int pos = 0;
01592 int maximum = 2000;
01593
01594
01595
01596 while (pos < size)
01597 {
01598 int thissize = size - pos;
01599 if (thissize > maximum)
01600 thissize = maximum;
01601
01602 ASM_OUTPUT_ASCII (asm_out_file, p, thissize);
01603
01604 pos += thissize;
01605 p += thissize;
01606 }
01607 }
01608
01609
01610
01611
01612 static bool
01613 emit_local (tree decl ATTRIBUTE_UNUSED,
01614 const char *name ATTRIBUTE_UNUSED,
01615 unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
01616 unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
01617 {
01618 #if defined ASM_OUTPUT_ALIGNED_DECL_LOCAL
01619 ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, decl, name,
01620 size, DECL_ALIGN (decl));
01621 return true;
01622 #elif defined ASM_OUTPUT_ALIGNED_LOCAL
01623 ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, DECL_ALIGN (decl));
01624 return true;
01625 #else
01626 ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
01627 return false;
01628 #endif
01629 }
01630
01631
01632
01633 #if defined ASM_OUTPUT_ALIGNED_BSS || defined ASM_OUTPUT_BSS
01634 static bool
01635 emit_bss (tree decl ATTRIBUTE_UNUSED,
01636 const char *name ATTRIBUTE_UNUSED,
01637 unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
01638 unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
01639 {
01640 #if defined ASM_OUTPUT_ALIGNED_BSS
01641 ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size, DECL_ALIGN (decl));
01642 return true;
01643 #else
01644 ASM_OUTPUT_BSS (asm_out_file, decl, name, size, rounded);
01645 return false;
01646 #endif
01647 }
01648 #endif
01649
01650
01651
01652 static bool
01653 emit_common (tree decl ATTRIBUTE_UNUSED,
01654 const char *name ATTRIBUTE_UNUSED,
01655 unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
01656 unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
01657 {
01658 #if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
01659 ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, decl, name,
01660 size, DECL_ALIGN (decl));
01661 return true;
01662 #elif defined ASM_OUTPUT_ALIGNED_COMMON
01663 ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, DECL_ALIGN (decl));
01664 return true;
01665 #else
01666 ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);
01667 return false;
01668 #endif
01669 }
01670
01671
01672
01673 static bool
01674 emit_tls_common (tree decl ATTRIBUTE_UNUSED,
01675 const char *name ATTRIBUTE_UNUSED,
01676 unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
01677 unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
01678 {
01679 #ifdef ASM_OUTPUT_TLS_COMMON
01680 ASM_OUTPUT_TLS_COMMON (asm_out_file, decl, name, size);
01681 return true;
01682 #else
01683 sorry ("thread-local COMMON data not implemented");
01684 return true;
01685 #endif
01686 }
01687
01688
01689
01690
01691 static void
01692 assemble_noswitch_variable (tree decl, const char *name, section *sect)
01693 {
01694 unsigned HOST_WIDE_INT size, rounded;
01695
01696 size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
01697 rounded = size;
01698
01699
01700
01701 if (size == 0)
01702 rounded = 1;
01703
01704
01705
01706 rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
01707 rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
01708 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
01709
01710 if (!sect->noswitch.callback (decl, name, size, rounded)
01711 && (unsigned HOST_WIDE_INT) DECL_ALIGN_UNIT (decl) > rounded)
01712 warning (0, "requested alignment for %q+D is greater than "
01713 "implemented alignment of %wu", decl, rounded);
01714 }
01715
01716
01717
01718
01719
01720 static void
01721 assemble_variable_contents (tree decl, const char *name,
01722 bool dont_output_data)
01723 {
01724
01725 #ifdef ASM_DECLARE_OBJECT_NAME
01726 last_assemble_variable_decl = decl;
01727 ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);
01728 #else
01729
01730 ASM_OUTPUT_LABEL (asm_out_file, name);
01731 #endif
01732
01733 if (!dont_output_data)
01734 {
01735 if (DECL_INITIAL (decl)
01736 && DECL_INITIAL (decl) != error_mark_node
01737 && !initializer_zerop (DECL_INITIAL (decl)))
01738
01739 output_constant (DECL_INITIAL (decl),
01740 tree_low_cst (DECL_SIZE_UNIT (decl), 1),
01741 DECL_ALIGN (decl));
01742 else
01743
01744 assemble_zeros (tree_low_cst (DECL_SIZE_UNIT (decl), 1));
01745 }
01746 }
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758 void
01759 assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
01760 int at_end ATTRIBUTE_UNUSED, int dont_output_data)
01761 {
01762 const char *name;
01763 rtx decl_rtl, symbol;
01764 section *sect;
01765
01766 if (lang_hooks.decls.prepare_assemble_variable)
01767 lang_hooks.decls.prepare_assemble_variable (decl);
01768
01769 last_assemble_variable_decl = 0;
01770
01771
01772
01773
01774
01775 if (DECL_EXTERNAL (decl))
01776 return;
01777
01778
01779
01780
01781 if (TREE_CODE (decl) == FUNCTION_DECL)
01782 return;
01783
01784
01785 if (DECL_RTL_SET_P (decl) && REG_P (DECL_RTL (decl)))
01786 {
01787 TREE_ASM_WRITTEN (decl) = 1;
01788 return;
01789 }
01790
01791
01792
01793
01794 if (DECL_SIZE (decl) == 0)
01795 layout_decl (decl, 0);
01796
01797
01798
01799
01800 if (!dont_output_data && DECL_SIZE (decl) == 0)
01801 {
01802 error ("storage size of %q+D isn%'t known", decl);
01803 TREE_ASM_WRITTEN (decl) = 1;
01804 return;
01805 }
01806
01807
01808
01809
01810
01811
01812 if (TREE_ASM_WRITTEN (decl))
01813 return;
01814
01815
01816
01817 decl_rtl = DECL_RTL (decl);
01818
01819 TREE_ASM_WRITTEN (decl) = 1;
01820
01821
01822 if (flag_syntax_only)
01823 return;
01824
01825 app_disable ();
01826
01827 if (! dont_output_data
01828 && ! host_integerp (DECL_SIZE_UNIT (decl), 1))
01829 {
01830 error ("size of variable %q+D is too large", decl);
01831 return;
01832 }
01833
01834 gcc_assert (MEM_P (decl_rtl));
01835 gcc_assert (GET_CODE (XEXP (decl_rtl, 0)) == SYMBOL_REF);
01836 symbol = XEXP (decl_rtl, 0);
01837 name = XSTR (symbol, 0);
01838 if (TREE_PUBLIC (decl) && DECL_NAME (decl))
01839 notice_global_symbol (decl);
01840
01841
01842
01843 #ifdef KEY
01844 if (!flag_spin_file)
01845 #endif
01846 {
01847 align_variable (decl, dont_output_data);
01848 set_mem_align (decl_rtl, DECL_ALIGN (decl));
01849 }
01850
01851 if (TREE_PUBLIC (decl))
01852 maybe_assemble_visibility (decl);
01853
01854 if (DECL_PRESERVE_P (decl))
01855 targetm.asm_out.mark_decl_preserved (name);
01856
01857
01858 sect = get_variable_section (decl, false);
01859 if (TREE_PUBLIC (decl)
01860 && DECL_NAME (decl)
01861 && (sect->common.flags & SECTION_COMMON) == 0)
01862 globalize_decl (decl);
01863
01864
01865 if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node)
01866 output_addressed_constants (DECL_INITIAL (decl));
01867
01868
01869 if (sect && (sect->common.flags & SECTION_CODE) != 0)
01870 DECL_IN_TEXT_SECTION (decl) = 1;
01871
01872 #ifdef KEY
01873 if (flag_spin_file) {
01874 DECL_EMITTED_BY_GXX(decl) = 1;
01875
01876
01877
01878 if (gspin_invoked (decl)) {
01879 gs_set_flag_value (decl, GS_DECL_EMITTED_BY_GXX, 1);
01880
01881
01882 gs_set_flag_value (decl, GS_DECL_EXTERNAL, DECL_EXTERNAL(decl));
01883 if (DECL_INITIAL (decl) == 0 ||
01884 DECL_INITIAL (decl) == error_mark_node) {
01885
01886 gs_set_operand(GS_NODE(decl), GS_DECL_SECTION_NAME,
01887 gs_x(DECL_SECTION_NAME(decl)));
01888 }
01889 }
01890
01891 if (DECL_ASSEMBLER_NAME_SET_P (decl) &&
01892 gspin_invoked (DECL_ASSEMBLER_NAME (decl)) &&
01893 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
01894 gs_set_flag_value (DECL_ASSEMBLER_NAME(decl),
01895 GS_TREE_SYMBOL_REFERENCED, 1);
01896 gspin_gxx_emits_decl (decl);
01897 }
01898 #endif
01899
01900
01901
01902
01903 if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol) && SYMBOL_REF_BLOCK (symbol))
01904 {
01905 gcc_assert (!dont_output_data);
01906 place_block_symbol (symbol);
01907 }
01908 else if (SECTION_STYLE (sect) == SECTION_NOSWITCH)
01909 assemble_noswitch_variable (decl, name, sect);
01910 else
01911 {
01912 switch_to_section (sect);
01913 if (DECL_ALIGN (decl) > BITS_PER_UNIT)
01914 ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DECL_ALIGN_UNIT (decl)));
01915 assemble_variable_contents (decl, name, dont_output_data);
01916 }
01917 }
01918
01919
01920
01921 static int
01922 contains_pointers_p (tree type)
01923 {
01924 switch (TREE_CODE (type))
01925 {
01926 case POINTER_TYPE:
01927 case REFERENCE_TYPE:
01928
01929
01930 case OFFSET_TYPE:
01931 return 1;
01932
01933 case RECORD_TYPE:
01934 case UNION_TYPE:
01935 case QUAL_UNION_TYPE:
01936 {
01937 tree fields;
01938
01939 for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
01940 if (TREE_CODE (fields) == FIELD_DECL
01941 && contains_pointers_p (TREE_TYPE (fields)))
01942 return 1;
01943 return 0;
01944 }
01945
01946 case ARRAY_TYPE:
01947
01948 return contains_pointers_p (TREE_TYPE (type));
01949
01950 default:
01951 return 0;
01952 }
01953 }
01954
01955
01956
01957
01958
01959 static GTY(()) tree pending_assemble_externals;
01960
01961 #ifdef ASM_OUTPUT_EXTERNAL
01962
01963
01964
01965 static bool
01966 incorporeal_function_p (tree decl)
01967 {
01968 if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
01969 {
01970 const char *name;
01971
01972 if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
01973 && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA)
01974 return true;
01975
01976 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
01977 if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
01978 return true;
01979 }
01980 return false;
01981 }
01982
01983
01984
01985 static void
01986 assemble_external_real (tree decl)
01987 {
01988 rtx rtl = DECL_RTL (decl);
01989
01990 if (MEM_P (rtl) && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
01991 && !SYMBOL_REF_USED (XEXP (rtl, 0))
01992 && !incorporeal_function_p (decl))
01993 {
01994
01995 SYMBOL_REF_USED (XEXP (rtl, 0)) = 1;
01996 ASM_OUTPUT_EXTERNAL (asm_out_file, decl, XSTR (XEXP (rtl, 0), 0));
01997 }
01998 }
01999 #endif
02000
02001 void
02002 process_pending_assemble_externals (void)
02003 {
02004 #ifdef ASM_OUTPUT_EXTERNAL
02005 tree list;
02006 for (list = pending_assemble_externals; list; list = TREE_CHAIN (list))
02007 assemble_external_real (TREE_VALUE (list));
02008
02009 pending_assemble_externals = 0;
02010 #endif
02011 }
02012
02013
02014
02015
02016
02017 void
02018 assemble_external (tree decl ATTRIBUTE_UNUSED)
02019 {
02020
02021
02022
02023
02024 gcc_assert (asm_out_file);
02025
02026 #ifdef ASM_OUTPUT_EXTERNAL
02027 if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
02028 return;
02029
02030 if (flag_unit_at_a_time)
02031 pending_assemble_externals = tree_cons (0, decl,
02032 pending_assemble_externals);
02033 else
02034 assemble_external_real (decl);
02035 #endif
02036 }
02037
02038
02039
02040 void
02041 assemble_external_libcall (rtx fun)
02042 {
02043
02044 if (! SYMBOL_REF_USED (fun))
02045 {
02046 SYMBOL_REF_USED (fun) = 1;
02047 targetm.asm_out.external_libcall (fun);
02048 }
02049 }
02050
02051
02052
02053 void
02054 assemble_label (const char *name)
02055 {
02056 ASM_OUTPUT_LABEL (asm_out_file, name);
02057 }
02058
02059
02060 void
02061 mark_referenced (tree id)
02062 {
02063 TREE_SYMBOL_REFERENCED (id) = 1;
02064 }
02065
02066
02067 void
02068 mark_decl_referenced (tree decl)
02069 {
02070 if (TREE_CODE (decl) == FUNCTION_DECL)
02071 {
02072
02073
02074
02075
02076 struct cgraph_node *node = cgraph_node (decl);
02077 if (!DECL_EXTERNAL (decl)
02078 && (!node->local.vtable_method || !cgraph_global_info_ready
02079 || !node->local.finalized))
02080 cgraph_mark_needed_node (node);
02081 }
02082 else if (TREE_CODE (decl) == VAR_DECL)
02083 {
02084 struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
02085 cgraph_varpool_mark_needed_node (node);
02086
02087
02088 node->force_output = true;
02089 }
02090
02091
02092 }
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102 static inline tree
02103 ultimate_transparent_alias_target (tree *alias)
02104 {
02105 tree target = *alias;
02106
02107 if (IDENTIFIER_TRANSPARENT_ALIAS (target))
02108 {
02109 gcc_assert (TREE_CHAIN (target));
02110 target = ultimate_transparent_alias_target (&TREE_CHAIN (target));
02111 gcc_assert (! IDENTIFIER_TRANSPARENT_ALIAS (target)
02112 && ! TREE_CHAIN (target));
02113 *alias = target;
02114 }
02115
02116 return target;
02117 }
02118
02119
02120
02121
02122
02123
02124 void
02125 assemble_name_raw (FILE *file, const char *name)
02126 {
02127 if (name[0] == '*')
02128 fputs (&name[1], file);
02129 else
02130 ASM_OUTPUT_LABELREF (file, name);
02131 }
02132
02133
02134
02135
02136
02137
02138 void
02139 assemble_name (FILE *file, const char *name)
02140 {
02141 const char *real_name;
02142 tree id;
02143
02144 real_name = targetm.strip_name_encoding (name);
02145
02146 id = maybe_get_identifier (real_name);
02147 if (id)
02148 {
02149 tree id_orig = id;
02150
02151 mark_referenced (id);
02152 ultimate_transparent_alias_target (&id);
02153 if (id != id_orig)
02154 name = IDENTIFIER_POINTER (id);
02155 gcc_assert (! TREE_CHAIN (id));
02156 }
02157
02158 assemble_name_raw (file, name);
02159 }
02160
02161
02162
02163
02164 rtx
02165 assemble_static_space (unsigned HOST_WIDE_INT size)
02166 {
02167 char name[12];
02168 const char *namestring;
02169 rtx x;
02170
02171 ASM_GENERATE_INTERNAL_LABEL (name, "LF", const_labelno);
02172 ++const_labelno;
02173 namestring = ggc_strdup (name);
02174
02175 x = gen_rtx_SYMBOL_REF (Pmode, namestring);
02176 SYMBOL_REF_FLAGS (x) = SYMBOL_FLAG_LOCAL;
02177
02178 #ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL
02179 ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name, size,
02180 BIGGEST_ALIGNMENT);
02181 #else
02182 #ifdef ASM_OUTPUT_ALIGNED_LOCAL
02183 ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT);
02184 #else
02185 {
02186
02187
02188
02189 unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED
02190 = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
02191 / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
02192 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
02193 ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
02194 }
02195 #endif
02196 #endif
02197 return x;
02198 }
02199
02200
02201
02202
02203
02204 static GTY(()) rtx initial_trampoline;
02205
02206 #ifdef TRAMPOLINE_TEMPLATE
02207 rtx
02208 assemble_trampoline_template (void)
02209 {
02210 char label[256];
02211 const char *name;
02212 int align;
02213 rtx symbol;
02214
02215 if (initial_trampoline)
02216 return initial_trampoline;
02217
02218
02219
02220 #ifdef TRAMPOLINE_SECTION
02221 switch_to_section (TRAMPOLINE_SECTION);
02222 #else
02223 switch_to_section (readonly_data_section);
02224 #endif
02225
02226
02227 align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
02228 if (align > 0)
02229 {
02230 ASM_OUTPUT_ALIGN (asm_out_file, align);
02231 }
02232
02233 targetm.asm_out.internal_label (asm_out_file, "LTRAMP", 0);
02234 TRAMPOLINE_TEMPLATE (asm_out_file);
02235
02236
02237 ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0);
02238 name = ggc_strdup (label);
02239 symbol = gen_rtx_SYMBOL_REF (Pmode, name);
02240 SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
02241
02242 initial_trampoline = gen_rtx_MEM (BLKmode, symbol);
02243 set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
02244
02245 return initial_trampoline;
02246 }
02247 #endif
02248
02249
02250
02251
02252 static inline unsigned
02253 min_align (unsigned int a, unsigned int b)
02254 {
02255 return (a | b) & -(a | b);
02256 }
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266 const char *
02267 integer_asm_op (int size, int aligned_p)
02268 {
02269 struct asm_int_op *ops;
02270
02271 if (aligned_p)
02272 ops = &targetm.asm_out.aligned_op;
02273 else
02274 ops = &targetm.asm_out.unaligned_op;
02275
02276 switch (size)
02277 {
02278 case 1:
02279 return targetm.asm_out.byte_op;
02280 case 2:
02281 return ops->hi;
02282 case 4:
02283 return ops->si;
02284 case 8:
02285 return ops->di;
02286 case 16:
02287 return ops->ti;
02288 default:
02289 return NULL;
02290 }
02291 }
02292
02293
02294
02295
02296 void
02297 assemble_integer_with_op (const char *op, rtx x)
02298 {
02299 fputs (op, asm_out_file);
02300 output_addr_const (asm_out_file, x);
02301 fputc ('\n', asm_out_file);
02302 }
02303
02304
02305
02306 bool
02307 default_assemble_integer (rtx x ATTRIBUTE_UNUSED,
02308 unsigned int size ATTRIBUTE_UNUSED,
02309 int aligned_p ATTRIBUTE_UNUSED)
02310 {
02311 const char *op = integer_asm_op (size, aligned_p);
02312
02313
02314 if (size > UNITS_PER_WORD && size > POINTER_SIZE / BITS_PER_UNIT)
02315 return false;
02316 return op && (assemble_integer_with_op (op, x), true);
02317 }
02318
02319
02320
02321
02322
02323
02324 bool
02325 assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
02326 {
02327 int aligned_p;
02328
02329 aligned_p = (align >= MIN (size * BITS_PER_UNIT, BIGGEST_ALIGNMENT));
02330
02331
02332 if (targetm.asm_out.integer (x, size, aligned_p))
02333 return true;
02334
02335 #ifdef KEY
02336 if (flag_spin_file)
02337 return true;
02338 #endif
02339
02340
02341
02342 if (size > 1)
02343 {
02344 enum machine_mode omode, imode;
02345 unsigned int subalign;
02346 unsigned int subsize, i;
02347
02348 subsize = size > UNITS_PER_WORD? UNITS_PER_WORD : 1;
02349 subalign = MIN (align, subsize * BITS_PER_UNIT);
02350 omode = mode_for_size (subsize * BITS_PER_UNIT, MODE_INT, 0);
02351 imode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
02352
02353 for (i = 0; i < size; i += subsize)
02354 {
02355 rtx partial = simplify_subreg (omode, x, imode, i);
02356 if (!partial || !assemble_integer (partial, subsize, subalign, 0))
02357 break;
02358 }
02359 if (i == size)
02360 return true;
02361
02362
02363
02364 gcc_assert (!i);
02365 }
02366
02367 gcc_assert (!force);
02368
02369 return false;
02370 }
02371
02372 void
02373 assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)
02374 {
02375 long data[4] = {0, 0, 0, 0};
02376 int i;
02377 int bitsize, nelts, nunits, units_per;
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391 nunits = GET_MODE_SIZE (mode);
02392 bitsize = nunits * BITS_PER_UNIT;
02393 nelts = CEIL (bitsize, 32);
02394 units_per = 32 / BITS_PER_UNIT;
02395
02396 real_to_target (data, &d, mode);
02397
02398
02399 assemble_integer (GEN_INT (data[0]), MIN (nunits, units_per), align, 1);
02400 nunits -= units_per;
02401
02402
02403 align = min_align (align, 32);
02404
02405 for (i = 1; i < nelts; i++)
02406 {
02407 assemble_integer (GEN_INT (data[i]), MIN (nunits, units_per), align, 1);
02408 nunits -= units_per;
02409 }
02410 }
02411
02412
02413
02414
02415
02416
02417 struct addr_const GTY(())
02418 {
02419 rtx base;
02420 HOST_WIDE_INT offset;
02421 };
02422
02423 static void
02424 decode_addr_const (tree exp, struct addr_const *value)
02425 {
02426 tree target = TREE_OPERAND (exp, 0);
02427 int offset = 0;
02428 rtx x;
02429
02430 while (1)
02431 {
02432 if (TREE_CODE (target) == COMPONENT_REF
02433 && host_integerp (byte_position (TREE_OPERAND (target, 1)), 0))
02434
02435 {
02436 offset += int_byte_position (TREE_OPERAND (target, 1));
02437 target = TREE_OPERAND (target, 0);
02438 }
02439 else if (TREE_CODE (target) == ARRAY_REF
02440 || TREE_CODE (target) == ARRAY_RANGE_REF)
02441 {
02442 offset += (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (target)), 1)
02443 * tree_low_cst (TREE_OPERAND (target, 1), 0));
02444 target = TREE_OPERAND (target, 0);
02445 }
02446 else
02447 break;
02448 }
02449
02450 switch (TREE_CODE (target))
02451 {
02452 case VAR_DECL:
02453 case FUNCTION_DECL:
02454 x = DECL_RTL (target);
02455 break;
02456
02457 case LABEL_DECL:
02458 x = gen_rtx_MEM (FUNCTION_MODE,
02459 gen_rtx_LABEL_REF (Pmode, force_label_rtx (target)));
02460 break;
02461
02462 case REAL_CST:
02463 case STRING_CST:
02464 case COMPLEX_CST:
02465 case CONSTRUCTOR:
02466 case INTEGER_CST:
02467 x = output_constant_def (target, 1);
02468 break;
02469
02470 default:
02471 gcc_unreachable ();
02472 }
02473
02474 gcc_assert (MEM_P (x));
02475 x = XEXP (x, 0);
02476
02477 value->base = x;
02478 value->offset = offset;
02479 }
02480
02481
02482
02483
02484
02485 struct constant_descriptor_tree GTY(())
02486 {
02487
02488 rtx rtl;
02489
02490
02491 tree value;
02492
02493
02494
02495
02496 hashval_t hash;
02497 };
02498
02499 static GTY((param_is (struct constant_descriptor_tree)))
02500 htab_t const_desc_htab;
02501
02502 static struct constant_descriptor_tree * build_constant_desc (tree);
02503 static void maybe_output_constant_def_contents (struct constant_descriptor_tree *, int);
02504
02505
02506
02507 static hashval_t
02508 const_desc_hash (const void *ptr)
02509 {
02510 return ((struct constant_descriptor_tree *)ptr)->hash;
02511 }
02512
02513 static hashval_t
02514 const_hash_1 (const tree exp)
02515 {
02516 const char *p;
02517 hashval_t hi;
02518 int len, i;
02519 enum tree_code code = TREE_CODE (exp);
02520
02521
02522
02523
02524 switch (code)
02525 {
02526 case INTEGER_CST:
02527 p = (char *) &TREE_INT_CST (exp);
02528 len = sizeof TREE_INT_CST (exp);
02529 break;
02530
02531 case REAL_CST:
02532 return real_hash (TREE_REAL_CST_PTR (exp));
02533
02534 case STRING_CST:
02535 p = TREE_STRING_POINTER (exp);
02536 len = TREE_STRING_LENGTH (exp);
02537 break;
02538
02539 case COMPLEX_CST:
02540 return (const_hash_1 (TREE_REALPART (exp)) * 5
02541 + const_hash_1 (TREE_IMAGPART (exp)));
02542
02543 case CONSTRUCTOR:
02544 {
02545 unsigned HOST_WIDE_INT idx;
02546 tree value;
02547
02548 hi = 5 + int_size_in_bytes (TREE_TYPE (exp));
02549
02550 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
02551 if (value)
02552 hi = hi * 603 + const_hash_1 (value);
02553
02554 return hi;
02555 }
02556
02557 case ADDR_EXPR:
02558 case FDESC_EXPR:
02559 {
02560 struct addr_const value;
02561
02562 decode_addr_const (exp, &value);
02563 switch (GET_CODE (value.base))
02564 {
02565 case SYMBOL_REF:
02566
02567
02568 hi = value.offset;
02569 p = XSTR (value.base, 0);
02570 for (i = 0; p[i] != 0; i++)
02571 hi = ((hi * 613) + (unsigned) (p[i]));
02572 break;
02573
02574 case LABEL_REF:
02575 hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;
02576 break;
02577
02578 default:
02579 gcc_unreachable ();
02580 }
02581 }
02582 return hi;
02583
02584 case PLUS_EXPR:
02585 case MINUS_EXPR:
02586 return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9
02587 + const_hash_1 (TREE_OPERAND (exp, 1)));
02588
02589 case NOP_EXPR:
02590 case CONVERT_EXPR:
02591 case NON_LVALUE_EXPR:
02592 return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2;
02593
02594 default:
02595
02596 return code;
02597 }
02598
02599
02600 hi = len;
02601 for (i = 0; i < len; i++)
02602 hi = ((hi * 613) + (unsigned) (p[i]));
02603
02604 return hi;
02605 }
02606
02607
02608 static int
02609 const_desc_eq (const void *p1, const void *p2)
02610 {
02611 const struct constant_descriptor_tree *c1 = p1;
02612 const struct constant_descriptor_tree *c2 = p2;
02613 if (c1->hash != c2->hash)
02614 return 0;
02615 return compare_constant (c1->value, c2->value);
02616 }
02617
02618
02619
02620
02621 static int
02622 compare_constant (const tree t1, const tree t2)
02623 {
02624 enum tree_code typecode;
02625
02626 if (t1 == NULL_TREE)
02627 return t2 == NULL_TREE;
02628 if (t2 == NULL_TREE)
02629 return 0;
02630
02631 if (TREE_CODE (t1) != TREE_CODE (t2))
02632 return 0;
02633
02634 switch (TREE_CODE (t1))
02635 {
02636 case INTEGER_CST:
02637
02638 if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
02639 return 0;
02640 if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
02641 return 0;
02642 return tree_int_cst_equal (t1, t2);
02643
02644 case REAL_CST:
02645
02646 if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
02647 return 0;
02648
02649 return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
02650
02651 case STRING_CST:
02652 if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
02653 return 0;
02654
02655 return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
02656 && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
02657 TREE_STRING_LENGTH (t1)));
02658
02659 case COMPLEX_CST:
02660 return (compare_constant (TREE_REALPART (t1), TREE_REALPART (t2))
02661 && compare_constant (TREE_IMAGPART (t1), TREE_IMAGPART (t2)));
02662
02663 case CONSTRUCTOR:
02664 {
02665 VEC(constructor_elt, gc) *v1, *v2;
02666 unsigned HOST_WIDE_INT idx;
02667
02668 typecode = TREE_CODE (TREE_TYPE (t1));
02669 if (typecode != TREE_CODE (TREE_TYPE (t2)))
02670 return 0;
02671
02672 if (typecode == ARRAY_TYPE)
02673 {
02674 HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
02675
02676 if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
02677 || size_1 == -1
02678 || size_1 != int_size_in_bytes (TREE_TYPE (t2)))
02679 return 0;
02680 }
02681 else
02682 {
02683
02684
02685 if (TREE_TYPE (t1) != TREE_TYPE (t2))
02686 return 0;
02687 }
02688
02689 v1 = CONSTRUCTOR_ELTS (t1);
02690 v2 = CONSTRUCTOR_ELTS (t2);
02691 if (VEC_length (constructor_elt, v1)
02692 != VEC_length (constructor_elt, v2))
02693 return 0;
02694
02695 for (idx = 0; idx < VEC_length (constructor_elt, v1); ++idx)
02696 {
02697 constructor_elt *c1 = VEC_index (constructor_elt, v1, idx);
02698 constructor_elt *c2 = VEC_index (constructor_elt, v2, idx);
02699
02700
02701 if (!compare_constant (c1->value, c2->value))
02702 return 0;
02703
02704 if (typecode == ARRAY_TYPE)
02705 {
02706 if (!compare_constant (c1->index, c2->index))
02707 return 0;
02708 }
02709 else
02710 {
02711 if (c1->index != c2->index)
02712 return 0;
02713 }
02714 }
02715
02716 return 1;
02717 }
02718
02719 case ADDR_EXPR:
02720 case FDESC_EXPR:
02721 {
02722 struct addr_const value1, value2;
02723
02724 decode_addr_const (t1, &value1);
02725 decode_addr_const (t2, &value2);
02726 return (value1.offset == value2.offset
02727 && strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0);
02728 }
02729
02730 case PLUS_EXPR:
02731 case MINUS_EXPR:
02732 case RANGE_EXPR:
02733 return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
02734 && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
02735
02736 case NOP_EXPR:
02737 case CONVERT_EXPR:
02738 case NON_LVALUE_EXPR:
02739 case VIEW_CONVERT_EXPR:
02740 return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
02741
02742 default:
02743 {
02744 tree nt1, nt2;
02745 nt1 = lang_hooks.expand_constant (t1);
02746 nt2 = lang_hooks.expand_constant (t2);
02747 if (nt1 != t1 || nt2 != t2)
02748 return compare_constant (nt1, nt2);
02749 else
02750 return 0;
02751 }
02752 }
02753
02754 gcc_unreachable ();
02755 }
02756
02757
02758
02759
02760 static tree
02761 copy_constant (tree exp)
02762 {
02763 switch (TREE_CODE (exp))
02764 {
02765 case ADDR_EXPR:
02766
02767
02768 if (CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))
02769 return build1 (TREE_CODE (exp), TREE_TYPE (exp),
02770 copy_constant (TREE_OPERAND (exp, 0)));
02771 else
02772 return copy_node (exp);
02773
02774 case INTEGER_CST:
02775 case REAL_CST:
02776 case STRING_CST:
02777 return copy_node (exp);
02778
02779 case COMPLEX_CST:
02780 return build_complex (TREE_TYPE (exp),
02781 copy_constant (TREE_REALPART (exp)),
02782 copy_constant (TREE_IMAGPART (exp)));
02783
02784 case PLUS_EXPR:
02785 case MINUS_EXPR:
02786 return build2 (TREE_CODE (exp), TREE_TYPE (exp),
02787 copy_constant (TREE_OPERAND (exp, 0)),
02788 copy_constant (TREE_OPERAND (exp, 1)));
02789
02790 case NOP_EXPR:
02791 case CONVERT_EXPR:
02792 case NON_LVALUE_EXPR:
02793 case VIEW_CONVERT_EXPR:
02794 return build1 (TREE_CODE (exp), TREE_TYPE (exp),
02795 copy_constant (TREE_OPERAND (exp, 0)));
02796
02797 case CONSTRUCTOR:
02798 {
02799 tree copy = copy_node (exp);
02800 VEC(constructor_elt, gc) *v;
02801 unsigned HOST_WIDE_INT idx;
02802 tree purpose, value;
02803
02804 v = VEC_alloc(constructor_elt, gc, VEC_length(constructor_elt,
02805 CONSTRUCTOR_ELTS (exp)));
02806 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, purpose, value)
02807 {
02808 constructor_elt *ce = VEC_quick_push (constructor_elt, v, NULL);
02809 ce->index = purpose;
02810 ce->value = copy_constant (value);
02811 }
02812 CONSTRUCTOR_ELTS (copy) = v;
02813 return copy;
02814 }
02815
02816 default:
02817 {
02818 tree t = lang_hooks.expand_constant (exp);
02819
02820 gcc_assert (t != exp);
02821 return copy_constant (t);
02822 }
02823 }
02824 }
02825
02826
02827
02828 static unsigned int
02829 get_constant_alignment (tree exp)
02830 {
02831 unsigned int align;
02832
02833 align = TYPE_ALIGN (TREE_TYPE (exp));
02834 #ifdef CONSTANT_ALIGNMENT
02835 align = CONSTANT_ALIGNMENT (exp, align);
02836 #endif
02837 return align;
02838 }
02839
02840
02841
02842 static section *
02843 get_constant_section (tree exp)
02844 {
02845 if (IN_NAMED_SECTION (exp))
02846 return get_named_section (exp, NULL, compute_reloc_for_constant (exp));
02847 else
02848 return targetm.asm_out.select_section (exp,
02849 compute_reloc_for_constant (exp),
02850 get_constant_alignment (exp));
02851 }
02852
02853
02854
02855 static HOST_WIDE_INT
02856 get_constant_size (tree exp)
02857 {
02858 HOST_WIDE_INT size;
02859
02860 size = int_size_in_bytes (TREE_TYPE (exp));
02861 if (TREE_CODE (exp) == STRING_CST)
02862 size = MAX (TREE_STRING_LENGTH (exp), size);
02863 return size;
02864 }
02865
02866
02867
02868
02869
02870
02871
02872
02873 static struct constant_descriptor_tree *
02874 build_constant_desc (tree exp)
02875 {
02876 rtx symbol;
02877 rtx rtl;
02878 char label[256];
02879 int labelno;
02880 struct constant_descriptor_tree *desc;
02881
02882 desc = ggc_alloc (sizeof (*desc));
02883 desc->value = copy_constant (exp);
02884
02885
02886 if (flag_mudflap && mf_marked_p (exp))
02887 mf_mark (desc->value);
02888
02889
02890 labelno = const_labelno++;
02891 ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
02892
02893
02894 if (use_object_blocks_p ())
02895 {
02896 section *sect = get_constant_section (exp);
02897 symbol = create_block_symbol (ggc_strdup (label),
02898 get_block_for_section (sect), -1);
02899 }
02900 else
02901 symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
02902 SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LOCAL;
02903 SET_SYMBOL_REF_DECL (symbol, desc->value);
02904 TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1;
02905
02906 rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol);
02907 set_mem_attributes (rtl, exp, 1);
02908 set_mem_alias_set (rtl, 0);
02909 set_mem_alias_set (rtl, const_alias_set);
02910
02911
02912
02913
02914
02915
02916
02917 targetm.encode_section_info (exp, rtl, true);
02918
02919 desc->rtl = rtl;
02920
02921 return desc;
02922 }
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937 rtx
02938 output_constant_def (tree exp, int defer)
02939 {
02940 struct constant_descriptor_tree *desc;
02941 struct constant_descriptor_tree key;
02942 void **loc;
02943
02944
02945
02946 key.value = exp;
02947 key.hash = const_hash_1 (exp);
02948 loc = htab_find_slot_with_hash (const_desc_htab, &key, key.hash, INSERT);
02949
02950 desc = *loc;
02951 if (desc == 0)
02952 {
02953 desc = build_constant_desc (exp);
02954 desc->hash = key.hash;
02955 *loc = desc;
02956 }
02957
02958 maybe_output_constant_def_contents (desc, defer);
02959 return desc->rtl;
02960 }
02961
02962
02963
02964 static void
02965 maybe_output_constant_def_contents (struct constant_descriptor_tree *desc,
02966 int defer)
02967 {
02968 rtx symbol = XEXP (desc->rtl, 0);
02969 tree exp = desc->value;
02970
02971 if (flag_syntax_only)
02972 return;
02973
02974 if (TREE_ASM_WRITTEN (exp))
02975
02976 return;
02977
02978
02979
02980 if (defer)
02981 {
02982
02983
02984
02985
02986
02987 if (cfun)
02988 n_deferred_constants++;
02989 return;
02990 }
02991
02992 output_constant_def_contents (symbol);
02993 }
02994
02995
02996
02997
02998
02999 static void
03000 assemble_constant_contents (tree exp, const char *label, unsigned int align)
03001 {
03002 HOST_WIDE_INT size;
03003
03004 size = get_constant_size (exp);
03005
03006
03007 #ifdef ASM_DECLARE_CONSTANT_NAME
03008 ASM_DECLARE_CONSTANT_NAME (asm_out_file, label, exp, size);
03009 #else
03010
03011 ASM_OUTPUT_LABEL (asm_out_file, label);
03012 #endif
03013
03014
03015 output_constant (exp, size, align);
03016 }
03017
03018
03019
03020 static void
03021 output_constant_def_contents (rtx symbol)
03022 {
03023 tree exp = SYMBOL_REF_DECL (symbol);
03024 unsigned int align;
03025
03026
03027
03028 output_addressed_constants (exp);
03029
03030
03031 TREE_ASM_WRITTEN (exp) = 1;
03032
03033
03034
03035
03036 if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol) && SYMBOL_REF_BLOCK (symbol))
03037 place_block_symbol (symbol);
03038 else
03039 {
03040 switch_to_section (get_constant_section (exp));
03041 align = get_constant_alignment (exp);
03042 if (align > BITS_PER_UNIT)
03043 ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
03044 assemble_constant_contents (exp, XSTR (symbol, 0), align);
03045 }
03046 if (flag_mudflap)
03047 mudflap_enqueue_constant (exp);
03048 }
03049
03050
03051
03052
03053 rtx
03054 lookup_constant_def (tree exp)
03055 {
03056 struct constant_descriptor_tree *desc;
03057 struct constant_descriptor_tree key;
03058
03059 key.value = exp;
03060 key.hash = const_hash_1 (exp);
03061 desc = htab_find_with_hash (const_desc_htab, &key, key.hash);
03062
03063 return (desc ? desc->rtl : NULL_RTX);
03064 }
03065
03066
03067
03068
03069
03070
03071
03072
03073 struct rtx_constant_pool GTY(())
03074 {
03075
03076 struct constant_descriptor_rtx *first;
03077 struct constant_descriptor_rtx *last;
03078
03079
03080
03081
03082
03083 htab_t GTY((param_is (struct constant_descriptor_rtx))) const_rtx_htab;
03084
03085
03086
03087 HOST_WIDE_INT offset;
03088 };
03089
03090 struct constant_descriptor_rtx GTY((chain_next ("%h.next")))
03091 {
03092 struct constant_descriptor_rtx *next;
03093 rtx mem;
03094 rtx sym;
03095 rtx constant;
03096 HOST_WIDE_INT offset;
03097 hashval_t hash;
03098 enum machine_mode mode;
03099 unsigned int align;
03100 int labelno;
03101 int mark;
03102 };
03103
03104
03105
03106 static hashval_t
03107 const_desc_rtx_hash (const void *ptr)
03108 {
03109 const struct constant_descriptor_rtx *desc = ptr;
03110 return desc->hash;
03111 }
03112
03113 static int
03114 const_desc_rtx_eq (const void *a, const void *b)
03115 {
03116 const struct constant_descriptor_rtx *x = a;
03117 const struct constant_descriptor_rtx *y = b;
03118
03119 if (x->mode != y->mode)
03120 return 0;
03121 return rtx_equal_p (x->constant, y->constant);
03122 }
03123
03124
03125
03126 static int
03127 const_rtx_hash_1 (rtx *xp, void *data)
03128 {
03129 unsigned HOST_WIDE_INT hwi;
03130 enum machine_mode mode;
03131 enum rtx_code code;
03132 hashval_t h, *hp;
03133 rtx x;
03134
03135 x = *xp;
03136 code = GET_CODE (x);
03137 mode = GET_MODE (x);
03138 h = (hashval_t) code * 1048573 + mode;
03139
03140 switch (code)
03141 {
03142 case CONST_INT:
03143 hwi = INTVAL (x);
03144 fold_hwi:
03145 {
03146 const int shift = sizeof (hashval_t) * CHAR_BIT;
03147 const int n = sizeof (HOST_WIDE_INT) / sizeof (hashval_t);
03148 int i;
03149
03150 h ^= (hashval_t) hwi;
03151 for (i = 1; i < n; ++i)
03152 {
03153 hwi >>= shift;
03154 h ^= (hashval_t) hwi;
03155 }
03156 }
03157 break;
03158
03159 case CONST_DOUBLE:
03160 if (mode == VOIDmode)
03161 {
03162 hwi = CONST_DOUBLE_LOW (x) ^ CONST_DOUBLE_HIGH (x);
03163 goto fold_hwi;
03164 }
03165 else
03166 h ^= real_hash (CONST_DOUBLE_REAL_VALUE (x));
03167 break;
03168
03169 case CONST_VECTOR:
03170 {
03171 int i;
03172 for (i = XVECLEN (x, 0); i-- > 0; )
03173 h = h * 251 + const_rtx_hash_1 (&XVECEXP (x, 0, i), data);
03174 }
03175 break;
03176
03177 case SYMBOL_REF:
03178 h ^= htab_hash_string (XSTR (x, 0));
03179 break;
03180
03181 case LABEL_REF:
03182 h = h * 251 + CODE_LABEL_NUMBER (XEXP (x, 0));
03183 break;
03184
03185 case UNSPEC:
03186 case UNSPEC_VOLATILE:
03187 h = h * 251 + XINT (x, 1);
03188 break;
03189
03190 default:
03191 break;
03192 }
03193
03194 hp = data;
03195 *hp = *hp * 509 + h;
03196 return 0;
03197 }
03198
03199
03200
03201 static hashval_t
03202 const_rtx_hash (rtx x)
03203 {
03204 hashval_t h = 0;
03205 for_each_rtx (&x, const_rtx_hash_1, &h);
03206 return h;
03207 }
03208
03209
03210
03211
03212 static struct rtx_constant_pool *
03213 create_constant_pool (void)
03214 {
03215 struct rtx_constant_pool *pool;
03216
03217 pool = ggc_alloc (sizeof (struct rtx_constant_pool));
03218 pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
03219 const_desc_rtx_eq, NULL);
03220 pool->first = NULL;
03221 pool->last = NULL;
03222 pool->offset = 0;
03223 return pool;
03224 }
03225
03226
03227
03228 void
03229 init_varasm_status (struct function *f)
03230 {
03231 struct varasm_status *p;
03232
03233 p = ggc_alloc (sizeof (struct varasm_status));
03234 f->varasm = p;
03235
03236 p->pool = create_constant_pool ();
03237 p->deferred_constants = 0;
03238 }
03239
03240
03241
03242
03243 rtx
03244 simplify_subtraction (rtx x)
03245 {
03246 rtx r = simplify_rtx (x);
03247 return r ? r : x;
03248 }
03249
03250
03251
03252
03253 rtx
03254 force_const_mem (enum machine_mode mode, rtx x)
03255 {
03256 struct constant_descriptor_rtx *desc, tmp;
03257 struct rtx_constant_pool *pool;
03258 char label[256];
03259 rtx def, symbol;
03260 hashval_t hash;
03261 unsigned int align;
03262 void **slot;
03263
03264
03265 if (targetm.cannot_force_const_mem (x))
03266 return NULL_RTX;
03267
03268
03269 current_function_uses_const_pool = 1;
03270
03271
03272 pool = (targetm.use_blocks_for_constant_p (mode, x)
03273 ? shared_constant_pool
03274 : cfun->varasm->pool);
03275
03276
03277 tmp.constant = x;
03278 tmp.mode = mode;
03279 hash = const_rtx_hash (x);
03280 slot = htab_find_slot_with_hash (pool->const_rtx_htab, &tmp, hash, INSERT);
03281 desc = *slot;
03282
03283
03284 if (desc)
03285 return copy_rtx (desc->mem);
03286
03287
03288 desc = ggc_alloc (sizeof (*desc));
03289 *slot = desc;
03290
03291
03292 align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode);
03293 #ifdef CONSTANT_ALIGNMENT
03294 {
03295 tree type = lang_hooks.types.type_for_mode (mode, 0);
03296 if (type != NULL_TREE)
03297 align = CONSTANT_ALIGNMENT (make_tree (type, x), align);
03298 }
03299 #endif
03300
03301 pool->offset += (align / BITS_PER_UNIT) - 1;
03302 pool->offset &= ~ ((align / BITS_PER_UNIT) - 1);
03303
03304 desc->next = NULL;
03305 desc->constant = tmp.constant;
03306 desc->offset = pool->offset;
03307 desc->hash = hash;
03308 desc->mode = mode;
03309 desc->align = align;
03310 desc->labelno = const_labelno;
03311 desc->mark = 0;
03312
03313 pool->offset += GET_MODE_SIZE (mode);
03314 if (pool->last)
03315 pool->last->next = desc;
03316 else
03317 pool->first = pool->last = desc;
03318 pool->last = desc;
03319
03320
03321 ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
03322 ++const_labelno;
03323
03324
03325
03326 if (use_object_blocks_p () && targetm.use_blocks_for_constant_p (mode, x))
03327 {
03328 section *sect = targetm.asm_out.select_rtx_section (mode, x, align);
03329 symbol = create_block_symbol (ggc_strdup (label),
03330 get_block_for_section (sect), -1);
03331 }
03332 else
03333 symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
03334 desc->sym = symbol;
03335 SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LOCAL;
03336 CONSTANT_POOL_ADDRESS_P (symbol) = 1;
03337 SET_SYMBOL_REF_CONSTANT (symbol, desc);
03338
03339
03340 desc->mem = def = gen_const_mem (mode, symbol);
03341 set_mem_attributes (def, lang_hooks.types.type_for_mode (mode, 0), 1);
03342 set_mem_align (def, align);
03343
03344
03345
03346 if (GET_CODE (x) == LABEL_REF)
03347 LABEL_PRESERVE_P (XEXP (x, 0)) = 1;
03348
03349 return copy_rtx (def);
03350 }
03351
03352
03353
03354 rtx
03355 get_pool_constant (rtx addr)
03356 {
03357 return SYMBOL_REF_CONSTANT (addr)->constant;
03358 }
03359
03360
03361
03362
03363 rtx
03364 get_pool_constant_mark (rtx addr, bool *pmarked)
03365 {
03366 struct constant_descriptor_rtx *desc;
03367
03368 desc = SYMBOL_REF_CONSTANT (addr);
03369 *pmarked = (desc->mark != 0);
03370 return desc->constant;
03371 }
03372
03373
03374
03375 enum machine_mode
03376 get_pool_mode (rtx addr)
03377 {
03378 return SYMBOL_REF_CONSTANT (addr)->mode;
03379 }
03380
03381
03382
03383 int
03384 get_pool_size (void)
03385 {
03386 return cfun->varasm->pool->offset;
03387 }
03388
03389
03390
03391
03392 static void
03393 output_constant_pool_2 (enum machine_mode mode, rtx x, unsigned int align)
03394 {
03395 switch (GET_MODE_CLASS (mode))
03396 {
03397 case MODE_FLOAT:
03398 case MODE_DECIMAL_FLOAT:
03399 {
03400 REAL_VALUE_TYPE r;
03401
03402 gcc_assert (GET_CODE (x) == CONST_DOUBLE);
03403 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
03404 assemble_real (r, mode, align);
03405 break;
03406 }
03407
03408 case MODE_INT:
03409 case MODE_PARTIAL_INT:
03410 assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
03411 break;
03412
03413 case MODE_VECTOR_FLOAT:
03414 case MODE_VECTOR_INT:
03415 {
03416 int i, units;
03417 enum machine_mode submode = GET_MODE_INNER (mode);
03418 unsigned int subalign = MIN (align, GET_MODE_BITSIZE (submode));
03419
03420 gcc_assert (GET_CODE (x) == CONST_VECTOR);
03421 units = CONST_VECTOR_NUNITS (x);
03422
03423 for (i = 0; i < units; i++)
03424 {
03425 rtx elt = CONST_VECTOR_ELT (x, i);
03426 output_constant_pool_2 (submode, elt, i ? subalign : align);
03427 }
03428 }
03429 break;
03430
03431 default:
03432 gcc_unreachable ();
03433 }
03434 }
03435
03436
03437
03438
03439 static void
03440 output_constant_pool_1 (struct constant_descriptor_rtx *desc,
03441 unsigned int align)
03442 {
03443 rtx x, tmp;
03444
03445 x = desc->constant;
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456 tmp = x;
03457 switch (GET_CODE (x))
03458 {
03459 case CONST:
03460 if (GET_CODE (XEXP (x, 0)) != PLUS
03461 || GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
03462 break;
03463 tmp = XEXP (XEXP (x, 0), 0);
03464
03465
03466 case LABEL_REF:
03467 tmp = XEXP (x, 0);
03468 gcc_assert (!INSN_DELETED_P (tmp));
03469 gcc_assert (!NOTE_P (tmp)
03470 || NOTE_LINE_NUMBER (tmp) != NOTE_INSN_DELETED);
03471 break;
03472
03473 default:
03474 break;
03475 }
03476
03477 #ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
03478 ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, desc->mode,
03479 align, desc->labelno, done);
03480 #endif
03481
03482 assemble_align (align);
03483
03484
03485 targetm.asm_out.internal_label (asm_out_file, "LC", desc->labelno);
03486
03487
03488 output_constant_pool_2 (desc->mode, x, align);
03489
03490
03491
03492 if (align > GET_MODE_BITSIZE (desc->mode)
03493 && in_section
03494 && (in_section->common.flags & SECTION_MERGE))
03495 assemble_align (align);
03496
03497 #ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
03498 done:
03499 #endif
03500 return;
03501 }
03502
03503
03504
03505
03506
03507 static int
03508 mark_constant (rtx *current_rtx, void *data ATTRIBUTE_UNUSED)
03509 {
03510 rtx x = *current_rtx;
03511
03512 if (x == NULL_RTX || GET_CODE (x) != SYMBOL_REF)
03513 return 0;
03514
03515 if (CONSTANT_POOL_ADDRESS_P (x))
03516 {
03517 struct constant_descriptor_rtx *desc = SYMBOL_REF_CONSTANT (x);
03518 if (desc->mark == 0)
03519 {
03520 desc->mark = 1;
03521 for_each_rtx (&desc->constant, mark_constant, NULL);
03522 }
03523 }
03524 else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
03525 {
03526 tree exp = SYMBOL_REF_DECL (x);
03527 if (!TREE_ASM_WRITTEN (exp))
03528 {
03529 n_deferred_constants--;
03530 output_constant_def_contents (x);
03531 }
03532 }
03533
03534 return -1;
03535 }
03536
03537
03538
03539
03540
03541
03542 static void
03543 mark_constants (rtx insn)
03544 {
03545 if (!INSN_P (insn))
03546 return;
03547
03548
03549
03550
03551 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
03552 {
03553 rtx seq = PATTERN (insn);
03554 int i, n = XVECLEN (seq, 0);
03555 for (i = 0; i < n; ++i)
03556 {
03557 rtx subinsn = XVECEXP (seq, 0, i);
03558 if (INSN_P (subinsn))
03559 for_each_rtx (&PATTERN (subinsn), mark_constant, NULL);
03560 }
03561 }
03562 else
03563 for_each_rtx (&PATTERN (insn), mark_constant, NULL);
03564 }
03565
03566
03567
03568
03569
03570 static void
03571 mark_constant_pool (void)
03572 {
03573 rtx insn, link;
03574
03575 if (!current_function_uses_const_pool && n_deferred_constants == 0)
03576 return;
03577
03578 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
03579 mark_constants (insn);
03580
03581 for (link = current_function_epilogue_delay_list;
03582 link;
03583 link = XEXP (link, 1))
03584 mark_constants (XEXP (link, 0));
03585 }
03586
03587
03588
03589 static void
03590 output_constant_pool_contents (struct rtx_constant_pool *pool)
03591 {
03592 struct constant_descriptor_rtx *desc;
03593
03594 for (desc = pool->first; desc ; desc = desc->next)
03595 if (desc->mark)
03596 {
03597
03598
03599
03600
03601 if (SYMBOL_REF_HAS_BLOCK_INFO_P (desc->sym)
03602 && SYMBOL_REF_BLOCK (desc->sym))
03603 place_block_symbol (desc->sym);
03604 else
03605 {
03606 switch_to_section (targetm.asm_out.select_rtx_section
03607 (desc->mode, desc->constant, desc->align));
03608 output_constant_pool_1 (desc, desc->align);
03609 }
03610 }
03611 }
03612
03613
03614
03615
03616 static void
03617 output_constant_pool (const char *fnname ATTRIBUTE_UNUSED,
03618 tree fndecl ATTRIBUTE_UNUSED)
03619 {
03620 struct rtx_constant_pool *pool = cfun->varasm->pool;
03621
03622
03623
03624
03625 mark_constant_pool ();
03626
03627 #ifdef ASM_OUTPUT_POOL_PROLOGUE
03628 ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool->offset);
03629 #endif
03630
03631 output_constant_pool_contents (pool);
03632
03633 #ifdef ASM_OUTPUT_POOL_EPILOGUE
03634 ASM_OUTPUT_POOL_EPILOGUE (asm_out_file, fnname, fndecl, pool->offset);
03635 #endif
03636 }
03637
03638
03639
03640 void
03641 output_shared_constant_pool (void)
03642 {
03643 output_constant_pool_contents (shared_constant_pool);
03644 }
03645
03646
03647
03648 int
03649 compute_reloc_for_constant (tree exp)
03650 {
03651 int reloc = 0, reloc2;
03652 tree tem;
03653
03654
03655
03656 exp = lang_hooks.expand_constant (exp);
03657
03658 switch (TREE_CODE (exp))
03659 {
03660 case ADDR_EXPR:
03661 case FDESC_EXPR:
03662
03663
03664
03665 for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
03666 tem = TREE_OPERAND (tem, 0))
03667 ;
03668
03669 if (TREE_PUBLIC (tem))
03670 reloc |= 2;
03671 else
03672 reloc |= 1;
03673 break;
03674
03675 case PLUS_EXPR:
03676 reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
03677 reloc |= compute_reloc_for_constant (TREE_OPERAND (exp, 1));
03678 break;
03679
03680 case MINUS_EXPR:
03681 reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
03682 reloc2 = compute_reloc_for_constant (TREE_OPERAND (exp, 1));
03683
03684 if (reloc == 1 && reloc2 == 1)
03685 reloc = 0;
03686 else
03687 reloc |= reloc2;
03688 break;
03689
03690 case NOP_EXPR:
03691 case CONVERT_EXPR:
03692 case NON_LVALUE_EXPR:
03693 case VIEW_CONVERT_EXPR:
03694 reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
03695 break;
03696
03697 case CONSTRUCTOR:
03698 {
03699 unsigned HOST_WIDE_INT idx;
03700 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, tem)
03701 if (tem != 0)
03702 reloc |= compute_reloc_for_constant (tem);
03703 }
03704 break;
03705
03706 default:
03707 break;
03708 }
03709 return reloc;
03710 }
03711
03712
03713
03714
03715
03716 static void
03717 output_addressed_constants (tree exp)
03718 {
03719 tree tem;
03720
03721
03722
03723 exp = lang_hooks.expand_constant (exp);
03724
03725 switch (TREE_CODE (exp))
03726 {
03727 case ADDR_EXPR:
03728 case FDESC_EXPR:
03729
03730
03731
03732 for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
03733 tem = TREE_OPERAND (tem, 0))
03734 ;
03735
03736
03737 if (TREE_CODE (tem) == CONST_DECL && DECL_INITIAL (tem))
03738 tem = DECL_INITIAL (tem);
03739
03740 if (CONSTANT_CLASS_P (tem) || TREE_CODE (tem) == CONSTRUCTOR)
03741 output_constant_def (tem, 0);
03742 break;
03743
03744 case PLUS_EXPR:
03745 case MINUS_EXPR:
03746 output_addressed_constants (TREE_OPERAND (exp, 1));
03747
03748
03749 case NOP_EXPR:
03750 case CONVERT_EXPR:
03751 case NON_LVALUE_EXPR:
03752 case VIEW_CONVERT_EXPR:
03753 output_addressed_constants (TREE_OPERAND (exp, 0));
03754 break;
03755
03756 case CONSTRUCTOR:
03757 {
03758 unsigned HOST_WIDE_INT idx;
03759 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, tem)
03760 if (tem != 0)
03761 output_addressed_constants (tem);
03762 }
03763 break;
03764
03765 default:
03766 break;
03767 }
03768 }
03769
03770
03771
03772
03773
03774
03775 bool
03776 constructor_static_from_elts_p (tree ctor)
03777 {
03778 return (TREE_CONSTANT (ctor)
03779 && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE
03780 || TREE_CODE (TREE_TYPE (ctor)) == RECORD_TYPE)
03781 && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
03782 }
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794 tree
03795 initializer_constant_valid_p (tree value, tree endtype)
03796 {
03797
03798
03799 value = lang_hooks.expand_constant (value);
03800
03801 switch (TREE_CODE (value))
03802 {
03803 case CONSTRUCTOR:
03804 if (constructor_static_from_elts_p (value))
03805 {
03806 unsigned HOST_WIDE_INT idx;
03807 tree elt;
03808 bool absolute = true;
03809
03810 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
03811 {
03812 tree reloc;
03813 reloc = initializer_constant_valid_p (elt, TREE_TYPE (elt));
03814 if (!reloc)
03815 return NULL_TREE;
03816 if (reloc != null_pointer_node)
03817 absolute = false;
03818 }
03819
03820
03821
03822 return absolute ? null_pointer_node : error_mark_node;
03823 }
03824
03825 return TREE_STATIC (value) ? null_pointer_node : NULL_TREE;
03826
03827 case INTEGER_CST:
03828 case VECTOR_CST:
03829 case REAL_CST:
03830 case STRING_CST:
03831 case COMPLEX_CST:
03832 return null_pointer_node;
03833
03834 case ADDR_EXPR:
03835 case FDESC_EXPR:
03836 value = staticp (TREE_OPERAND (value, 0));
03837 if (value)
03838 {
03839
03840
03841 if (TREE_CODE (value) == INDIRECT_REF
03842 && TREE_CONSTANT (TREE_OPERAND (value, 0)))
03843 return null_pointer_node;
03844
03845 if (TREE_CODE (value) == FUNCTION_DECL
03846 && ((decl_function_context (value)
03847 && !DECL_NO_STATIC_CHAIN (value))
03848 || DECL_DLLIMPORT_P (value)))
03849 return NULL_TREE;
03850
03851
03852 if (TREE_CODE (value) == CONSTRUCTOR)
03853 return NULL_TREE;
03854 }
03855 return value;
03856
03857 case VIEW_CONVERT_EXPR:
03858 case NON_LVALUE_EXPR:
03859 return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
03860
03861 case CONVERT_EXPR:
03862 case NOP_EXPR:
03863 {
03864 tree src;
03865 tree src_type;
03866 tree dest_type;
03867
03868 src = TREE_OPERAND (value, 0);
03869 src_type = TREE_TYPE (src);
03870 dest_type = TREE_TYPE (value);
03871
03872
03873
03874 if ((POINTER_TYPE_P (dest_type) && POINTER_TYPE_P (src_type))
03875 || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type))
03876 || (TREE_CODE (dest_type) == OFFSET_TYPE
03877 && TREE_CODE (src_type) == OFFSET_TYPE))
03878 return initializer_constant_valid_p (src, endtype);
03879
03880
03881 if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)
03882 && (TYPE_PRECISION (dest_type) == TYPE_PRECISION (src_type)))
03883 return initializer_constant_valid_p (src, endtype);
03884
03885
03886
03887 if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type))
03888 {
03889 tree inner = initializer_constant_valid_p (src, endtype);
03890 if (inner == null_pointer_node)
03891 return null_pointer_node;
03892 break;
03893 }
03894
03895
03896 if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)
03897 && (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type)))
03898 return initializer_constant_valid_p (src, endtype);
03899
03900
03901
03902 if ((POINTER_TYPE_P (dest_type)
03903 || TREE_CODE (dest_type) == OFFSET_TYPE)
03904 && INTEGRAL_TYPE_P (src_type))
03905 {
03906 if (TREE_CODE (src) == INTEGER_CST
03907 && TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type))
03908 return null_pointer_node;
03909 if (integer_zerop (src))
03910 return null_pointer_node;
03911 else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type))
03912 return initializer_constant_valid_p (src, endtype);
03913 }
03914
03915
03916
03917 if (TREE_CODE (dest_type) == RECORD_TYPE
03918 || TREE_CODE (dest_type) == UNION_TYPE)
03919 return initializer_constant_valid_p (src, endtype);
03920 }
03921 break;
03922
03923 case PLUS_EXPR:
03924 if (! INTEGRAL_TYPE_P (endtype)
03925 || TYPE_PRECISION (endtype) >= POINTER_SIZE)
03926 {
03927 tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
03928 endtype);
03929 tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
03930 endtype);
03931
03932 if (valid0 == null_pointer_node)
03933 return valid1;
03934 if (valid1 == null_pointer_node)
03935 return valid0;
03936 }
03937 break;
03938
03939 case MINUS_EXPR:
03940 if (! INTEGRAL_TYPE_P (endtype)
03941 || TYPE_PRECISION (endtype) >= POINTER_SIZE)
03942 {
03943 tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
03944 endtype);
03945 tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
03946 endtype);
03947
03948 if (valid1 == null_pointer_node)
03949 return valid0;
03950
03951
03952 if (valid0 == valid1 && valid0 != 0)
03953 return null_pointer_node;
03954
03955
03956
03957
03958 if (valid0 && TREE_CODE (valid0) == STRING_CST
03959 && valid1 && TREE_CODE (valid1) == STRING_CST
03960 && operand_equal_p (valid0, valid1, 1))
03961 return null_pointer_node;
03962 }
03963
03964
03965 if (INTEGRAL_TYPE_P (endtype))
03966 {
03967 tree op0, op1;
03968
03969 op0 = TREE_OPERAND (value, 0);
03970 op1 = TREE_OPERAND (value, 1);
03971
03972
03973
03974
03975
03976
03977 while (TREE_CODE (op0) == NOP_EXPR
03978 || TREE_CODE (op0) == CONVERT_EXPR
03979 || TREE_CODE (op0) == NON_LVALUE_EXPR)
03980 {
03981 tree inner = TREE_OPERAND (op0, 0);
03982 if (inner == error_mark_node
03983 || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
03984 || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
03985 > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
03986 break;
03987 op0 = inner;
03988 }
03989
03990 while (TREE_CODE (op1) == NOP_EXPR
03991 || TREE_CODE (op1) == CONVERT_EXPR
03992 || TREE_CODE (op1) == NON_LVALUE_EXPR)
03993 {
03994 tree inner = TREE_OPERAND (op1, 0);
03995 if (inner == error_mark_node
03996 || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
03997 || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
03998 > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
03999 break;
04000 op1 = inner;
04001 }
04002
04003 op0 = initializer_constant_valid_p (op0, endtype);
04004 op1 = initializer_constant_valid_p (op1, endtype);
04005
04006
04007 if (op0 && op1)
04008 {
04009 if (op0 == op1)
04010 return null_pointer_node;
04011
04012
04013 if (TREE_CODE (op0) == LABEL_DECL
04014 && TREE_CODE (op1) == LABEL_DECL)
04015 return null_pointer_node;
04016
04017 if (TREE_CODE (op0) == STRING_CST
04018 && TREE_CODE (op1) == STRING_CST
04019 && operand_equal_p (op0, op1, 1))
04020 return null_pointer_node;
04021 }
04022 }
04023 break;
04024
04025 default:
04026 break;
04027 }
04028
04029 return 0;
04030 }
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047
04048
04049
04050
04051
04052 void
04053 output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
04054 {
04055 enum tree_code code;
04056 unsigned HOST_WIDE_INT thissize;
04057
04058
04059
04060
04061 exp = lang_hooks.expand_constant (exp);
04062
04063 if (size == 0 || flag_syntax_only)
04064 return;
04065
04066
04067
04068
04069
04070 if (TREE_CODE (exp) == NOP_EXPR
04071 && POINTER_TYPE_P (TREE_TYPE (exp))
04072 && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
04073 {
04074 tree saved_type = TREE_TYPE (exp);
04075
04076
04077
04078 while (TREE_CODE (exp) == NOP_EXPR
04079 && POINTER_TYPE_P (TREE_TYPE (exp))
04080 && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
04081 exp = TREE_OPERAND (exp, 0);
04082
04083
04084
04085
04086 if (TREE_CODE (exp) == ADDR_EXPR)
04087 exp = build1 (ADDR_EXPR, saved_type, TREE_OPERAND (exp, 0));
04088
04089 else if (TREE_CODE (exp) == INTEGER_CST)
04090 exp = build_int_cst_wide (saved_type, TREE_INT_CST_LOW (exp),
04091 TREE_INT_CST_HIGH (exp));
04092
04093 }
04094
04095
04096
04097 while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
04098 || TREE_CODE (exp) == NON_LVALUE_EXPR
04099 || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
04100 {
04101 HOST_WIDE_INT type_size = int_size_in_bytes (TREE_TYPE (exp));
04102 HOST_WIDE_INT op_size = int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0)));
04103
04104
04105
04106
04107 if (type_size > op_size
04108 && TREE_CODE (exp) != VIEW_CONVERT_EXPR
04109 && TREE_CODE (TREE_TYPE (exp)) != UNION_TYPE)
04110
04111 break;
04112 else
04113 exp = TREE_OPERAND (exp, 0);
04114 }
04115
04116 code = TREE_CODE (TREE_TYPE (exp));
04117 thissize = int_size_in_bytes (TREE_TYPE (exp));
04118
04119
04120 exp = lang_hooks.expand_constant (exp);
04121
04122
04123
04124 if (TREE_CODE (exp) == CONSTRUCTOR
04125 && VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (exp)))
04126 {
04127 assemble_zeros (size);
04128 return;
04129 }
04130
04131 if (TREE_CODE (exp) == FDESC_EXPR)
04132 {
04133 #ifdef ASM_OUTPUT_FDESC
04134 HOST_WIDE_INT part = tree_low_cst (TREE_OPERAND (exp, 1), 0);
04135 tree decl = TREE_OPERAND (exp, 0);
04136 ASM_OUTPUT_FDESC (asm_out_file, decl, part);
04137 #else
04138 gcc_unreachable ();
04139 #endif
04140 return;
04141 }
04142
04143
04144
04145 switch (code)
04146 {
04147 case BOOLEAN_TYPE:
04148 case INTEGER_TYPE:
04149 case ENUMERAL_TYPE:
04150 case POINTER_TYPE:
04151 case REFERENCE_TYPE:
04152 case OFFSET_TYPE:
04153 if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
04154 EXPAND_INITIALIZER),
04155 MIN (size, thissize), align, 0))
04156 error ("initializer for integer value is too complicated");
04157 break;
04158
04159 case REAL_TYPE:
04160 if (TREE_CODE (exp) != REAL_CST)
04161 error ("initializer for floating value is not a floating constant");
04162
04163 #ifdef KEY
04164 if (!flag_spin_file)
04165 #endif
04166 assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
04167 break;
04168
04169 case COMPLEX_TYPE:
04170 #ifdef KEY
04171 if (!flag_spin_file)
04172 #endif
04173 {
04174 output_constant (TREE_REALPART (exp), thissize / 2, align);
04175 output_constant (TREE_IMAGPART (exp), thissize / 2,
04176 min_align (align, BITS_PER_UNIT * (thissize / 2)));
04177 }
04178 break;
04179
04180 case ARRAY_TYPE:
04181 case VECTOR_TYPE:
04182 switch (TREE_CODE (exp))
04183 {
04184 case CONSTRUCTOR:
04185 output_constructor (exp, size, align);
04186 return;
04187 case STRING_CST:
04188 #ifdef KEY
04189 if (!flag_spin_file)
04190 #endif
04191 {
04192 thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
04193 size);
04194 assemble_string (TREE_STRING_POINTER (exp), thissize);
04195 }
04196 break;
04197
04198 case VECTOR_CST:
04199 {
04200 int elt_size;
04201 tree link;
04202 unsigned int nalign;
04203 enum machine_mode inner;
04204
04205 inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
04206 nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
04207
04208 elt_size = GET_MODE_SIZE (inner);
04209
04210 link = TREE_VECTOR_CST_ELTS (exp);
04211 output_constant (TREE_VALUE (link), elt_size, align);
04212 thissize = elt_size;
04213 while ((link = TREE_CHAIN (link)) != NULL)
04214 {
04215 output_constant (TREE_VALUE (link), elt_size, nalign);
04216 thissize += elt_size;
04217 }
04218 break;
04219 }
04220 default:
04221 gcc_unreachable ();
04222 }
04223 break;
04224
04225 case RECORD_TYPE:
04226 case UNION_TYPE:
04227 gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
04228 output_constructor (exp, size, align);
04229 return;
04230
04231 case ERROR_MARK:
04232 return;
04233
04234 default:
04235 gcc_unreachable ();
04236 }
04237
04238 if (size > thissize)
04239 assemble_zeros (size - thissize);
04240 }
04241
04242
04243
04244
04245
04246
04247 static unsigned HOST_WIDE_INT
04248 array_size_for_constructor (tree val)
04249 {
04250 tree max_index, i;
04251 unsigned HOST_WIDE_INT cnt;
04252 tree index, value, tmp;
04253
04254
04255
04256
04257 if (TREE_CODE (val) == STRING_CST)
04258 return TREE_STRING_LENGTH (val);
04259
04260 max_index = NULL_TREE;
04261 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (val), cnt, index, value)
04262 {
04263 if (TREE_CODE (index) == RANGE_EXPR)
04264 index = TREE_OPERAND (index, 1);
04265 if (max_index == NULL_TREE || tree_int_cst_lt (max_index, index))
04266 max_index = index;
04267 }
04268
04269 if (max_index == NULL_TREE)
04270 return 0;
04271
04272
04273 tmp = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)));
04274 i = size_binop (MINUS_EXPR, fold_convert (sizetype, max_index),
04275 fold_convert (sizetype, tmp));
04276 i = size_binop (PLUS_EXPR, i, build_int_cst (sizetype, 1));
04277
04278
04279 i = size_binop (MULT_EXPR, i, TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
04280
04281 return tree_low_cst (i, 1);
04282 }
04283
04284
04285
04286
04287 static void
04288 output_constructor (tree exp, unsigned HOST_WIDE_INT size,
04289 unsigned int align)
04290 {
04291 tree type = TREE_TYPE (exp);
04292 tree field = 0;
04293 tree min_index = 0;
04294
04295
04296 HOST_WIDE_INT total_bytes = 0;
04297
04298 int byte_buffer_in_use = 0;
04299 int byte = 0;
04300 unsigned HOST_WIDE_INT cnt;
04301 constructor_elt *ce;
04302
04303 gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
04304
04305 if (TREE_CODE (type) == RECORD_TYPE)
04306 field = TYPE_FIELDS (type);
04307
04308 if (TREE_CODE (type) == ARRAY_TYPE
04309 && TYPE_DOMAIN (type) != 0)
04310 min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321 for (cnt = 0;
04322 VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce);
04323 cnt++, field = field ? TREE_CHAIN (field) : 0)
04324 {
04325 tree val = ce->value;
04326 tree index = 0;
04327
04328
04329
04330 if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
04331 || TREE_CODE (type) == QUAL_UNION_TYPE)
04332 && ce->index != 0)
04333 field = ce->index;
04334
04335 else if (TREE_CODE (type) == ARRAY_TYPE)
04336 index = ce->index;
04337
04338 #ifdef ASM_COMMENT_START
04339 if (field && flag_verbose_asm)
04340 fprintf (asm_out_file, "%s %s:\n",
04341 ASM_COMMENT_START,
04342 DECL_NAME (field)
04343 ? IDENTIFIER_POINTER (DECL_NAME (field))
04344 : "<anonymous>");
04345 #endif
04346
04347
04348 if (val != 0)
04349 STRIP_NOPS (val);
04350
04351 if (index && TREE_CODE (index) == RANGE_EXPR)
04352 {
04353 unsigned HOST_WIDE_INT fieldsize
04354 = int_size_in_bytes (TREE_TYPE (type));
04355 HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
04356 HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
04357 HOST_WIDE_INT index;
04358 unsigned int align2 = min_align (align, fieldsize * BITS_PER_UNIT);
04359
04360 for (index = lo_index; index <= hi_index; index++)
04361 {
04362
04363 if (val == 0)
04364 assemble_zeros (fieldsize);
04365 else
04366 output_constant (val, fieldsize, align2);
04367
04368
04369 total_bytes += fieldsize;
04370 }
04371 }
04372 else if (field == 0 || !DECL_BIT_FIELD (field))
04373 {
04374
04375
04376 unsigned HOST_WIDE_INT fieldsize;
04377
04378
04379 HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
04380 unsigned int align2;
04381
04382 if (index != 0)
04383 pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
04384 * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
04385
04386
04387 if (byte_buffer_in_use)
04388 {
04389 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
04390 total_bytes++;
04391 byte_buffer_in_use = 0;
04392 }
04393
04394
04395
04396
04397 if ((field != 0 || index != 0) && pos != total_bytes)
04398 {
04399 gcc_assert (pos >= total_bytes);
04400 assemble_zeros (pos - total_bytes);
04401 total_bytes = pos;
04402 }
04403
04404
04405 align2 = min_align (align, BITS_PER_UNIT * pos);
04406
04407
04408 if (field)
04409 {
04410 fieldsize = 0;
04411
04412
04413
04414
04415
04416
04417 if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
04418 && TYPE_DOMAIN (TREE_TYPE (field))
04419 && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
04420 {
04421 fieldsize = array_size_for_constructor (val);
04422
04423
04424 gcc_assert (!fieldsize || !TREE_CHAIN (field));
04425 }
04426 else if (DECL_SIZE_UNIT (field))
04427 {
04428
04429
04430 if (host_integerp (DECL_SIZE_UNIT (field), 1))
04431 fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
04432 }
04433 }
04434 else
04435 fieldsize = int_size_in_bytes (TREE_TYPE (type));
04436
04437
04438 if (val == 0)
04439 assemble_zeros (fieldsize);
04440 else
04441 output_constant (val, fieldsize, align2);
04442
04443
04444 total_bytes += fieldsize;
04445 }
04446 else if (val != 0 && TREE_CODE (val) != INTEGER_CST)
04447 error ("invalid initial value for member %qs",
04448 IDENTIFIER_POINTER (DECL_NAME (field)));
04449 else
04450 {
04451
04452
04453 HOST_WIDE_INT next_offset = int_bit_position (field);
04454 HOST_WIDE_INT end_offset
04455 = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
04456
04457 if (val == 0)
04458 val = integer_zero_node;
04459
04460
04461
04462 if (next_offset / BITS_PER_UNIT != total_bytes)
04463 {
04464
04465 if (byte_buffer_in_use)
04466 {
04467 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
04468 total_bytes++;
04469 byte_buffer_in_use = 0;
04470 }
04471
04472
04473 if (next_offset / BITS_PER_UNIT != total_bytes)
04474 {
04475 gcc_assert (next_offset / BITS_PER_UNIT >= total_bytes);
04476 assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);
04477 total_bytes = next_offset / BITS_PER_UNIT;
04478 }
04479 }
04480
04481 if (! byte_buffer_in_use)
04482 byte = 0;
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492 while (next_offset < end_offset)
04493 {
04494 int this_time;
04495 int shift;
04496 HOST_WIDE_INT value;
04497 HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
04498 HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
04499
04500
04501
04502 while (next_byte != total_bytes)
04503 {
04504 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
04505 total_bytes++;
04506 byte = 0;
04507 }
04508
04509
04510
04511 this_time = MIN (end_offset - next_offset,
04512 BITS_PER_UNIT - next_bit);
04513 if (BYTES_BIG_ENDIAN)
04514 {
04515
04516
04517
04518 shift = end_offset - next_offset - this_time;
04519
04520
04521
04522
04523
04524 if (shift < HOST_BITS_PER_WIDE_INT
04525 && shift + this_time > HOST_BITS_PER_WIDE_INT)
04526 {
04527 this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
04528 shift = HOST_BITS_PER_WIDE_INT;
04529 }
04530
04531
04532 if (shift < HOST_BITS_PER_WIDE_INT)
04533 value = TREE_INT_CST_LOW (val);
04534 else
04535 {
04536 gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
04537 value = TREE_INT_CST_HIGH (val);
04538 shift -= HOST_BITS_PER_WIDE_INT;
04539 }
04540
04541
04542
04543 byte |= (((value >> shift)
04544 & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
04545 << (BITS_PER_UNIT - this_time - next_bit));
04546 }
04547 else
04548 {
04549
04550
04551
04552
04553 shift = next_offset - int_bit_position (field);
04554
04555
04556
04557
04558
04559 if (shift < HOST_BITS_PER_WIDE_INT
04560 && shift + this_time > HOST_BITS_PER_WIDE_INT)
04561 this_time = (HOST_BITS_PER_WIDE_INT - shift);
04562
04563
04564 if (shift < HOST_BITS_PER_WIDE_INT)
04565 value = TREE_INT_CST_LOW (val);
04566 else
04567 {
04568 gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
04569 value = TREE_INT_CST_HIGH (val);
04570 shift -= HOST_BITS_PER_WIDE_INT;
04571 }
04572
04573
04574
04575 byte |= (((value >> shift)
04576 & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
04577 << next_bit);
04578 }
04579
04580 next_offset += this_time;
04581 byte_buffer_in_use = 1;
04582 }
04583 }
04584 }
04585
04586 if (byte_buffer_in_use)
04587 {
04588 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
04589 total_bytes++;
04590 }
04591
04592 if ((unsigned HOST_WIDE_INT)total_bytes < size)
04593 assemble_zeros (size - total_bytes);
04594 }
04595
04596
04597
04598 static GTY(()) tree weak_decls;
04599
04600
04601
04602 static void
04603 mark_weak (tree decl)
04604 {
04605 DECL_WEAK (decl) = 1;
04606
04607 if (DECL_RTL_SET_P (decl)
04608 && MEM_P (DECL_RTL (decl))
04609 && XEXP (DECL_RTL (decl), 0)
04610 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
04611 SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = 1;
04612 }
04613
04614
04615
04616 void
04617 merge_weak (tree newdecl, tree olddecl)
04618 {
04619 if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl))
04620 {
04621 if (DECL_WEAK (newdecl) && SUPPORTS_WEAK)
04622 {
04623 tree *pwd;
04624
04625
04626 for (pwd = &weak_decls; *pwd; pwd = &TREE_CHAIN (*pwd))
04627 if (TREE_VALUE (*pwd) == newdecl)
04628 {
04629 *pwd = TREE_CHAIN (*pwd);
04630 break;
04631 }
04632 }
04633 return;
04634 }
04635
04636 if (DECL_WEAK (newdecl))
04637 {
04638 tree wd;
04639
04640
04641
04642
04643
04644
04645
04646 if (TREE_ASM_WRITTEN (olddecl))
04647 error ("weak declaration of %q+D must precede definition",
04648 newdecl);
04649
04650
04651
04652
04653 else if (TREE_USED (olddecl)
04654 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (olddecl)))
04655 warning (0, "weak declaration of %q+D after first use results "
04656 "in unspecified behavior", newdecl);
04657
04658 if (SUPPORTS_WEAK)
04659 {
04660
04661
04662 for (wd = weak_decls; wd; wd = TREE_CHAIN (wd))
04663 if (TREE_VALUE (wd) == newdecl)
04664 {
04665 TREE_VALUE (wd) = olddecl;
04666 break;
04667 }
04668
04669
04670
04671
04672 }
04673
04674
04675 mark_weak (olddecl);
04676 }
04677 else
04678
04679
04680 mark_weak (newdecl);
04681 }
04682
04683
04684
04685 void
04686 declare_weak (tree decl)
04687 {
04688 if (! TREE_PUBLIC (decl))
04689 error ("weak declaration of %q+D must be public", decl);
04690 else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
04691 error ("weak declaration of %q+D must precede definition", decl);
04692 else if (SUPPORTS_WEAK)
04693 {
04694 if (! DECL_WEAK (decl))
04695 weak_decls = tree_cons (NULL, decl, weak_decls);
04696 }
04697 else
04698 warning (0, "weak declaration of %q+D not supported", decl);
04699
04700 mark_weak (decl);
04701 }
04702
04703 static void
04704 weak_finish_1 (tree decl)
04705 {
04706 #if defined (ASM_WEAKEN_DECL) || defined (ASM_WEAKEN_LABEL)
04707 const char *const name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
04708 #endif
04709
04710 if (! TREE_USED (decl))
04711 return;
04712
04713 #ifdef ASM_WEAKEN_DECL
04714 ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL);
04715 #else
04716 #ifdef ASM_WEAKEN_LABEL
04717 ASM_WEAKEN_LABEL (asm_out_file, name);
04718 #else
04719 #ifdef ASM_OUTPUT_WEAK_ALIAS
04720 {
04721 static bool warn_once = 0;
04722 if (! warn_once)
04723 {
04724 warning (0, "only weak aliases are supported in this configuration");
04725 warn_once = 1;
04726 }
04727 return;
04728 }
04729 #endif
04730 #endif
04731 #endif
04732 }
04733
04734
04735
04736 static GTY(()) tree weakref_targets;
04737
04738
04739 static tree find_decl_and_mark_needed (tree decl, tree target);
04740
04741
04742
04743 void
04744 weak_finish (void)
04745 {
04746 tree t;
04747
04748 for (t = weakref_targets; t; t = TREE_CHAIN (t))
04749 {
04750 tree alias_decl = TREE_PURPOSE (t);
04751 tree target = ultimate_transparent_alias_target (&TREE_VALUE (t));
04752
04753 if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias_decl)))
04754
04755
04756 target = NULL_TREE;
04757 #ifndef ASM_OUTPUT_WEAKREF
04758 else if (! TREE_SYMBOL_REFERENCED (target))
04759 {
04760
04761
04762
04763 # if defined ASM_WEAKEN_LABEL && ! defined ASM_WEAKEN_DECL
04764 ASM_WEAKEN_LABEL (asm_out_file, IDENTIFIER_POINTER (target));
04765 # else
04766 tree decl = find_decl_and_mark_needed (alias_decl, target);
04767
04768 if (! decl)
04769 {
04770 decl = build_decl (TREE_CODE (alias_decl), target,
04771 TREE_TYPE (alias_decl));
04772
04773 DECL_EXTERNAL (decl) = 1;
04774 TREE_PUBLIC (decl) = 1;
04775 DECL_ARTIFICIAL (decl) = 1;
04776 TREE_NOTHROW (decl) = TREE_NOTHROW (alias_decl);
04777 TREE_USED (decl) = 1;
04778 }
04779
04780 weak_finish_1 (decl);
04781 # endif
04782 }
04783 #endif
04784
04785 {
04786 tree *p;
04787 tree t2;
04788
04789
04790
04791
04792 for (p = &weak_decls; (t2 = *p) ; )
04793 {
04794 if (TREE_VALUE (t2) == alias_decl
04795 || target == DECL_ASSEMBLER_NAME (TREE_VALUE (t2)))
04796 *p = TREE_CHAIN (t2);
04797 else
04798 p = &TREE_CHAIN (t2);
04799 }
04800
04801
04802 for (p = &TREE_CHAIN (t); (t2 = *p) ; )
04803 {
04804 if (target == ultimate_transparent_alias_target (&TREE_VALUE (t2)))
04805 *p = TREE_CHAIN (t2);
04806 else
04807 p = &TREE_CHAIN (t2);
04808 }
04809 }
04810 }
04811
04812 for (t = weak_decls; t; t = TREE_CHAIN (t))
04813 {
04814 tree decl = TREE_VALUE (t);
04815
04816 weak_finish_1 (decl);
04817 }
04818 }
04819
04820
04821
04822 static void
04823 globalize_decl (tree decl)
04824 {
04825 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
04826
04827 #if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
04828 if (DECL_WEAK (decl))
04829 {
04830 tree *p, t;
04831
04832 #ifdef ASM_WEAKEN_DECL
04833 ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
04834 #else
04835 ASM_WEAKEN_LABEL (asm_out_file, name);
04836 #endif
04837
04838
04839
04840 for (p = &weak_decls; (t = *p) ; )
04841 {
04842 if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
04843 *p = TREE_CHAIN (t);
04844 else
04845 p = &TREE_CHAIN (t);
04846 }
04847
04848
04849
04850 for (p = &weakref_targets; (t = *p) ; )
04851 {
04852 if (DECL_ASSEMBLER_NAME (decl)
04853 == ultimate_transparent_alias_target (&TREE_VALUE (t)))
04854 *p = TREE_CHAIN (t);
04855 else
04856 p = &TREE_CHAIN (t);
04857 }
04858
04859 return;
04860 }
04861 #elif defined(ASM_MAKE_LABEL_LINKONCE)
04862 if (DECL_ONE_ONLY (decl))
04863 ASM_MAKE_LABEL_LINKONCE (asm_out_file, name);
04864 #endif
04865
04866 targetm.asm_out.globalize_label (asm_out_file, name);
04867 }
04868
04869
04870
04871
04872
04873 typedef struct alias_pair GTY(())
04874 {
04875 tree decl;
04876 tree target;
04877 } alias_pair;
04878
04879
04880 DEF_VEC_O(alias_pair);
04881 DEF_VEC_ALLOC_O(alias_pair,gc);
04882
04883 static GTY(()) VEC(alias_pair,gc) *alias_pairs;
04884
04885
04886
04887
04888 static tree
04889 find_decl_and_mark_needed (tree decl, tree target)
04890 {
04891 struct cgraph_node *fnode = NULL;
04892 struct cgraph_varpool_node *vnode = NULL;
04893
04894 if (TREE_CODE (decl) == FUNCTION_DECL)
04895 {
04896 fnode = cgraph_node_for_asm (target);
04897 if (fnode == NULL)
04898 vnode = cgraph_varpool_node_for_asm (target);
04899 }
04900 else
04901 {
04902 vnode = cgraph_varpool_node_for_asm (target);
04903 if (vnode == NULL)
04904 fnode = cgraph_node_for_asm (target);
04905 }
04906
04907 if (fnode)
04908 {
04909
04910
04911
04912
04913
04914 if (! cgraph_global_info_ready)
04915 cgraph_mark_needed_node (fnode);
04916 return fnode->decl;
04917 }
04918 else if (vnode)
04919 {
04920 cgraph_varpool_mark_needed_node (vnode);
04921 return vnode->decl;
04922 }
04923 else
04924 return NULL_TREE;
04925 }
04926
04927
04928
04929
04930
04931 static void
04932 do_assemble_alias (tree decl, tree target)
04933 {
04934 if (TREE_ASM_WRITTEN (decl))
04935 return;
04936
04937 TREE_ASM_WRITTEN (decl) = 1;
04938 TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
04939
04940 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
04941 {
04942 ultimate_transparent_alias_target (&target);
04943
04944 if (!TREE_SYMBOL_REFERENCED (target))
04945 weakref_targets = tree_cons (decl, target, weakref_targets);
04946
04947 #ifdef ASM_OUTPUT_WEAKREF
04948 ASM_OUTPUT_WEAKREF (asm_out_file, decl,
04949 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
04950 IDENTIFIER_POINTER (target));
04951 #else
04952 if (!SUPPORTS_WEAK)
04953 {
04954 error ("%Jweakref is not supported in this configuration", decl);
04955 return;
04956 }
04957 #endif
04958 return;
04959 }
04960
04961 #ifdef ASM_OUTPUT_DEF
04962
04963
04964 if (TREE_PUBLIC (decl))
04965 {
04966 globalize_decl (decl);
04967 maybe_assemble_visibility (decl);
04968 }
04969
04970 # ifdef ASM_OUTPUT_DEF_FROM_DECLS
04971 ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target);
04972 # else
04973 ASM_OUTPUT_DEF (asm_out_file,
04974 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
04975 IDENTIFIER_POINTER (target));
04976 # endif
04977 #elif defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
04978 {
04979 const char *name;
04980 tree *p, t;
04981
04982 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
04983 # ifdef ASM_WEAKEN_DECL
04984 ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
04985 # else
04986 ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
04987 # endif
04988
04989
04990 for (p = &weak_decls; (t = *p) ; )
04991 if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
04992 *p = TREE_CHAIN (t);
04993 else
04994 p = &TREE_CHAIN (t);
04995
04996
04997
04998 for (p = &weakref_targets; (t = *p) ; )
04999 {
05000 if (DECL_ASSEMBLER_NAME (decl)
05001 == ultimate_transparent_alias_target (&TREE_VALUE (t)))
05002 *p = TREE_CHAIN (t);
05003 else
05004 p = &TREE_CHAIN (t);
05005 }
05006 }
05007 #endif
05008 }
05009
05010
05011
05012
05013 void
05014 finish_aliases_1 (void)
05015 {
05016 unsigned i;
05017 alias_pair *p;
05018
05019 for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
05020 {
05021 tree target_decl;
05022
05023 target_decl = find_decl_and_mark_needed (p->decl, p->target);
05024 if (target_decl == NULL)
05025 {
05026 if (! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
05027 error ("%q+D aliased to undefined symbol %qs",
05028 p->decl, IDENTIFIER_POINTER (p->target));
05029 }
05030 else if (DECL_EXTERNAL (target_decl)
05031 && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
05032 error ("%q+D aliased to external symbol %qs",
05033 p->decl, IDENTIFIER_POINTER (p->target));
05034 #ifdef KEY
05035 if (flag_spin_file && target_decl) {
05036 gs_t gs_decl = gs_x(p->decl);
05037 gs_set_operand(gs_decl, GS_DECL_ALIAS_TARGET, gs_x(target_decl));
05038 }
05039 #endif
05040 }
05041 }
05042
05043
05044
05045
05046
05047 void
05048 finish_aliases_2 (void)
05049 {
05050 unsigned i;
05051 alias_pair *p;
05052
05053 for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
05054 do_assemble_alias (p->decl, p->target);
05055
05056 VEC_truncate (alias_pair, alias_pairs, 0);
05057 }
05058
05059
05060
05061
05062 void
05063 assemble_alias (tree decl, tree target)
05064 {
05065 tree target_decl;
05066 bool is_weakref = false;
05067
05068 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
05069 {
05070 tree alias = DECL_ASSEMBLER_NAME (decl);
05071
05072 is_weakref = true;
05073
05074 ultimate_transparent_alias_target (&target);
05075
05076 if (alias == target)
05077 error ("weakref %q+D ultimately targets itself", decl);
05078 else
05079 {
05080 #ifndef ASM_OUTPUT_WEAKREF
05081 IDENTIFIER_TRANSPARENT_ALIAS (alias) = 1;
05082 TREE_CHAIN (alias) = target;
05083 #endif
05084 }
05085 #ifndef KEY
05086 if (TREE_PUBLIC (decl))
05087 error ("weakref %q+D must have static linkage", decl);
05088 #endif
05089 }
05090 else
05091 {
05092 #if !defined (ASM_OUTPUT_DEF)
05093 # if !defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL)
05094 error ("%Jalias definitions not supported in this configuration", decl);
05095 return;
05096 # else
05097 if (!DECL_WEAK (decl))
05098 {
05099 error ("%Jonly weak aliases are supported in this configuration", decl);
05100 return;
05101 }
05102 # endif
05103 #endif
05104 }
05105
05106
05107
05108 make_decl_rtl (decl);
05109 TREE_USED (decl) = 1;
05110
05111
05112
05113
05114 if (! is_weakref)
05115 DECL_EXTERNAL (decl) = 0;
05116
05117
05118 if (TREE_CODE (decl) == FUNCTION_DECL)
05119 cgraph_node (decl)->alias = true;
05120 else
05121 cgraph_varpool_node (decl)->alias = true;
05122
05123
05124
05125 target_decl = find_decl_and_mark_needed (decl, target);
05126 if (target_decl && TREE_ASM_WRITTEN (target_decl)) {
05127 do_assemble_alias (decl, target);
05128
05129 #ifdef KEY
05130 if (flag_spin_file) {
05131 gs_t gs_decl = gs_x(decl);
05132 gs_set_operand(gs_decl, GS_DECL_ALIAS_TARGET, gs_x(target_decl));
05133 }
05134 #endif
05135 }
05136 else
05137 {
05138 alias_pair *p = VEC_safe_push (alias_pair, gc, alias_pairs, NULL);
05139 p->decl = decl;
05140 p->target = target;
05141 }
05142 }
05143
05144
05145
05146
05147 void
05148 default_assemble_visibility (tree decl, int vis)
05149 {
05150 static const char * const visibility_types[] = {
05151 NULL, "protected", "hidden", "internal"
05152 };
05153
05154 const char *name, *type;
05155
05156 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
05157 type = visibility_types[vis];
05158
05159 #ifdef HAVE_GAS_HIDDEN
05160 fprintf (asm_out_file, "\t.%s\t", type);
05161 assemble_name (asm_out_file, name);
05162 fprintf (asm_out_file, "\n");
05163 #else
05164 warning (OPT_Wattributes, "visibility attribute not supported "
05165 "in this configuration; ignored");
05166 #endif
05167 }
05168
05169
05170
05171 static void
05172 maybe_assemble_visibility (tree decl)
05173 {
05174 enum symbol_visibility vis = DECL_VISIBILITY (decl);
05175
05176 if (vis != VISIBILITY_DEFAULT)
05177 targetm.asm_out.visibility (decl, vis);
05178 }
05179
05180
05181
05182
05183
05184
05185 int
05186 supports_one_only (void)
05187 {
05188 if (SUPPORTS_ONE_ONLY)
05189 return 1;
05190 return SUPPORTS_WEAK;
05191 }
05192
05193
05194
05195
05196 void
05197 make_decl_one_only (tree decl)
05198 {
05199 gcc_assert (TREE_CODE (decl) == VAR_DECL
05200 || TREE_CODE (decl) == FUNCTION_DECL);
05201
05202 TREE_PUBLIC (decl) = 1;
05203
05204 if (SUPPORTS_ONE_ONLY)
05205 {
05206 #ifdef MAKE_DECL_ONE_ONLY
05207 MAKE_DECL_ONE_ONLY (decl);
05208 #ifdef KEY
05209 if (flag_spin_file && gspin_invoked(decl))
05210 gs_set_flag_value (decl, GS_DECL_WEAK, DECL_WEAK(decl));
05211 #endif
05212 #endif
05213 DECL_ONE_ONLY (decl) = 1;
05214 }
05215 else if (TREE_CODE (decl) == VAR_DECL
05216 && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
05217 DECL_COMMON (decl) = 1;
05218 else
05219 {
05220 gcc_assert (SUPPORTS_WEAK);
05221 DECL_WEAK (decl) = 1;
05222 }
05223 }
05224
05225 void
05226 init_varasm_once (void)
05227 {
05228 section_htab = htab_create_ggc (31, section_entry_hash,
05229 section_entry_eq, NULL);
05230 object_block_htab = htab_create_ggc (31, object_block_entry_hash,
05231 object_block_entry_eq, NULL);
05232 const_desc_htab = htab_create_ggc (1009, const_desc_hash,
05233 const_desc_eq, NULL);
05234
05235 const_alias_set = new_alias_set ();
05236 shared_constant_pool = create_constant_pool ();
05237
05238 #ifdef TEXT_SECTION_ASM_OP
05239 text_section = get_unnamed_section (SECTION_CODE, output_section_asm_op,
05240 TEXT_SECTION_ASM_OP);
05241 #endif
05242
05243 #ifdef DATA_SECTION_ASM_OP
05244 data_section = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
05245 DATA_SECTION_ASM_OP);
05246 #endif
05247
05248 #ifdef SDATA_SECTION_ASM_OP
05249 sdata_section = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
05250 SDATA_SECTION_ASM_OP);
05251 #endif
05252
05253 #ifdef READONLY_DATA_SECTION_ASM_OP
05254 readonly_data_section = get_unnamed_section (0, output_section_asm_op,
05255 READONLY_DATA_SECTION_ASM_OP);
05256 #endif
05257
05258 #ifdef CTORS_SECTION_ASM_OP
05259 ctors_section = get_unnamed_section (0, output_section_asm_op,
05260 CTORS_SECTION_ASM_OP);
05261 #endif
05262
05263 #ifdef DTORS_SECTION_ASM_OP
05264 dtors_section = get_unnamed_section (0, output_section_asm_op,
05265 DTORS_SECTION_ASM_OP);
05266 #endif
05267
05268 #ifdef BSS_SECTION_ASM_OP
05269 bss_section = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
05270 output_section_asm_op,
05271 BSS_SECTION_ASM_OP);
05272 #endif
05273
05274 #ifdef SBSS_SECTION_ASM_OP
05275 sbss_section = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
05276 output_section_asm_op,
05277 SBSS_SECTION_ASM_OP);
05278 #endif
05279
05280 tls_comm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS
05281 | SECTION_COMMON, emit_tls_common);
05282 lcomm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS
05283 | SECTION_COMMON, emit_local);
05284 comm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS
05285 | SECTION_COMMON, emit_common);
05286
05287 #if defined ASM_OUTPUT_ALIGNED_BSS || defined ASM_OUTPUT_BSS
05288 bss_noswitch_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS,
05289 emit_bss);
05290 #endif
05291
05292 targetm.asm_out.init_sections ();
05293
05294 if (readonly_data_section == NULL)
05295 readonly_data_section = text_section;
05296 }
05297
05298 enum tls_model
05299 decl_default_tls_model (tree decl)
05300 {
05301 enum tls_model kind;
05302 bool is_local;
05303
05304 is_local = targetm.binds_local_p (decl);
05305 if (!flag_shlib)
05306 {
05307 if (is_local)
05308 kind = TLS_MODEL_LOCAL_EXEC;
05309 else
05310 kind = TLS_MODEL_INITIAL_EXEC;
05311 }
05312
05313
05314
05315 else if (optimize && is_local)
05316 kind = TLS_MODEL_LOCAL_DYNAMIC;
05317 else
05318 kind = TLS_MODEL_GLOBAL_DYNAMIC;
05319 if (kind < flag_tls_default)
05320 kind = flag_tls_default;
05321
05322 return kind;
05323 }
05324
05325
05326
05327
05328
05329
05330
05331
05332 unsigned int
05333 default_section_type_flags (tree decl, const char *name, int reloc)
05334 {
05335 unsigned int flags;
05336
05337 if (decl && TREE_CODE (decl) == FUNCTION_DECL)
05338 flags = SECTION_CODE;
05339 else if (decl && decl_readonly_section (decl, reloc))
05340 flags = 0;
05341 else if (current_function_decl
05342 && cfun
05343 && cfun->unlikely_text_section_name
05344 && strcmp (name, cfun->unlikely_text_section_name) == 0)
05345 flags = SECTION_CODE;
05346 else if (!decl
05347 && (!current_function_decl || !cfun)
05348 && strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
05349 flags = SECTION_CODE;
05350 else
05351 flags = SECTION_WRITE;
05352
05353 if (decl && DECL_ONE_ONLY (decl))
05354 flags |= SECTION_LINKONCE;
05355
05356 if (decl && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
05357 flags |= SECTION_TLS | SECTION_WRITE;
05358
05359 if (strcmp (name, ".bss") == 0
05360 || strncmp (name, ".bss.", 5) == 0
05361 || strncmp (name, ".gnu.linkonce.b.", 16) == 0
05362 || strcmp (name, ".sbss") == 0
05363 || strncmp (name, ".sbss.", 6) == 0
05364 || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
05365 flags |= SECTION_BSS;
05366
05367 if (strcmp (name, ".tdata") == 0
05368 || strncmp (name, ".tdata.", 7) == 0
05369 || strncmp (name, ".gnu.linkonce.td.", 17) == 0)
05370 flags |= SECTION_TLS;
05371
05372 if (strcmp (name, ".tbss") == 0
05373 || strncmp (name, ".tbss.", 6) == 0
05374 || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
05375 flags |= SECTION_TLS | SECTION_BSS;
05376
05377
05378
05379
05380
05381
05382 if (!(flags & (SECTION_CODE | SECTION_BSS | SECTION_TLS))
05383 && (strcmp (name, ".init_array") == 0
05384 || strcmp (name, ".fini_array") == 0
05385 || strcmp (name, ".preinit_array") == 0))
05386 flags |= SECTION_NOTYPE;
05387
05388 return flags;
05389 }
05390
05391
05392
05393
05394
05395 bool
05396 have_global_bss_p (void)
05397 {
05398 return bss_noswitch_section || targetm.have_switchable_bss_sections;
05399 }
05400
05401
05402
05403
05404 void
05405 default_no_named_section (const char *name ATTRIBUTE_UNUSED,
05406 unsigned int flags ATTRIBUTE_UNUSED,
05407 tree decl ATTRIBUTE_UNUSED)
05408 {
05409
05410
05411 gcc_unreachable ();
05412 }
05413
05414 void
05415 default_elf_asm_named_section (const char *name, unsigned int flags,
05416 tree decl ATTRIBUTE_UNUSED)
05417 {
05418 char flagchars[10], *f = flagchars;
05419
05420
05421
05422
05423
05424 if (!(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
05425 && (flags & SECTION_DECLARED))
05426 {
05427 fprintf (asm_out_file, "\t.section\t%s\n", name);
05428 return;
05429 }
05430
05431 if (!(flags & SECTION_DEBUG))
05432 *f++ = 'a';
05433 if (flags & SECTION_WRITE)
05434 *f++ = 'w';
05435 if (flags & SECTION_CODE)
05436 *f++ = 'x';
05437 if (flags & SECTION_SMALL)
05438 *f++ = 's';
05439 if (flags & SECTION_MERGE)
05440 *f++ = 'M';
05441 if (flags & SECTION_STRINGS)
05442 *f++ = 'S';
05443 if (flags & SECTION_TLS)
05444 *f++ = 'T';
05445 if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
05446 *f++ = 'G';
05447 *f = '\0';
05448
05449 fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
05450
05451 if (!(flags & SECTION_NOTYPE))
05452 {
05453 const char *type;
05454 const char *format;
05455
05456 if (flags & SECTION_BSS)
05457 type = "nobits";
05458 else
05459 type = "progbits";
05460
05461 format = ",@%s";
05462 #ifdef ASM_COMMENT_START
05463
05464
05465 if (strcmp (ASM_COMMENT_START, "@") == 0)
05466 format = ",%%%s";
05467 #endif
05468 fprintf (asm_out_file, format, type);
05469
05470 if (flags & SECTION_ENTSIZE)
05471 fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
05472 if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
05473 fprintf (asm_out_file, ",%s,comdat",
05474 lang_hooks.decls.comdat_group (decl));
05475 }
05476
05477 putc ('\n', asm_out_file);
05478 }
05479
05480 void
05481 default_coff_asm_named_section (const char *name, unsigned int flags,
05482 tree decl ATTRIBUTE_UNUSED)
05483 {
05484 char flagchars[8], *f = flagchars;
05485
05486 if (flags & SECTION_WRITE)
05487 *f++ = 'w';
05488 if (flags & SECTION_CODE)
05489 *f++ = 'x';
05490 *f = '\0';
05491
05492 fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
05493 }
05494
05495 void
05496 default_pe_asm_named_section (const char *name, unsigned int flags,
05497 tree decl)
05498 {
05499 default_coff_asm_named_section (name, flags, decl);
05500
05501 if (flags & SECTION_LINKONCE)
05502 {
05503
05504
05505
05506 fprintf (asm_out_file, "\t.linkonce %s\n",
05507 (flags & SECTION_CODE ? "discard" : "same_size"));
05508 }
05509 }
05510
05511
05512
05513 section *
05514 default_select_section (tree decl, int reloc,
05515 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
05516 {
05517 if (DECL_P (decl))
05518 {
05519 if (decl_readonly_section (decl, reloc))
05520 return readonly_data_section;
05521 }
05522 else if (TREE_CODE (decl) == CONSTRUCTOR)
05523 {
05524 if (! ((flag_pic && reloc)
05525 || !TREE_READONLY (decl)
05526 || TREE_SIDE_EFFECTS (decl)
05527 || !TREE_CONSTANT (decl)))
05528 return readonly_data_section;
05529 }
05530 else if (TREE_CODE (decl) == STRING_CST)
05531 return readonly_data_section;
05532 else if (! (flag_pic && reloc))
05533 return readonly_data_section;
05534
05535 return data_section;
05536 }
05537
05538 enum section_category
05539 categorize_decl_for_section (tree decl, int reloc)
05540 {
05541 enum section_category ret;
05542
05543 if (TREE_CODE (decl) == FUNCTION_DECL)
05544 return SECCAT_TEXT;
05545 else if (TREE_CODE (decl) == STRING_CST)
05546 {
05547 if (flag_mudflap)
05548 return SECCAT_RODATA;
05549 else
05550 return SECCAT_RODATA_MERGE_STR;
05551 }
05552 else if (TREE_CODE (decl) == VAR_DECL)
05553 {
05554 if (bss_initializer_p (decl))
05555 {
05556 ret = SECCAT_BSS;
05557 #ifdef KEY
05558
05559
05560
05561
05562 if (flag_spin_file) {
05563 if (DECL_INITIAL(decl) != NULL &&
05564 DECL_INITIAL(decl) != error_mark_node) {
05565 DECL_INITIAL(decl) = NULL;
05566 if (GS_NODE(decl) != NULL) {
05567 gs_set_operand((gs_t) GS_NODE(decl), GS_DECL_INITIAL,
05568 (gs_t) NULL);
05569 }
05570 }
05571 }
05572 #endif
05573 }
05574 else if (! TREE_READONLY (decl)
05575 || TREE_SIDE_EFFECTS (decl)
05576 || ! TREE_CONSTANT (DECL_INITIAL (decl)))
05577 {
05578
05579
05580
05581
05582 if (reloc & targetm.asm_out.reloc_rw_mask ())
05583 ret = reloc == 1 ? SECCAT_DATA_REL_LOCAL : SECCAT_DATA_REL;
05584 else
05585 ret = SECCAT_DATA;
05586 }
05587 else if (reloc & targetm.asm_out.reloc_rw_mask ())
05588 ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO;
05589 else if (reloc || flag_merge_constants < 2)
05590
05591
05592
05593 ret = SECCAT_RODATA;
05594 else if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
05595 ret = SECCAT_RODATA_MERGE_STR_INIT;
05596 else
05597 ret = SECCAT_RODATA_MERGE_CONST;
05598 }
05599 else if (TREE_CODE (decl) == CONSTRUCTOR)
05600 {
05601 if ((reloc & targetm.asm_out.reloc_rw_mask ())
05602 || TREE_SIDE_EFFECTS (decl)
05603 || ! TREE_CONSTANT (decl))
05604 ret = SECCAT_DATA;
05605 else
05606 ret = SECCAT_RODATA;
05607 }
05608 else
05609 ret = SECCAT_RODATA;
05610
05611
05612 if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
05613 {
05614
05615
05616 if (ret == SECCAT_BSS
05617 || (flag_zero_initialized_in_bss
05618 && initializer_zerop (DECL_INITIAL (decl))))
05619 ret = SECCAT_TBSS;
05620 else
05621 ret = SECCAT_TDATA;
05622 }
05623
05624
05625 else if (targetm.in_small_data_p (decl))
05626 {
05627 if (ret == SECCAT_BSS)
05628 ret = SECCAT_SBSS;
05629 else if (targetm.have_srodata_section && ret == SECCAT_RODATA)
05630 ret = SECCAT_SRODATA;
05631 else
05632 ret = SECCAT_SDATA;
05633 }
05634
05635 return ret;
05636 }
05637
05638 bool
05639 decl_readonly_section (tree decl, int reloc)
05640 {
05641 switch (categorize_decl_for_section (decl, reloc))
05642 {
05643 case SECCAT_RODATA:
05644 case SECCAT_RODATA_MERGE_STR:
05645 case SECCAT_RODATA_MERGE_STR_INIT:
05646 case SECCAT_RODATA_MERGE_CONST:
05647 case SECCAT_SRODATA:
05648 return true;
05649 break;
05650 default:
05651 return false;
05652 break;
05653 }
05654 }
05655
05656
05657
05658 section *
05659 default_elf_select_section (tree decl, int reloc,
05660 unsigned HOST_WIDE_INT align)
05661 {
05662 const char *sname;
05663 switch (categorize_decl_for_section (decl, reloc))
05664 {
05665 case SECCAT_TEXT:
05666
05667 gcc_unreachable ();
05668 case SECCAT_RODATA:
05669 return readonly_data_section;
05670 case SECCAT_RODATA_MERGE_STR:
05671 return mergeable_string_section (decl, align, 0);
05672 case SECCAT_RODATA_MERGE_STR_INIT:
05673 return mergeable_string_section (DECL_INITIAL (decl), align, 0);
05674 case SECCAT_RODATA_MERGE_CONST:
05675 return mergeable_constant_section (DECL_MODE (decl), align, 0);
05676 case SECCAT_SRODATA:
05677 sname = ".sdata2";
05678 break;
05679 case SECCAT_DATA:
05680 return data_section;
05681 case SECCAT_DATA_REL:
05682 sname = ".data.rel";
05683 break;
05684 case SECCAT_DATA_REL_LOCAL:
05685 sname = ".data.rel.local";
05686 break;
05687 case SECCAT_DATA_REL_RO:
05688 sname = ".data.rel.ro";
05689 break;
05690 case SECCAT_DATA_REL_RO_LOCAL:
05691 sname = ".data.rel.ro.local";
05692 break;
05693 case SECCAT_SDATA:
05694 sname = ".sdata";
05695 break;
05696 case SECCAT_TDATA:
05697 sname = ".tdata";
05698 break;
05699 case SECCAT_BSS:
05700 if (bss_section)
05701 return bss_section;
05702 sname = ".bss";
05703 break;
05704 case SECCAT_SBSS:
05705 sname = ".sbss";
05706 break;
05707 case SECCAT_TBSS:
05708 sname = ".tbss";
05709 break;
05710 default:
05711 gcc_unreachable ();
05712 }
05713
05714 if (!DECL_P (decl))
05715 decl = NULL_TREE;
05716 return get_named_section (decl, sname, reloc);
05717 }
05718
05719
05720
05721
05722 void
05723 default_unique_section (tree decl, int reloc)
05724 {
05725
05726 bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
05727 const char *prefix, *name;
05728 size_t nlen, plen;
05729 char *string;
05730
05731 switch (categorize_decl_for_section (decl, reloc))
05732 {
05733 case SECCAT_TEXT:
05734 prefix = one_only ? ".gnu.linkonce.t." : ".text.";
05735 break;
05736 case SECCAT_RODATA:
05737 case SECCAT_RODATA_MERGE_STR:
05738 case SECCAT_RODATA_MERGE_STR_INIT:
05739 case SECCAT_RODATA_MERGE_CONST:
05740 prefix = one_only ? ".gnu.linkonce.r." : ".rodata.";
05741 break;
05742 case SECCAT_SRODATA:
05743 prefix = one_only ? ".gnu.linkonce.s2." : ".sdata2.";
05744 break;
05745 case SECCAT_DATA:
05746 prefix = one_only ? ".gnu.linkonce.d." : ".data.";
05747 break;
05748 case SECCAT_DATA_REL:
05749 prefix = one_only ? ".gnu.linkonce.d.rel." : ".data.rel.";
05750 break;
05751 case SECCAT_DATA_REL_LOCAL:
05752 prefix = one_only ? ".gnu.linkonce.d.rel.local." : ".data.rel.local.";
05753 break;
05754 case SECCAT_DATA_REL_RO:
05755 prefix = one_only ? ".gnu.linkonce.d.rel.ro." : ".data.rel.ro.";
05756 break;
05757 case SECCAT_DATA_REL_RO_LOCAL:
05758 prefix = one_only ? ".gnu.linkonce.d.rel.ro.local."
05759 : ".data.rel.ro.local.";
05760 break;
05761 case SECCAT_SDATA:
05762 prefix = one_only ? ".gnu.linkonce.s." : ".sdata.";
05763 break;
05764 case SECCAT_BSS:
05765 prefix = one_only ? ".gnu.linkonce.b." : ".bss.";
05766 break;
05767 case SECCAT_SBSS:
05768 prefix = one_only ? ".gnu.linkonce.sb." : ".sbss.";
05769 break;
05770 case SECCAT_TDATA:
05771 prefix = one_only ? ".gnu.linkonce.td." : ".tdata.";
05772 break;
05773 case SECCAT_TBSS:
05774 prefix = one_only ? ".gnu.linkonce.tb." : ".tbss.";
05775 break;
05776 default:
05777 gcc_unreachable ();
05778 }
05779 plen = strlen (prefix);
05780
05781 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
05782 name = targetm.strip_name_encoding (name);
05783 nlen = strlen (name);
05784
05785 string = alloca (nlen + plen + 1);
05786 memcpy (string, prefix, plen);
05787 memcpy (string + plen, name, nlen + 1);
05788
05789 DECL_SECTION_NAME (decl) = build_string (nlen + plen, string);
05790 }
05791
05792
05793
05794
05795
05796 static int
05797 compute_reloc_for_rtx_1 (rtx *xp, void *data)
05798 {
05799 int *preloc = data;
05800 rtx x = *xp;
05801
05802 switch (GET_CODE (x))
05803 {
05804 case SYMBOL_REF:
05805 *preloc |= SYMBOL_REF_LOCAL_P (x) ? 1 : 2;
05806 break;
05807 case LABEL_REF:
05808 *preloc |= 1;
05809 break;
05810 default:
05811 break;
05812 }
05813
05814 return 0;
05815 }
05816
05817 static int
05818 compute_reloc_for_rtx (rtx x)
05819 {
05820 int reloc;
05821
05822 switch (GET_CODE (x))
05823 {
05824 case CONST:
05825 case SYMBOL_REF:
05826 case LABEL_REF:
05827 reloc = 0;
05828 for_each_rtx (&x, compute_reloc_for_rtx_1, &reloc);
05829 return reloc;
05830
05831 default:
05832 return 0;
05833 }
05834 }
05835
05836 section *
05837 default_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
05838 rtx x,
05839 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
05840 {
05841 if (compute_reloc_for_rtx (x) & targetm.asm_out.reloc_rw_mask ())
05842 return data_section;
05843 else
05844 return readonly_data_section;
05845 }
05846
05847 section *
05848 default_elf_select_rtx_section (enum machine_mode mode, rtx x,
05849 unsigned HOST_WIDE_INT align)
05850 {
05851 int reloc = compute_reloc_for_rtx (x);
05852
05853
05854
05855 if (reloc & targetm.asm_out.reloc_rw_mask ())
05856 {
05857 if (reloc == 1)
05858 return get_named_section (NULL, ".data.rel.ro.local", 1);
05859 else
05860 return get_named_section (NULL, ".data.rel.ro", 3);
05861 }
05862
05863 return mergeable_constant_section (mode, align, 0);
05864 }
05865
05866
05867
05868 void
05869 default_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
05870 {
05871 rtx symbol;
05872 int flags;
05873
05874
05875 if (!MEM_P (rtl))
05876 return;
05877 symbol = XEXP (rtl, 0);
05878 if (GET_CODE (symbol) != SYMBOL_REF)
05879 return;
05880
05881 flags = SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_HAS_BLOCK_INFO;
05882 if (TREE_CODE (decl) == FUNCTION_DECL)
05883 flags |= SYMBOL_FLAG_FUNCTION;
05884 if (targetm.binds_local_p (decl))
05885 flags |= SYMBOL_FLAG_LOCAL;
05886 if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
05887 flags |= DECL_TLS_MODEL (decl) << SYMBOL_FLAG_TLS_SHIFT;
05888 else if (targetm.in_small_data_p (decl))
05889 flags |= SYMBOL_FLAG_SMALL;
05890
05891
05892
05893 if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
05894 flags |= SYMBOL_FLAG_EXTERNAL;
05895
05896 SYMBOL_REF_FLAGS (symbol) = flags;
05897 }
05898
05899
05900
05901
05902 const char *
05903 default_strip_name_encoding (const char *str)
05904 {
05905 return str + (*str == '*');
05906 }
05907
05908 #ifdef ASM_OUTPUT_DEF
05909
05910
05911
05912 void
05913 default_asm_output_anchor (rtx symbol)
05914 {
05915 char buffer[100];
05916
05917 sprintf (buffer, ". + " HOST_WIDE_INT_PRINT_DEC,
05918 SYMBOL_REF_BLOCK_OFFSET (symbol));
05919 ASM_OUTPUT_DEF (asm_out_file, XSTR (symbol, 0), buffer);
05920 }
05921 #endif
05922
05923
05924
05925 bool
05926 default_use_anchors_for_symbol_p (rtx symbol)
05927 {
05928 section *sect;
05929 tree decl;
05930
05931
05932
05933 sect = SYMBOL_REF_BLOCK (symbol)->sect;
05934 if (sect->common.flags & SECTION_MERGE)
05935 return false;
05936
05937
05938
05939 if (sect->common.flags & SECTION_SMALL)
05940 return false;
05941
05942 decl = SYMBOL_REF_DECL (symbol);
05943 if (decl && DECL_P (decl))
05944 {
05945
05946
05947 if (!targetm.binds_local_p (decl))
05948 return false;
05949
05950
05951
05952
05953
05954
05955 if (targetm.in_small_data_p (decl))
05956 return false;
05957 }
05958 return true;
05959 }
05960
05961
05962
05963
05964 bool
05965 default_binds_local_p (tree exp)
05966 {
05967 return default_binds_local_p_1 (exp, flag_shlib);
05968 }
05969
05970 bool
05971 default_binds_local_p_1 (tree exp, int shlib)
05972 {
05973 bool local_p;
05974
05975
05976 if (!DECL_P (exp))
05977 local_p = true;
05978
05979
05980 else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp)))
05981 local_p = false;
05982
05983 else if (! TREE_PUBLIC (exp))
05984 local_p = true;
05985
05986
05987 else if (DECL_VISIBILITY_SPECIFIED (exp)
05988 && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
05989 local_p = true;
05990
05991 else if (DECL_EXTERNAL (exp))
05992 local_p = false;
05993
05994
05995 else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
05996 local_p = true;
05997
05998
05999 else if (DECL_WEAK (exp))
06000 local_p = false;
06001
06002
06003 else if (shlib)
06004 local_p = false;
06005
06006
06007 else if (DECL_COMMON (exp)
06008 && (DECL_INITIAL (exp) == NULL
06009 || DECL_INITIAL (exp) == error_mark_node))
06010 local_p = false;
06011
06012
06013 else
06014 local_p = true;
06015
06016 return local_p;
06017 }
06018
06019
06020
06021 bool
06022 default_valid_pointer_mode (enum machine_mode mode)
06023 {
06024 return (mode == ptr_mode || mode == Pmode);
06025 }
06026
06027
06028
06029
06030 #ifdef GLOBAL_ASM_OP
06031 void
06032 default_globalize_label (FILE * stream, const char *name)
06033 {
06034 fputs (GLOBAL_ASM_OP, stream);
06035 assemble_name (stream, name);
06036 putc ('\n', stream);
06037 }
06038 #endif
06039
06040
06041
06042
06043 void
06044 default_emit_unwind_label (FILE * stream ATTRIBUTE_UNUSED,
06045 tree decl ATTRIBUTE_UNUSED,
06046 int for_eh ATTRIBUTE_UNUSED,
06047 int empty ATTRIBUTE_UNUSED)
06048 {
06049 }
06050
06051
06052
06053
06054 void
06055 default_emit_except_table_label (FILE * stream ATTRIBUTE_UNUSED)
06056 {
06057 }
06058
06059
06060
06061
06062 void
06063 default_internal_label (FILE *stream, const char *prefix,
06064 unsigned long labelno)
06065 {
06066 char *const buf = alloca (40 + strlen (prefix));
06067 ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno);
06068 ASM_OUTPUT_INTERNAL_LABEL (stream, buf);
06069 }
06070
06071
06072
06073 void
06074 default_file_start (void)
06075 {
06076 if (targetm.file_start_app_off && !flag_verbose_asm)
06077 fputs (ASM_APP_OFF, asm_out_file);
06078
06079 if (targetm.file_start_file_directive)
06080 output_file_directive (asm_out_file, main_input_filename);
06081 }
06082
06083
06084
06085
06086
06087
06088 int trampolines_created;
06089
06090 void
06091 file_end_indicate_exec_stack (void)
06092 {
06093 unsigned int flags = SECTION_DEBUG;
06094 if (trampolines_created)
06095 flags |= SECTION_CODE;
06096
06097 switch_to_section (get_section (".note.GNU-stack", flags, NULL));
06098 }
06099
06100
06101
06102
06103 void
06104 output_section_asm_op (const void *directive)
06105 {
06106 fprintf (asm_out_file, "%s\n", (const char *) directive);
06107 }
06108
06109
06110
06111
06112 void
06113 switch_to_section (section *new_section)
06114 {
06115 if (in_section == new_section)
06116 return;
06117
06118 if (new_section->common.flags & SECTION_FORGET)
06119 in_section = NULL;
06120 else
06121 in_section = new_section;
06122
06123 switch (SECTION_STYLE (new_section))
06124 {
06125 case SECTION_NAMED:
06126 if (cfun
06127 && !cfun->unlikely_text_section_name
06128 && strcmp (new_section->named.name,
06129 UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
06130 cfun->unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
06131
06132 targetm.asm_out.named_section (new_section->named.name,
06133 new_section->named.common.flags,
06134 new_section->named.decl);
06135 break;
06136
06137 case SECTION_UNNAMED:
06138 new_section->unnamed.callback (new_section->unnamed.data);
06139 break;
06140
06141 case SECTION_NOSWITCH:
06142 gcc_unreachable ();
06143 break;
06144 }
06145
06146 new_section->common.flags |= SECTION_DECLARED;
06147 }
06148
06149
06150
06151
06152 void
06153 place_block_symbol (rtx symbol)
06154 {
06155 unsigned HOST_WIDE_INT size, mask, offset;
06156 struct constant_descriptor_rtx *desc;
06157 unsigned int alignment;
06158 struct object_block *block;
06159 tree decl;
06160
06161 gcc_assert (SYMBOL_REF_BLOCK (symbol));
06162 if (SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0)
06163 return;
06164
06165
06166 if (CONSTANT_POOL_ADDRESS_P (symbol))
06167 {
06168 desc = SYMBOL_REF_CONSTANT (symbol);
06169 alignment = desc->align;
06170 size = GET_MODE_SIZE (desc->mode);
06171 }
06172 else if (TREE_CONSTANT_POOL_ADDRESS_P (symbol))
06173 {
06174 decl = SYMBOL_REF_DECL (symbol);
06175 alignment = get_constant_alignment (decl);
06176 size = get_constant_size (decl);
06177 }
06178 else
06179 {
06180 decl = SYMBOL_REF_DECL (symbol);
06181 alignment = DECL_ALIGN (decl);
06182 size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
06183 }
06184
06185
06186 block = SYMBOL_REF_BLOCK (symbol);
06187 mask = alignment / BITS_PER_UNIT - 1;
06188 offset = (block->size + mask) & ~mask;
06189 SYMBOL_REF_BLOCK_OFFSET (symbol) = offset;
06190
06191
06192 block->alignment = MAX (block->alignment, alignment);
06193 block->size = offset + size;
06194
06195 VEC_safe_push (rtx, gc, block->objects, symbol);
06196 }
06197
06198
06199
06200
06201
06202 rtx
06203 get_section_anchor (struct object_block *block, HOST_WIDE_INT offset,
06204 enum tls_model model)
06205 {
06206 char label[100];
06207 unsigned int begin, middle, end;
06208 unsigned HOST_WIDE_INT min_offset, max_offset, range, bias, delta;
06209 rtx anchor;
06210
06211
06212
06213
06214
06215
06216
06217
06218
06219
06220
06221
06222
06223
06224
06225 max_offset = (unsigned HOST_WIDE_INT) targetm.max_anchor_offset;
06226 min_offset = (unsigned HOST_WIDE_INT) targetm.min_anchor_offset;
06227 range = max_offset - min_offset + 1;
06228 if (range == 0)
06229 offset = 0;
06230 else
06231 {
06232 bias = 1 << (GET_MODE_BITSIZE (ptr_mode) - 1);
06233 if (offset < 0)
06234 {
06235 delta = -(unsigned HOST_WIDE_INT) offset + max_offset;
06236 delta -= delta % range;
06237 if (delta > bias)
06238 delta = bias;
06239 offset = (HOST_WIDE_INT) (-delta);
06240 }
06241 else
06242 {
06243 delta = (unsigned HOST_WIDE_INT) offset - min_offset;
06244 delta -= delta % range;
06245 if (delta > bias - 1)
06246 delta = bias - 1;
06247 offset = (HOST_WIDE_INT) delta;
06248 }
06249 }
06250
06251
06252
06253 begin = 0;
06254 end = VEC_length (rtx, block->anchors);
06255 while (begin != end)
06256 {
06257 middle = (end + begin) / 2;
06258 anchor = VEC_index (rtx, block->anchors, middle);
06259 if (SYMBOL_REF_BLOCK_OFFSET (anchor) > offset)
06260 end = middle;
06261 else if (SYMBOL_REF_BLOCK_OFFSET (anchor) < offset)
06262 begin = middle + 1;
06263 else if (SYMBOL_REF_TLS_MODEL (anchor) > model)
06264 end = middle;
06265 else if (SYMBOL_REF_TLS_MODEL (anchor) < model)
06266 begin = middle + 1;
06267 else
06268 return anchor;
06269 }
06270
06271
06272 ASM_GENERATE_INTERNAL_LABEL (label, "LANCHOR", anchor_labelno++);
06273 anchor = create_block_symbol (ggc_strdup (label), block, offset);
06274 SYMBOL_REF_FLAGS (anchor) |= SYMBOL_FLAG_LOCAL | SYMBOL_FLAG_ANCHOR;
06275 SYMBOL_REF_FLAGS (anchor) |= model << SYMBOL_FLAG_TLS_SHIFT;
06276
06277
06278 VEC_safe_insert (rtx, gc, block->anchors, begin, anchor);
06279 return anchor;
06280 }
06281
06282
06283
06284 static void
06285 output_object_block (struct object_block *block)
06286 {
06287 struct constant_descriptor_rtx *desc;
06288 unsigned int i;
06289 HOST_WIDE_INT offset;
06290 tree decl;
06291 rtx symbol;
06292
06293 if (block->objects == NULL)
06294 return;
06295
06296
06297
06298 switch_to_section (block->sect);
06299 assemble_align (block->alignment);
06300
06301
06302
06303 for (i = 0; VEC_iterate (rtx, block->anchors, i, symbol); i++)
06304 targetm.asm_out.output_anchor (symbol);
06305
06306
06307 offset = 0;
06308 for (i = 0; VEC_iterate (rtx, block->objects, i, symbol); i++)
06309 {
06310
06311 assemble_zeros (SYMBOL_REF_BLOCK_OFFSET (symbol) - offset);
06312 offset = SYMBOL_REF_BLOCK_OFFSET (symbol);
06313 if (CONSTANT_POOL_ADDRESS_P (symbol))
06314 {
06315 desc = SYMBOL_REF_CONSTANT (symbol);
06316 output_constant_pool_1 (desc, 1);
06317 offset += GET_MODE_SIZE (desc->mode);
06318 }
06319 else if (TREE_CONSTANT_POOL_ADDRESS_P (symbol))
06320 {
06321 decl = SYMBOL_REF_DECL (symbol);
06322 assemble_constant_contents (decl, XSTR (symbol, 0),
06323 get_constant_alignment (decl));
06324 offset += get_constant_size (decl);
06325 }
06326 else
06327 {
06328 decl = SYMBOL_REF_DECL (symbol);
06329 assemble_variable_contents (decl, XSTR (symbol, 0), false);
06330 offset += tree_low_cst (DECL_SIZE_UNIT (decl), 1);
06331 }
06332 }
06333 }
06334
06335
06336
06337
06338 static int
06339 output_object_block_htab (void **slot, void *data ATTRIBUTE_UNUSED)
06340 {
06341 output_object_block ((struct object_block *) (*slot));
06342 return 1;
06343 }
06344
06345
06346
06347 void
06348 output_object_blocks (void)
06349 {
06350 htab_traverse (object_block_htab, output_object_block_htab, NULL);
06351 }
06352
06353 #include "gt-varasm.h"