From 8ce4ae95b9d25c3091004d44d707c006855bedb8 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Sun, 25 Jan 2004 21:27:37 +0000 Subject: [PATCH] * config/mips/mips.c (mips_offset_within_object_p): New function. (mips_symbolic_constant_p): Use it in the SYMBOL_SMALL_DATA and SYMBOL_CONSTANT_POOL cases. Also use it for SYMBOL_GENERAL if the ABI has 64-bit pointers and the object file only allows 32-bit symbols. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@76586 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 +++++++ gcc/config/mips/mips.c | 47 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b9492736dd1..ccad5da79dc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2004-01-25 Richard Sandiford + + * config/mips/mips.c (mips_offset_within_object_p): New function. + (mips_symbolic_constant_p): Use it in the SYMBOL_SMALL_DATA and + SYMBOL_CONSTANT_POOL cases. Also use it for SYMBOL_GENERAL if the + ABI has 64-bit pointers and the object file only allows 32-bit symbols. + 2004-01-25 Kazu Hirata * config/sh/sh.h (PROMOTE_FUNCTION_ARGS): Remove. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 1c87e111573..df338f71c22 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -191,6 +191,7 @@ struct mips_integer_op; static enum mips_symbol_type mips_classify_symbol (rtx); static void mips_split_const (rtx, rtx *, HOST_WIDE_INT *); +static bool mips_offset_within_object_p (rtx, HOST_WIDE_INT); static bool mips_symbolic_constant_p (rtx, enum mips_symbol_type *); static bool mips_valid_base_register_p (rtx, enum machine_mode, int); static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode); @@ -914,6 +915,29 @@ mips_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset) } +/* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points + to the same object as SYMBOL. */ + +static bool +mips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset) +{ + if (GET_CODE (symbol) != SYMBOL_REF) + return false; + + if (CONSTANT_POOL_ADDRESS_P (symbol) + && offset >= 0 + && offset < (int) GET_MODE_SIZE (get_pool_mode (symbol))) + return true; + + if (SYMBOL_REF_DECL (symbol) != 0 + && offset >= 0 + && offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol)))) + return true; + + return false; +} + + /* Return true if X is a symbolic constant that can be calculated in the same way as a bare symbol. If it is, store the type of the symbol in *SYMBOL_TYPE. */ @@ -939,21 +963,22 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type) switch (*symbol_type) { case SYMBOL_GENERAL: - /* %hi() and %lo() can handle anything. */ + /* If the target has 64-bit pointers and the object file only + supports 32-bit symbols, the values of those symbols will be + sign-extended. In this case we can't allow an arbitrary offset + in case the 32-bit value X + OFFSET has a different sign from X. */ + if (Pmode == DImode && !ABI_HAS_64BIT_SYMBOLS) + return mips_offset_within_object_p (x, offset); + + /* In other cases the relocations can handle any offset. */ return true; case SYMBOL_SMALL_DATA: - /* Make sure that the offset refers to something within the - -G limit. If the offset is allowed to grow too much, - it could overflow the range of %gp_rel(). */ - return (offset > 0 && offset < mips_section_threshold); - case SYMBOL_CONSTANT_POOL: - /* Similarly check the range of offsets for mips16 constant - pool entries. */ - return (CONSTANT_POOL_ADDRESS_P (x) - && offset > 0 - && offset < (int) GET_MODE_SIZE (get_pool_mode (x))); + /* Make sure that the offset refers to something within the + underlying object. This should guarantee that the final + PC- or GP-relative offset is within the 16-bit limit. */ + return mips_offset_within_object_p (x, offset); case SYMBOL_GOT_LOCAL: case SYMBOL_GOTOFF_PAGE: -- 2.11.4.GIT