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