re PR c++/12945 (MIPS g++.old-deja/g++.abi/ptrflags.C fails.)

PR target/12945
	* coverage.c (coverage_counter_alloc): Set SYMBOL_FLAG_LOCAL for
	for counter labels.
	* config/mips/mips.c (INTERNAL_SYMBOL_P): Delete.
	(mips_classify_symbol): Always treat SYMBOL_REF_FLAG as indicating
	string constants if TARGET_MIPS16.  Use SYMBOL_REF_DECL to check
	the binding of decl symbols, otherwise check SYMBOL_REF_LOCAL_P.
	(mips_symbol_insns): Don't trust the local/global classification.
	(m16_usym8_4, m16_usym5_4): Same mips16 change as mips_classify_symbol.
	(override_options): Make -mabicalls -fno-unit-at-a-time imply
	-mno-explicit-relocs.
	(mips_encode_section_info): Don't use SYMBOL_REF_FLAG to distinguish
	between local and global symbols.

From-SVN: r75422
This commit is contained in:
Richard Sandiford 2004-01-05 09:37:02 +00:00 committed by Richard Sandiford
parent 816bc01fa3
commit f614987783
3 changed files with 93 additions and 70 deletions

View File

@ -1,3 +1,19 @@
2004-01-05 Richard Sandiford <rsandifo@redhat.com>
PR target/12945
* coverage.c (coverage_counter_alloc): Set SYMBOL_FLAG_LOCAL for
for counter labels.
* config/mips/mips.c (INTERNAL_SYMBOL_P): Delete.
(mips_classify_symbol): Always treat SYMBOL_REF_FLAG as indicating
string constants if TARGET_MIPS16. Use SYMBOL_REF_DECL to check
the binding of decl symbols, otherwise check SYMBOL_REF_LOCAL_P.
(mips_symbol_insns): Don't trust the local/global classification.
(m16_usym8_4, m16_usym5_4): Same mips16 change as mips_classify_symbol.
(override_options): Make -mabicalls -fno-unit-at-a-time imply
-mno-explicit-relocs.
(mips_encode_section_info): Don't use SYMBOL_REF_FLAG to distinguish
between local and global symbols.
2004-01-05 Richard Sandiford <rsandifo@redhat.com> 2004-01-05 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips-protos.h (mips_dangerous_for_la25_p): Declare. * config/mips/mips-protos.h (mips_dangerous_for_la25_p): Declare.

View File

@ -77,10 +77,6 @@ enum internal_test {
#define SINGLE_WORD_MODE_P(MODE) \ #define SINGLE_WORD_MODE_P(MODE) \
((MODE) != BLKmode && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) ((MODE) != BLKmode && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD)
/* True if the given SYMBOL_REF is for an internally-generated symbol. */
#define INTERNAL_SYMBOL_P(SYM) \
(XSTR (SYM, 0)[0] == '*' && XSTR (SYM, 0)[1] == LOCAL_LABEL_PREFIX[0])
/* True if X is an unspec wrapper around a SYMBOL_REF or LABEL_REF. */ /* True if X is an unspec wrapper around a SYMBOL_REF or LABEL_REF. */
#define UNSPEC_ADDRESS_P(X) \ #define UNSPEC_ADDRESS_P(X) \
(GET_CODE (X) == UNSPEC \ (GET_CODE (X) == UNSPEC \
@ -823,23 +819,44 @@ mips_classify_symbol (rtx x)
return SYMBOL_GENERAL; return SYMBOL_GENERAL;
} }
if (INTERNAL_SYMBOL_P (x))
{
/* The symbol is a local label. For TARGET_MIPS16, SYMBOL_REF_FLAG
will be set if the symbol refers to a string in the current
function's constant pool. */
if (TARGET_MIPS16 && SYMBOL_REF_FLAG (x))
return SYMBOL_CONSTANT_POOL;
if (TARGET_ABICALLS)
return SYMBOL_GOT_LOCAL;
}
if (SYMBOL_REF_SMALL_P (x)) if (SYMBOL_REF_SMALL_P (x))
return SYMBOL_SMALL_DATA; return SYMBOL_SMALL_DATA;
/* When generating mips16 code, SYMBOL_REF_FLAG indicates a string
in the current function's constant pool. */
if (TARGET_MIPS16 && SYMBOL_REF_FLAG (x))
return SYMBOL_CONSTANT_POOL;
if (TARGET_ABICALLS) if (TARGET_ABICALLS)
return (SYMBOL_REF_FLAG (x) ? SYMBOL_GOT_LOCAL : SYMBOL_GOT_GLOBAL); {
if (SYMBOL_REF_DECL (x) == 0)
return SYMBOL_REF_LOCAL_P (x) ? SYMBOL_GOT_LOCAL : SYMBOL_GOT_GLOBAL;
/* There are three cases to consider:
- o32 PIC (either with or without explicit relocs)
- n32/n64 PIC without explicit relocs
- n32/n64 PIC with explicit relocs
In the first case, both local and global accesses will use an
R_MIPS_GOT16 relocation. We must correctly predict which of
the two semantics (local or global) the assembler and linker
will apply. The choice doesn't depend on the symbol's
visibility, so we deliberately ignore decl_visibility and
binds_local_p here.
In the second case, the assembler will not use R_MIPS_GOT16
relocations, but it chooses between local and global accesses
in the same way as for o32 PIC.
In the third case we have more freedom since both forms of
access will work for any kind of symbol. However, there seems
little point in doing things differently. */
if (DECL_P (SYMBOL_REF_DECL (x)) && TREE_PUBLIC (SYMBOL_REF_DECL (x)))
return SYMBOL_GOT_GLOBAL;
return SYMBOL_GOT_LOCAL;
}
return SYMBOL_GENERAL; return SYMBOL_GENERAL;
} }
@ -1073,27 +1090,28 @@ mips_symbol_insns (enum mips_symbol_type type)
return 2; return 2;
case SYMBOL_GOT_LOCAL: case SYMBOL_GOT_LOCAL:
/* For o32 and o64, the sequence is:
lw $at,%got(symbol)
nop
and the final address is $at + %lo(symbol). A load/add
sequence is also needed for n32 and n64. Some versions
of GAS insert a nop in the n32/n64 sequences too so, for
simplicity, use the worst case of 3 instructions. */
return 3;
case SYMBOL_GOT_GLOBAL: case SYMBOL_GOT_GLOBAL:
/* When using a small GOT, we just fetch the address using /* Unless -funit-at-a-time is in effect, we can't be sure whether
a gp-relative load. For a big GOT, we need a sequence the local/global classification is accurate. See override_options
such as: for details.
lui $at,%got_hi(symbol) The worst cases are:
daddu $at,$at,$gp
and the final address is $at + %got_lo(symbol). */ (1) For local symbols when generating o32 or o64 code. The assembler
return (TARGET_XGOT ? 3 : 1); will use:
lw $at,%got(symbol)
nop
...and the final address will be $at + %lo(symbol).
(2) For global symbols when -mxgot. The assembler will use:
lui $at,%got_hi(symbol)
(d)addu $at,$at,$gp
...and the final address will be $at + %got_lo(symbol). */
return 3;
case SYMBOL_GOTOFF_PAGE: case SYMBOL_GOTOFF_PAGE:
case SYMBOL_GOTOFF_GLOBAL: case SYMBOL_GOTOFF_GLOBAL:
@ -2078,7 +2096,6 @@ m16_usym8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
if (GET_CODE (op) == SYMBOL_REF if (GET_CODE (op) == SYMBOL_REF
&& SYMBOL_REF_FLAG (op) && SYMBOL_REF_FLAG (op)
&& cfun->machine->insns_len > 0 && cfun->machine->insns_len > 0
&& INTERNAL_SYMBOL_P (op)
&& (cfun->machine->insns_len + get_pool_size () + mips_string_length && (cfun->machine->insns_len + get_pool_size () + mips_string_length
< 4 * 0x100)) < 4 * 0x100))
{ {
@ -2101,7 +2118,6 @@ m16_usym5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
if (GET_CODE (op) == SYMBOL_REF if (GET_CODE (op) == SYMBOL_REF
&& SYMBOL_REF_FLAG (op) && SYMBOL_REF_FLAG (op)
&& cfun->machine->insns_len > 0 && cfun->machine->insns_len > 0
&& INTERNAL_SYMBOL_P (op)
&& (cfun->machine->insns_len + get_pool_size () + mips_string_length && (cfun->machine->insns_len + get_pool_size () + mips_string_length
< 4 * 0x20)) < 4 * 0x20))
{ {
@ -4785,6 +4801,28 @@ override_options (void)
&& (target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0) && (target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0)
target_flags &= ~MASK_EXPLICIT_RELOCS; target_flags &= ~MASK_EXPLICIT_RELOCS;
/* Make -mabicalls -fno-unit-at-a-time imply -mno-explicit-relocs
unless the user says otherwise.
There are two problems here:
(1) The value of an R_MIPS_GOT16 relocation depends on whether
the symbol is local or global. We therefore need to know
a symbol's binding before refering to it using %got().
(2) R_MIPS_CALL16 can only be applied to global symbols.
When not using -funit-at-a-time, a symbol's binding may change
after it has been used. For example, the C++ front-end will
initially assume that the typeinfo for an incomplete type will be
comdat, on the basis that the type could be completed later in the
file. But if the type never is completed, the typeinfo will become
local instead. */
if (!flag_unit_at_a_time
&& TARGET_ABICALLS
&& (target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0)
target_flags &= ~MASK_EXPLICIT_RELOCS;
/* -mrnames says to use the MIPS software convention for register /* -mrnames says to use the MIPS software convention for register
names instead of the hardware names (ie, $a0 instead of $4). names instead of the hardware names (ie, $a0 instead of $4).
We do this by switching the names in mips_reg_names, which the We do this by switching the names in mips_reg_names, which the
@ -7052,10 +7090,7 @@ mips_in_small_data_p (tree decl)
constants which are put in the .text section. We also record the constants which are put in the .text section. We also record the
total length of all such strings; this total is used to decide total length of all such strings; this total is used to decide
whether we need to split the constant table, and need not be whether we need to split the constant table, and need not be
precisely correct. precisely correct. */
When generating -mabicalls code, SYMBOL_REF_FLAG is set if we
should treat the symbol as SYMBOL_GOT_LOCAL. */
static void static void
mips_encode_section_info (tree decl, rtx rtl, int first) mips_encode_section_info (tree decl, rtx rtl, int first)
@ -7107,35 +7142,6 @@ mips_encode_section_info (tree decl, rtx rtl, int first)
SYMBOL_REF_FLAG (symbol) = 1; SYMBOL_REF_FLAG (symbol) = 1;
} }
else if (TARGET_ABICALLS)
{
/* Mark the symbol if we should treat it as SYMBOL_GOT_LOCAL.
There are three cases to consider:
- o32 PIC (either with or without explicit relocs)
- n32/n64 PIC without explicit relocs
- n32/n64 PIC with explicit relocs
In the first case, both local and global accesses will use an
R_MIPS_GOT16 relocation. We must correctly predict which of
the two semantics (local or global) the assembler and linker
will apply. The choice doesn't depend on the symbol's
visibility, so we deliberately ignore decl_visibility and
binds_local_p here.
In the second case, the assembler will not use R_MIPS_GOT16
relocations, but it chooses between local and global accesses
in the same way as for o32 PIC.
In the third case we have more freedom since both forms of
access will work for any kind of symbol. However, there seems
little point in doing things differently. */
if (DECL_P (decl) && TREE_PUBLIC (decl))
SYMBOL_REF_FLAG (symbol) = 0;
else
SYMBOL_REF_FLAG (symbol) = 1;
}
default_encode_section_info (decl, rtl, first); default_encode_section_info (decl, rtl, first);
} }

View File

@ -374,6 +374,7 @@ coverage_counter_alloc (unsigned counter, unsigned num)
ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1); ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
} }
fn_b_ctrs[counter] = fn_n_ctrs[counter]; fn_b_ctrs[counter] = fn_n_ctrs[counter];
fn_n_ctrs[counter] += num; fn_n_ctrs[counter] += num;