[RTL, ColdFire 15/63] Avoid out-of-segment constants on uClinux.

Richard Sandiford richard@codesourcery.com
Wed Jan 10 11:05:00 GMT 2007


One of the big problems with the uClinux flat format is that it cannot
cope with relocations that point outside the symbol's containing segment.
E.g. things like:

    extern unsigned char a[];
    ... &a[12345 - x] ...

cannot be implemented as "&a[12345] - x" because "a" might be less than
12345 bytes from the end of the segment.  This problem applies to both
text and data relocations: we should never emit a symbolic constant
if we are unsure whether it is contained within the symbol's segment.

MIPS has a similar problem for other reasons, so this patch moves two
helper routines, mips_offset_within_block_p and mips_split_const,
from mips.c to rtlanal.c (removing the mips_ prefixes, of course).

The patch also removes the unused predicates from the movsi expander.
It seems odd to handle non-legitimate operands in something that appears
to be (but really isn't) guarded by *_operand predicates.

One problem with this patch is that we sometimes need to access
individual bytes or words of wider MEMs.  This will ICE if the
wider MEM has a legitimate constant address but the narrower
one doesn't.  This is a generic problem that applies to all
addresses with limited ranges, and a later patch will fix it.

FWIW, bfin_legitimate_constant_p does something similar, but it
doesn't cope with constant pool entries or object blocks, neither
of which the Blackfin port uses.

The split_const function is similar to get_related_value and
get_integer_term, but has the advantage of (a) only walking the
rtl once and (b) returning an rtx offset, so that if the caller
needs an rtx, it doesn't need to regenerate one from the HOST_WIDE_INT.
(get_related_value and get_integer_term also cope with MINUS of a
CONST_INT, but that isn't canonical rtl.)

Boostrapped & regression-tested on x86_64-linux-gnu.  I also compared
the assembly output of mipsisa64-elf and mips64-linux-gnu for the
C and C++ testsuites, using the options:

  -O0
  -O2
  -mabi=n32
  -mabi=64
  -mabi=eabi -mno-abicalls
  -mabi=32
  -mabi=o64

There were no differences.  I'll sign off on the MIPS bits if
everything else is OK.

Richard


gcc/
	* Makefile.in (rtlanal.o): Depend on tree.h.
	* rtl.h (offset_within_section_p, split_const): Declare.
	* rtlanal.c: Include tree.h.
	(offset_within_block_p): New function, taken from
	mips_offset_within_object_p.
	(split_const): New function, taken from mips_split_const.
	* config/m68k/m68k-protos.h (m68k_illegitimate_symbolic_constant_p):
	Declare.
	* config/m68k/m68k.h (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P): Define.
	(CONSTANT_ADDRESS_P): Only accept legitimate constants.
	(LEGITIMATE_CONSTANT_P): Check m68k_illegitimate_symbolic_constant_p.
	* config/m68k/m68k.c (TARGET_CANNOT_FORCE_CONST_MEM): Define.
	(m68k_illegitimate_symbolic_constant_p): New function.
	* config/m68k/m68k.md (movsi): Remove misleading predicates.
	If M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P and the source is a
	symbolic constant that might be outside the symbol's section,
	move the symbol first and then add the offset.
	* config/m68k/uclinux.h (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P):
	Override.
	* config/mips/mips.c (mips_split_const): Delete.
	(mips_offset_within_object_p): Delete.
	(mips_symbolic_constant_p): Use offset_within_section_p and
	split_const instead of mips_offset_within_object_p and
	mips_split_const.
	(mips_cannot_force_const_mem, mips_const_insns, mips_unspec_address)
	(mips_legitimize_const_move, print_operand_reloc)
	(mips_dangerous_for_la25_p): Use split_const instead of
	mips_split_const.

Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	2007-01-09 15:01:42.000000000 +0000
+++ gcc/Makefile.in	2007-01-09 15:01:56.000000000 +0000
@@ -2189,7 +2189,7 @@ print-rtl.o : print-rtl.c $(CONFIG_H) $(
     $(BCONFIG_H) $(REAL_H)
 rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \
    $(RTL_H) hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) $(REAL_H) \
-   $(FLAGS_H) $(REGS_H) output.h $(TARGET_H) $(FUNCTION_H)
+   $(FLAGS_H) $(REGS_H) output.h $(TARGET_H) $(FUNCTION_H) $(TREE_H)
 
 varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    $(RTL_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) hard-reg-set.h $(REGS_H) \
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2007-01-09 15:01:42.000000000 +0000
+++ gcc/rtl.h	2007-01-09 15:01:56.000000000 +0000
@@ -1678,6 +1678,8 @@ extern int rtx_varies_p (rtx, int);
 extern int rtx_addr_varies_p (rtx, int);
 extern HOST_WIDE_INT get_integer_term (rtx);
 extern rtx get_related_value (rtx);
+extern bool offset_within_block_p (rtx, HOST_WIDE_INT);
+extern void split_const (rtx, rtx *, rtx *);
 extern int reg_mentioned_p (rtx, rtx);
 extern int count_occurrences (rtx, rtx, int);
 extern int reg_referenced_p (rtx, rtx);
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	2007-01-09 15:01:42.000000000 +0000
+++ gcc/rtlanal.c	2007-01-09 15:01:56.000000000 +0000
@@ -37,6 +37,7 @@ Software Foundation; either version 2, o
 #include "real.h"
 #include "regs.h"
 #include "function.h"
+#include "tree.h"
 
 /* Information about a subreg of a hard register.  */
 struct subreg_info
@@ -496,6 +497,61 @@ get_related_value (rtx x)
   return 0;
 }
 
+/* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points
+   to somewhere in the same object or object_block as SYMBOL.  */
+
+bool
+offset_within_block_p (rtx symbol, HOST_WIDE_INT offset)
+{
+  tree decl;
+
+  if (GET_CODE (symbol) != SYMBOL_REF)
+    return false;
+
+  if (offset == 0)
+    return true;
+
+  if (offset > 0)
+    {
+      if (CONSTANT_POOL_ADDRESS_P (symbol)
+	  && offset < (int) GET_MODE_SIZE (get_pool_mode (symbol)))
+	return true;
+
+      decl = SYMBOL_REF_DECL (symbol);
+      if (decl && offset < int_size_in_bytes (TREE_TYPE (decl)))
+	return true;
+    }
+
+  if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol)
+      && SYMBOL_REF_BLOCK (symbol)
+      && SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0
+      && ((unsigned HOST_WIDE_INT) offset + SYMBOL_REF_BLOCK_OFFSET (symbol)
+	  < (unsigned HOST_WIDE_INT) SYMBOL_REF_BLOCK (symbol)->size))
+    return true;
+
+  return false;
+}
+
+/* Split X into a base and a constant offset, storing them in *BASE_OUT
+   and *OFFSET_OUT respectively.  */
+
+void
+split_const (rtx x, rtx *base_out, rtx *offset_out)
+{
+  if (GET_CODE (x) == CONST)
+    {
+      x = XEXP (x, 0);
+      if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
+	{
+	  *base_out = XEXP (x, 0);
+	  *offset_out = XEXP (x, 1);
+	  return;
+	}
+    }
+  *base_out = x;
+  *offset_out = const0_rtx;
+}
+
 /* Return the number of places FIND appears within X.  If COUNT_DEST is
    zero, we do not count occurrences inside the destination of a SET.  */
 
Index: gcc/config/m68k/m68k-protos.h
===================================================================
--- gcc/config/m68k/m68k-protos.h	2007-01-09 15:01:54.000000000 +0000
+++ gcc/config/m68k/m68k-protos.h	2007-01-09 15:01:56.000000000 +0000
@@ -49,6 +49,7 @@ extern int standard_68881_constant_p (rt
 extern void print_operand_address (FILE *, rtx);
 extern void print_operand (FILE *, rtx, int);
 extern void notice_update_cc (rtx, rtx);
+extern bool m68k_illegitimate_symbolic_constant_p (rtx);
 extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
 extern int valid_dbcc_comparison_p_2 (rtx, enum machine_mode);
 extern rtx m68k_libcall_value (enum machine_mode);
Index: gcc/config/m68k/m68k.h
===================================================================
--- gcc/config/m68k/m68k.h	2007-01-09 15:01:56.000000000 +0000
+++ gcc/config/m68k/m68k.h	2007-01-09 15:01:56.000000000 +0000
@@ -770,17 +770,25 @@ #define FP_REG_P(X) (REG_P (X) && REGNO_
 /* 1 if X is an address register  */
 #define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X)))
 
+/* True if SYMBOL + OFFSET constants must refer to something within
+   SYMBOL's section.  */
+#ifndef M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P
+#define M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 0
+#endif
 
 #define MAX_REGS_PER_ADDRESS 2
 
-#define CONSTANT_ADDRESS_P(X)   \
-  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF		\
-   || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST		\
-   || GET_CODE (X) == HIGH)
+#define CONSTANT_ADDRESS_P(X)						\
+  ((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF		\
+    || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST		\
+    || GET_CODE (X) == HIGH)						\
+   && LEGITIMATE_CONSTANT_P (X))
 
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
-#define LEGITIMATE_CONSTANT_P(X) (GET_MODE (X) != XFmode)
+#define LEGITIMATE_CONSTANT_P(X)				\
+  (GET_MODE (X) != XFmode					\
+   && !m68k_illegitimate_symbolic_constant_p (X))
 
 #ifndef REG_OK_STRICT
 #define PCREL_GENERAL_OPERAND_OK 0
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c	2007-01-09 15:01:54.000000000 +0000
+++ gcc/config/m68k/m68k.c	2007-01-09 15:01:56.000000000 +0000
@@ -192,6 +192,9 @@ #define TARGET_PROMOTE_PROTOTYPES hook_b
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX m68k_struct_value_rtx
 
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM m68k_illegitimate_symbolic_constant_p
+
 static const struct attribute_spec m68k_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
@@ -1650,6 +1653,23 @@ output_btst (rtx *operands, rtx countop,
   return "btst %0,%1";
 }
 
+/* Return true if X is an illegitimate symbolic constant.  */
+
+bool
+m68k_illegitimate_symbolic_constant_p (rtx x)
+{
+  rtx base, offset;
+
+  if (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
+    {
+      split_const (x, &base, &offset);
+      if (GET_CODE (base) == SYMBOL_REF
+	  && !offset_within_block_p (base, INTVAL (offset)))
+	return true;
+    }
+  return false;
+}
+
 /* Legitimize PIC addresses.  If the address is already
    position-independent, we return ORIG.  Newly generated
    position-independent addresses go to REG.  If we need more
Index: gcc/config/m68k/m68k.md
===================================================================
--- gcc/config/m68k/m68k.md	2007-01-09 15:01:53.000000000 +0000
+++ gcc/config/m68k/m68k.md	2007-01-09 15:01:56.000000000 +0000
@@ -637,10 +637,12 @@ (define_insn "movsi_const0"
 ;; In both the PIC and non-PIC cases the patterns generated will
 ;; matched by the next define_insn.
 (define_expand "movsi"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "")
-	(match_operand:SI 1 "general_operand" ""))]
+  [(set (match_operand:SI 0 "" "")
+	(match_operand:SI 1 "" ""))]
   ""
 {
+  rtx tmp, base, offset;
+
   if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
     {
       /* The source is an address which requires PIC relocation.
@@ -661,6 +663,18 @@ (define_expand "movsi"
 	operands[0] = gen_rtx_MEM (SImode,
 			       force_reg (SImode, XEXP (operands[0], 0)));
     }
+  if (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
+    {
+      split_const (operands[1], &base, &offset);
+      if (GET_CODE (base) == SYMBOL_REF
+	  && !offset_within_block_p (base, INTVAL (offset)))
+	{
+	  tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
+	  emit_move_insn (tmp, base);
+	  emit_insn (gen_addsi3 (operands[0], tmp, offset));
+	  DONE;
+	}
+    }
 })
 
 ;; General case of fullword move.  The register constraints
Index: gcc/config/m68k/uclinux.h
===================================================================
--- gcc/config/m68k/uclinux.h	2007-01-09 15:01:42.000000000 +0000
+++ gcc/config/m68k/uclinux.h	2007-01-09 15:01:56.000000000 +0000
@@ -63,3 +63,8 @@ #define TARGET_OS_CPP_BUILTINS()		\
     }						\
   while (0)
 
+/* The uclinux binary format relies on relocations against a segment being
+   within that segment.  Conservatively apply this rule to individual
+   sections.  */
+#undef M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P
+#define M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 1
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2007-01-09 15:01:42.000000000 +0000
+++ gcc/config/mips/mips.c	2007-01-09 15:01:56.000000000 +0000
@@ -267,8 +267,6 @@ struct mips_integer_op;
 struct mips_sim;
 
 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_valid_base_register_p (rtx, enum machine_mode, int);
 static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
 static bool mips_classify_address (struct mips_address_info *, rtx,
@@ -1311,58 +1309,6 @@ mips_classify_symbol (rtx x)
   return SYMBOL_GENERAL;
 }
 
-
-/* Split X into a base and a constant offset, storing them in *BASE
-   and *OFFSET respectively.  */
-
-static void
-mips_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset)
-{
-  *offset = 0;
-
-  if (GET_CODE (x) == CONST)
-    {
-      x = XEXP (x, 0);
-      if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
-	{
-	  *offset += INTVAL (XEXP (x, 1));
-	  x = XEXP (x, 0);
-	}
-    }
-  *base = x;
-}
-
-
-/* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points
-   to the same object as SYMBOL, or to the same object_block.  */
-
-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;
-
-  if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol)
-      && SYMBOL_REF_BLOCK (symbol)
-      && SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0
-      && ((unsigned HOST_WIDE_INT) offset + SYMBOL_REF_BLOCK_OFFSET (symbol)
-	  < (unsigned HOST_WIDE_INT) SYMBOL_REF_BLOCK (symbol)->size))
-    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.  */
@@ -1370,9 +1316,9 @@ mips_offset_within_object_p (rtx symbol,
 bool
 mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
 {
-  HOST_WIDE_INT offset;
+  rtx offset;
 
-  mips_split_const (x, &x, &offset);
+  split_const (x, &x, &offset);
   if (UNSPEC_ADDRESS_P (x))
     *symbol_type = UNSPEC_ADDRESS_TYPE (x);
   else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
@@ -1384,7 +1330,7 @@ mips_symbolic_constant_p (rtx x, enum mi
   else
     return false;
 
-  if (offset == 0)
+  if (offset == const0_rtx)
     return true;
 
   /* Check whether a nonzero offset is valid for the underlying
@@ -1400,7 +1346,7 @@ mips_symbolic_constant_p (rtx x, enum mi
 	 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);
+	return offset_within_block_p (x, INTVAL (offset));
 
       /* In other cases the relocations can handle any offset.  */
       return true;
@@ -1416,15 +1362,15 @@ mips_symbolic_constant_p (rtx x, enum mi
 
     case SYMBOL_SMALL_DATA:
       /* Make sure that the offset refers to something within the
-	 underlying object.  This should guarantee that the final
+	 same object block.  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);
+      return offset_within_block_p (x, INTVAL (offset));
 
     case SYMBOL_GOT_LOCAL:
     case SYMBOL_GOTOFF_PAGE:
       /* The linker should provide enough local GOT entries for a
 	 16-bit offset.  Larger offsets may lead to GOT overflow.  */
-      return SMALL_OPERAND (offset);
+      return SMALL_INT (offset);
 
     case SYMBOL_GOT_GLOBAL:
     case SYMBOL_GOTOFF_GLOBAL:
@@ -1614,8 +1560,7 @@ mips_tls_symbol_ref_1 (rtx *x, void *dat
 static bool
 mips_cannot_force_const_mem (rtx x)
 {
-  rtx base;
-  HOST_WIDE_INT offset;
+  rtx base, offset;
 
   if (!TARGET_MIPS16)
     {
@@ -1631,8 +1576,8 @@ mips_cannot_force_const_mem (rtx x)
       if (GET_CODE (x) == CONST_INT)
 	return true;
 
-      mips_split_const (x, &base, &offset);
-      if (symbolic_operand (base, VOIDmode) && SMALL_OPERAND (offset))
+      split_const (x, &base, &offset);
+      if (symbolic_operand (base, VOIDmode) && SMALL_INT (offset))
 	return true;
     }
 
@@ -1819,7 +1764,7 @@ mips_const_insns (rtx x)
 {
   struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS];
   enum mips_symbol_type symbol_type;
-  HOST_WIDE_INT offset;
+  rtx offset;
 
   switch (GET_CODE (x))
     {
@@ -1860,16 +1805,16 @@ mips_const_insns (rtx x)
       /* Otherwise try splitting the constant into a base and offset.
 	 16-bit offsets can be added using an extra addiu.  Larger offsets
 	 must be calculated separately and then added to the base.  */
-      mips_split_const (x, &x, &offset);
+      split_const (x, &x, &offset);
       if (offset != 0)
 	{
 	  int n = mips_const_insns (x);
 	  if (n != 0)
 	    {
-	      if (SMALL_OPERAND (offset))
+	      if (SMALL_INT (offset))
 		return n + 1;
 	      else
-		return n + 1 + mips_build_integer (codes, offset);
+		return n + 1 + mips_build_integer (codes, INTVAL (offset));
 	    }
 	}
       return 0;
@@ -1968,13 +1913,14 @@ mips_split_symbol (rtx temp, rtx addr)
 rtx
 mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
 {
-  rtx base;
-  HOST_WIDE_INT offset;
+  rtx base, offset;
 
-  mips_split_const (address, &base, &offset);
+  split_const (address, &base, &offset);
   base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
 			 UNSPEC_ADDRESS_FIRST + symbol_type);
-  return plus_constant (gen_rtx_CONST (Pmode, base), offset);
+  if (offset != const0_rtx)
+    base = gen_rtx_PLUS (Pmode, base, offset);
+  return gen_rtx_CONST (Pmode, base);
 }
 
 
@@ -2322,8 +2268,7 @@ mips_move_integer (rtx dest, rtx temp, u
 static void
 mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
 {
-  rtx base;
-  HOST_WIDE_INT offset;
+  rtx base, offset;
 
   /* Split moves of big integers into smaller pieces.  */
   if (splittable_const_int_operand (src, mode))
@@ -2348,13 +2293,13 @@ mips_legitimize_const_move (enum machine
   /* If we have (const (plus symbol offset)), load the symbol first
      and then add in the offset.  This is usually better than forcing
      the constant into memory, at least in non-mips16 code.  */
-  mips_split_const (src, &base, &offset);
+  split_const (src, &base, &offset);
   if (!TARGET_MIPS16
-      && offset != 0
-      && (!no_new_pseudos || SMALL_OPERAND (offset)))
+      && offset != const0_rtx
+      && (!no_new_pseudos || SMALL_INT (offset)))
     {
       base = mips_force_temporary (dest, base);
-      emit_move_insn (dest, mips_add_offset (0, base, offset));
+      emit_move_insn (dest, mips_add_offset (0, base, INTVAL (offset)));
       return;
     }
 
@@ -5728,16 +5673,15 @@ print_operand_reloc (FILE *file, rtx op,
 {
   enum mips_symbol_type symbol_type;
   const char *p;
-  rtx base;
-  HOST_WIDE_INT offset;
+  rtx base, offset;
 
   if (!mips_symbolic_constant_p (op, &symbol_type) || relocs[symbol_type] == 0)
     fatal_insn ("PRINT_OPERAND, invalid operand for relocation", op);
 
   /* If OP uses an UNSPEC address, we want to print the inner symbol.  */
-  mips_split_const (op, &base, &offset);
+  split_const (op, &base, &offset);
   if (UNSPEC_ADDRESS_P (base))
-    op = plus_constant (UNSPEC_ADDRESS (base), offset);
+    op = plus_constant (UNSPEC_ADDRESS (base), INTVAL (offset));
 
   fputs (relocs[symbol_type], file);
   output_addr_const (file, op);
@@ -7713,12 +7657,12 @@ mips_cannot_change_mode_class (enum mach
 bool
 mips_dangerous_for_la25_p (rtx x)
 {
-  HOST_WIDE_INT offset;
+  rtx offset;
 
   if (TARGET_EXPLICIT_RELOCS)
     return false;
 
-  mips_split_const (x, &x, &offset);
+  split_const (x, &x, &offset);
   return global_got_operand (x, VOIDmode);
 }
 



More information about the Gcc-patches mailing list