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