/* In the name of slightly smaller debug output, and to cater to
general assembler lossage, recognize PIC+GOTOFF and turn it back
- into a direct symbol reference. */
+ into a direct symbol reference.
+
+ On Darwin, this is necessary to avoid a crash, because Darwin
+ has a different PIC label for each routine but the DWARF debugging
+ information is not associated with any particular routine, so it's
+ necessary to remove references to the PIC label from RTL stored by
+ the DWARF output code. */
static rtx
ix86_delegitimize_address (rtx orig_x)
{
- rtx x = orig_x, y;
+ rtx x = orig_x;
+ /* reg_addend is NULL or a multiple of some register. */
+ rtx reg_addend = NULL_RTX;
+ /* const_addend is NULL or a const_int. */
+ rtx const_addend = NULL_RTX;
+ /* This is the result, or NULL. */
+ rtx result = NULL_RTX;
if (GET_CODE (x) == MEM)
x = XEXP (x, 0);
if (GET_CODE (XEXP (x, 0)) == REG
&& REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
/* %ebx + GOT/GOTOFF */
- y = NULL;
+ ;
else if (GET_CODE (XEXP (x, 0)) == PLUS)
{
/* %ebx + %reg * scale + GOT/GOTOFF */
- y = XEXP (x, 0);
- if (GET_CODE (XEXP (y, 0)) == REG
- && REGNO (XEXP (y, 0)) == PIC_OFFSET_TABLE_REGNUM)
- y = XEXP (y, 1);
- else if (GET_CODE (XEXP (y, 1)) == REG
- && REGNO (XEXP (y, 1)) == PIC_OFFSET_TABLE_REGNUM)
- y = XEXP (y, 0);
+ reg_addend = XEXP (x, 0);
+ if (GET_CODE (XEXP (reg_addend, 0)) == REG
+ && REGNO (XEXP (reg_addend, 0)) == PIC_OFFSET_TABLE_REGNUM)
+ reg_addend = XEXP (reg_addend, 1);
+ else if (GET_CODE (XEXP (reg_addend, 1)) == REG
+ && REGNO (XEXP (reg_addend, 1)) == PIC_OFFSET_TABLE_REGNUM)
+ reg_addend = XEXP (reg_addend, 0);
else
return orig_x;
- if (GET_CODE (y) != REG
- && GET_CODE (y) != MULT
- && GET_CODE (y) != ASHIFT)
+ if (GET_CODE (reg_addend) != REG
+ && GET_CODE (reg_addend) != MULT
+ && GET_CODE (reg_addend) != ASHIFT)
return orig_x;
}
else
return orig_x;
x = XEXP (XEXP (x, 1), 0);
- if (GET_CODE (x) == UNSPEC
- && ((XINT (x, 1) == UNSPEC_GOT && GET_CODE (orig_x) == MEM)
- || (XINT (x, 1) == UNSPEC_GOTOFF && GET_CODE (orig_x) != MEM)))
- {
- if (y)
- return gen_rtx_PLUS (Pmode, y, XVECEXP (x, 0, 0));
- return XVECEXP (x, 0, 0);
- }
-
if (GET_CODE (x) == PLUS
- && GET_CODE (XEXP (x, 0)) == UNSPEC
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && ((XINT (XEXP (x, 0), 1) == UNSPEC_GOT && GET_CODE (orig_x) == MEM)
- || (XINT (XEXP (x, 0), 1) == UNSPEC_GOTOFF
- && GET_CODE (orig_x) != MEM)))
+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
{
- x = gen_rtx_PLUS (VOIDmode, XVECEXP (XEXP (x, 0), 0, 0), XEXP (x, 1));
- if (y)
- return gen_rtx_PLUS (Pmode, y, x);
- return x;
+ const_addend = XEXP (x, 1);
+ x = XEXP (x, 0);
}
+ if (GET_CODE (x) == UNSPEC
+ && ((XINT (x, 1) == UNSPEC_GOT && GET_CODE (orig_x) == MEM)
+ || (XINT (x, 1) == UNSPEC_GOTOFF && GET_CODE (orig_x) != MEM)))
+ result = XVECEXP (x, 0, 0);
+
if (TARGET_MACHO && darwin_local_data_pic (x)
&& GET_CODE (orig_x) != MEM)
- {
- x = XEXP (x, 0);
- if (y)
- return gen_rtx_PLUS (Pmode, y, x);
- return x;
- }
- return orig_x;
+ result = XEXP (x, 0);
+
+ if (! result)
+ return orig_x;
+
+ if (const_addend)
+ result = gen_rtx_PLUS (Pmode, result, const_addend);
+ if (reg_addend)
+ result = gen_rtx_PLUS (Pmode, reg_addend, result);
+ return result;
}
\f
static void