summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000/rs6000.cc')
-rw-r--r--gcc/config/rs6000/rs6000.cc38
1 files changed, 36 insertions, 2 deletions
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index eaba9a2d698..bc3ef0721a4 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -8317,8 +8317,14 @@ darwin_rs6000_legitimate_lo_sum_const_p (rtx x, machine_mode mode)
if (GET_CODE (x) == CONST)
x = XEXP (x, 0);
+ /* If we are building PIC code, then any symbol must be wrapped in an
+ UNSPEC_MACHOPIC_OFFSET so that it will get the picbase subtracted. */
+ bool machopic_offs_p = false;
if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_MACHOPIC_OFFSET)
- x = XVECEXP (x, 0, 0);
+ {
+ x = XVECEXP (x, 0, 0);
+ machopic_offs_p = true;
+ }
rtx sym = NULL_RTX;
unsigned HOST_WIDE_INT offset = 0;
@@ -8349,6 +8355,9 @@ darwin_rs6000_legitimate_lo_sum_const_p (rtx x, machine_mode mode)
if (sym)
{
tree decl = SYMBOL_REF_DECL (sym);
+ /* As noted above, PIC code cannot use a bare SYMBOL_REF. */
+ if (TARGET_MACHO && flag_pic && !machopic_offs_p)
+ return false;
#if TARGET_MACHO
if (MACHO_SYMBOL_INDIRECTION_P (sym))
/* The decl in an indirection symbol is the original one, which might
@@ -8936,7 +8945,7 @@ legitimate_lo_sum_address_p (machine_mode mode, rtx x, int strict)
return false;
x = XEXP (x, 1);
- if (TARGET_ELF || TARGET_MACHO)
+ if (TARGET_ELF)
{
bool large_toc_ok;
@@ -8962,7 +8971,32 @@ legitimate_lo_sum_address_p (machine_mode mode, rtx x, int strict)
return CONSTANT_P (x) || large_toc_ok;
}
+ else if (TARGET_MACHO)
+ {
+ if (GET_MODE_NUNITS (mode) != 1)
+ return false;
+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
+ && !(/* see above */
+ TARGET_HARD_FLOAT && (mode == DFmode || mode == DDmode)))
+ return false;
+#if TARGET_MACHO
+ if (MACHO_DYNAMIC_NO_PIC_P || !flag_pic)
+ return CONSTANT_P (x);
+#endif
+ /* Macho-O PIC code from here. */
+ if (GET_CODE (x) == CONST)
+ x = XEXP (x, 0);
+
+ /* SYMBOL_REFs need to be wrapped in an UNSPEC_MACHOPIC_OFFSET. */
+ if (SYMBOL_REF_P (x))
+ return false;
+ /* So this is OK if the wrapped object is const. */
+ if (GET_CODE (x) == UNSPEC
+ && XINT (x, 1) == UNSPEC_MACHOPIC_OFFSET)
+ return CONSTANT_P (XVECEXP (x, 0, 0));
+ return CONSTANT_P (x);
+ }
return false;
}