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