reload.c (operands_match_p): Handle rtvecs.
* reload.c (operands_match_p): Handle rtvecs. * i386.c (legitimate_pic_address_disp_p): New. (legitimate_address_p): Use it. (legitimize_pic_address): Use unspecs to represent @GOT and @GOTOFF. Handle constant pool symbols just like statics. (emit_pic_move): Use Pmode not SImode for clarity. (output_pic_addr_const) [SYMBOL_REF]: Remove @GOT and @GOTOFF hacks. [UNSPEC]: New, handling what we killed above. [PLUS]: Detect and abort on invalid symbol arithmetic. * i386.h (CONSTANT_ADDRESS_P): Remove HIGH. From-SVN: r21968
This commit is contained in:
parent
264fac3496
commit
91bb873f6a
5 changed files with 208 additions and 112 deletions
|
@ -1,3 +1,17 @@
|
|||
Tue Aug 25 12:23:20 PDT 1998 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* reload.c (operands_match_p): Handle rtvecs.
|
||||
|
||||
* i386.c (legitimate_pic_address_disp_p): New.
|
||||
(legitimate_address_p): Use it.
|
||||
(legitimize_pic_address): Use unspecs to represent @GOT and @GOTOFF.
|
||||
Handle constant pool symbols just like statics.
|
||||
(emit_pic_move): Use Pmode not SImode for clarity.
|
||||
(output_pic_addr_const) [SYMBOL_REF]: Remove @GOT and @GOTOFF hacks.
|
||||
[UNSPEC]: New, handling what we killed above.
|
||||
[PLUS]: Detect and abort on invalid symbol arithmetic.
|
||||
* i386.h (CONSTANT_ADDRESS_P): Remove HIGH.
|
||||
|
||||
Tue Aug 25 12:02:23 1998 Mark Mitchell <mark@markmitchell.com>
|
||||
|
||||
* alias.c: Include output.h.
|
||||
|
|
|
@ -2507,6 +2507,37 @@ do { \
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
static int
|
||||
legitimate_pic_address_disp_p (disp)
|
||||
register rtx disp;
|
||||
{
|
||||
if (GET_CODE (disp) != CONST)
|
||||
return 0;
|
||||
disp = XEXP (disp, 0);
|
||||
|
||||
if (GET_CODE (disp) == PLUS)
|
||||
{
|
||||
if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
|
||||
return 0;
|
||||
disp = XEXP (disp, 0);
|
||||
}
|
||||
|
||||
if (GET_CODE (disp) != UNSPEC
|
||||
|| XVECLEN (disp, 0) != 1)
|
||||
return 0;
|
||||
|
||||
/* Must be @GOT or @GOTOFF. */
|
||||
if (XINT (disp, 1) != 6
|
||||
&& XINT (disp, 1) != 7)
|
||||
return 0;
|
||||
|
||||
if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
|
||||
&& GET_CODE (XVECEXP (disp, 0, 0)) != LABEL_REF)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
legitimate_address_p (mode, addr, strict)
|
||||
enum machine_mode mode;
|
||||
|
@ -2668,20 +2699,10 @@ legitimate_address_p (mode, addr, strict)
|
|||
}
|
||||
}
|
||||
|
||||
/* Validate displacement
|
||||
Constant pool addresses must be handled special. They are
|
||||
considered legitimate addresses, but only if not used with regs.
|
||||
When printed, the output routines know to print the reference with the
|
||||
PIC reg, even though the PIC reg doesn't appear in the RTL. */
|
||||
/* Validate displacement. */
|
||||
if (disp)
|
||||
{
|
||||
if (GET_CODE (disp) == SYMBOL_REF
|
||||
&& CONSTANT_POOL_ADDRESS_P (disp)
|
||||
&& base == 0
|
||||
&& indx == 0)
|
||||
;
|
||||
|
||||
else if (!CONSTANT_ADDRESS_P (disp))
|
||||
if (!CONSTANT_ADDRESS_P (disp))
|
||||
{
|
||||
ADDR_INVALID ("Displacement is not valid.\n", disp);
|
||||
return FALSE;
|
||||
|
@ -2693,20 +2714,32 @@ legitimate_address_p (mode, addr, strict)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
else if (flag_pic && SYMBOLIC_CONST (disp)
|
||||
&& base != pic_offset_table_rtx
|
||||
&& (indx != pic_offset_table_rtx || scale != NULL_RTX))
|
||||
if (flag_pic && SYMBOLIC_CONST (disp))
|
||||
{
|
||||
ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
|
||||
return FALSE;
|
||||
if (! legitimate_pic_address_disp_p (disp))
|
||||
{
|
||||
ADDR_INVALID ("Displacement is an invalid PIC construct.\n",
|
||||
disp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (base != pic_offset_table_rtx
|
||||
&& (indx != pic_offset_table_rtx || scale != NULL_RTX))
|
||||
{
|
||||
ADDR_INVALID ("PIC displacement against invalid base.\n", disp);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
else if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
|
||||
&& (base != NULL_RTX || indx != NULL_RTX))
|
||||
else if (HALF_PIC_P ())
|
||||
{
|
||||
ADDR_INVALID ("Displacement is an invalid half-pic reference.\n",
|
||||
disp);
|
||||
return FALSE;
|
||||
if (! HALF_PIC_ADDRESS_P (disp)
|
||||
|| (base != NULL_RTX || indx != NULL_RTX))
|
||||
{
|
||||
ADDR_INVALID ("Displacement is an invalid half-pic reference.\n",
|
||||
disp);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2720,29 +2753,20 @@ legitimate_address_p (mode, addr, strict)
|
|||
/* Return a legitimate reference for ORIG (an address) using the
|
||||
register REG. If REG is 0, a new pseudo is generated.
|
||||
|
||||
There are three types of references that must be handled:
|
||||
There are two types of references that must be handled:
|
||||
|
||||
1. Global data references must load the address from the GOT, via
|
||||
the PIC reg. An insn is emitted to do this load, and the reg is
|
||||
returned.
|
||||
|
||||
2. Static data references must compute the address as an offset
|
||||
from the GOT, whose base is in the PIC reg. An insn is emitted to
|
||||
compute the address into a reg, and the reg is returned. Static
|
||||
data objects have SYMBOL_REF_FLAG set to differentiate them from
|
||||
global data objects.
|
||||
|
||||
3. Constant pool addresses must be handled special. They are
|
||||
considered legitimate addresses, but only if not used with regs.
|
||||
When printed, the output routines know to print the reference with the
|
||||
PIC reg, even though the PIC reg doesn't appear in the RTL.
|
||||
2. Static data references, constant pool addresses, and code labels
|
||||
compute the address as an offset from the GOT, whose base is in
|
||||
the PIC reg. Static data objects have SYMBOL_REF_FLAG set to
|
||||
differentiate them from global data objects. The returned
|
||||
address is the PIC reg + an unspec constant.
|
||||
|
||||
GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
|
||||
reg also appears in the address (except for constant pool references,
|
||||
noted above).
|
||||
|
||||
"switch" statements also require special handling when generating
|
||||
PIC code. See comments by the `casesi' insn in i386.md for details. */
|
||||
reg also appears in the address. */
|
||||
|
||||
rtx
|
||||
legitimize_pic_address (orig, reg)
|
||||
|
@ -2751,60 +2775,99 @@ legitimize_pic_address (orig, reg)
|
|||
{
|
||||
rtx addr = orig;
|
||||
rtx new = orig;
|
||||
rtx base;
|
||||
|
||||
if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
|
||||
if (GET_CODE (addr) == LABEL_REF
|
||||
|| (GET_CODE (addr) == SYMBOL_REF
|
||||
&& (CONSTANT_POOL_ADDRESS_P (addr)
|
||||
|| SYMBOL_REF_FLAG (addr))))
|
||||
{
|
||||
if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
|
||||
reg = new = orig;
|
||||
else
|
||||
{
|
||||
if (reg == 0)
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
/* This symbol may be referenced via a displacement from the PIC
|
||||
base address (@GOTOFF). */
|
||||
|
||||
if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
|
||||
|| GET_CODE (addr) == LABEL_REF)
|
||||
new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
|
||||
else
|
||||
new = gen_rtx_MEM (Pmode,
|
||||
gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig));
|
||||
|
||||
emit_move_insn (reg, new);
|
||||
}
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
return reg;
|
||||
}
|
||||
new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, addr), 7);
|
||||
new = gen_rtx_CONST (VOIDmode, new);
|
||||
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
|
||||
|
||||
else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
|
||||
{
|
||||
rtx base;
|
||||
|
||||
if (GET_CODE (addr) == CONST)
|
||||
if (reg != 0)
|
||||
{
|
||||
addr = XEXP (addr, 0);
|
||||
if (GET_CODE (addr) != PLUS)
|
||||
abort ();
|
||||
emit_move_insn (reg, new);
|
||||
new = reg;
|
||||
}
|
||||
}
|
||||
else if (GET_CODE (addr) == SYMBOL_REF)
|
||||
{
|
||||
/* This symbol must be referenced via a load from the
|
||||
Global Offset Table (@GOT). */
|
||||
|
||||
if (XEXP (addr, 0) == pic_offset_table_rtx)
|
||||
return orig;
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, addr), 6);
|
||||
new = gen_rtx_CONST (VOIDmode, new);
|
||||
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
|
||||
new = gen_rtx_MEM (Pmode, new);
|
||||
RTX_UNCHANGING_P (new) = 1;
|
||||
|
||||
if (reg == 0)
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
|
||||
base = legitimize_pic_address (XEXP (addr, 0), reg);
|
||||
addr = legitimize_pic_address (XEXP (addr, 1),
|
||||
base == reg ? NULL_RTX : reg);
|
||||
|
||||
if (GET_CODE (addr) == CONST_INT)
|
||||
return plus_constant (base, INTVAL (addr));
|
||||
|
||||
if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
|
||||
emit_move_insn (reg, new);
|
||||
new = reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GET_CODE (addr) == CONST)
|
||||
{
|
||||
base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
|
||||
addr = XEXP (addr, 1);
|
||||
addr = XEXP (addr, 0);
|
||||
if (GET_CODE (addr) == UNSPEC)
|
||||
{
|
||||
/* Check that the unspec is one of the ones we generate? */
|
||||
}
|
||||
else if (GET_CODE (addr) != PLUS)
|
||||
abort();
|
||||
}
|
||||
if (GET_CODE (addr) == PLUS)
|
||||
{
|
||||
rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
|
||||
|
||||
return gen_rtx (PLUS, Pmode, base, addr);
|
||||
/* Check first to see if this is a constant offset from a @GOTOFF
|
||||
symbol reference. */
|
||||
if ((GET_CODE (op0) == LABEL_REF
|
||||
|| (GET_CODE (op0) == SYMBOL_REF
|
||||
&& (CONSTANT_POOL_ADDRESS_P (op0)
|
||||
|| SYMBOL_REF_FLAG (op0))))
|
||||
&& GET_CODE (op1) == CONST_INT)
|
||||
{
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, op0), 7);
|
||||
new = gen_rtx_PLUS (VOIDmode, new, op1);
|
||||
new = gen_rtx_CONST (VOIDmode, new);
|
||||
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
|
||||
|
||||
if (reg != 0)
|
||||
{
|
||||
emit_move_insn (reg, new);
|
||||
new = reg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base = legitimize_pic_address (XEXP (addr, 0), reg);
|
||||
new = legitimize_pic_address (XEXP (addr, 1),
|
||||
base == reg ? NULL_RTX : reg);
|
||||
|
||||
if (GET_CODE (new) == CONST_INT)
|
||||
new = plus_constant (base, INTVAL (new));
|
||||
else
|
||||
{
|
||||
if (GET_CODE (new) == PLUS && CONSTANT_P (XEXP (new, 1)))
|
||||
{
|
||||
base = gen_rtx_PLUS (Pmode, base, XEXP (new, 0));
|
||||
new = XEXP (new, 1);
|
||||
}
|
||||
new = gen_rtx_PLUS (Pmode, base, new);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
@ -2819,7 +2882,7 @@ emit_pic_move (operands, mode)
|
|||
rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
|
||||
|
||||
if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
|
||||
operands[1] = force_reg (SImode, operands[1]);
|
||||
operands[1] = force_reg (Pmode, operands[1]);
|
||||
else
|
||||
operands[1] = legitimize_pic_address (operands[1], temp);
|
||||
}
|
||||
|
@ -3032,31 +3095,14 @@ output_pic_addr_const (file, x, code)
|
|||
break;
|
||||
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
if (GET_CODE (x) == SYMBOL_REF)
|
||||
assemble_name (file, XSTR (x, 0));
|
||||
else
|
||||
{
|
||||
ASM_GENERATE_INTERNAL_LABEL (buf, "L",
|
||||
CODE_LABEL_NUMBER (XEXP (x, 0)));
|
||||
assemble_name (asm_out_file, buf);
|
||||
}
|
||||
|
||||
if (code == 'X')
|
||||
; /* No suffix, dammit. */
|
||||
else if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
|
||||
fprintf (file, "@GOTOFF(%%ebx)");
|
||||
else if (code == 'P')
|
||||
fprintf (file, "@PLT");
|
||||
else if (GET_CODE (x) == LABEL_REF)
|
||||
fprintf (file, "@GOTOFF");
|
||||
else if (! SYMBOL_REF_FLAG (x))
|
||||
fprintf (file, "@GOT");
|
||||
else
|
||||
fprintf (file, "@GOTOFF");
|
||||
|
||||
assemble_name (file, XSTR (x, 0));
|
||||
if (code == 'P' && ! SYMBOL_REF_FLAG (x))
|
||||
fputs ("@PLT", file);
|
||||
break;
|
||||
|
||||
case LABEL_REF:
|
||||
x = XEXP (x, 0);
|
||||
/* FALLTHRU */
|
||||
case CODE_LABEL:
|
||||
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
|
||||
assemble_name (asm_out_file, buf);
|
||||
|
@ -3094,17 +3140,17 @@ output_pic_addr_const (file, x, code)
|
|||
if (GET_CODE (XEXP (x, 0)) == CONST_INT)
|
||||
{
|
||||
output_pic_addr_const (file, XEXP (x, 0), code);
|
||||
if (INTVAL (XEXP (x, 1)) >= 0)
|
||||
fprintf (file, "+");
|
||||
fprintf (file, "+");
|
||||
output_pic_addr_const (file, XEXP (x, 1), code);
|
||||
}
|
||||
else
|
||||
else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
output_pic_addr_const (file, XEXP (x, 1), code);
|
||||
if (INTVAL (XEXP (x, 0)) >= 0)
|
||||
fprintf (file, "+");
|
||||
fprintf (file, "+");
|
||||
output_pic_addr_const (file, XEXP (x, 0), code);
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
break;
|
||||
|
||||
case MINUS:
|
||||
|
@ -3113,6 +3159,27 @@ output_pic_addr_const (file, x, code)
|
|||
output_pic_addr_const (file, XEXP (x, 1), code);
|
||||
break;
|
||||
|
||||
case UNSPEC:
|
||||
if (XVECLEN (x, 0) != 1)
|
||||
abort ();
|
||||
output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
|
||||
switch (XINT (x, 1))
|
||||
{
|
||||
case 6:
|
||||
fputs ("@GOT", file);
|
||||
break;
|
||||
case 7:
|
||||
fputs ("@GOTOFF", file);
|
||||
break;
|
||||
case 8:
|
||||
fputs ("@PLT", file);
|
||||
break;
|
||||
default:
|
||||
output_operand_lossage ("invalid UNSPEC as operand");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
output_operand_lossage ("invalid expression as operand");
|
||||
}
|
||||
|
|
|
@ -1703,10 +1703,9 @@ do { \
|
|||
|
||||
#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)
|
||||
|
||||
/* Nonzero if the constant value X is a legitimate general operand.
|
||||
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
;; prevent insns referencing it being scheduled across the initial
|
||||
;; decrement of the stack pointer.
|
||||
;; 5 This is a `bsf' operation.
|
||||
;; 6 This is the @GOT offset of a PIC address.
|
||||
;; 7 This is the @GOTOFF offset of a PIC address.
|
||||
;; 8 This is a reference to a symbol's @PLT address.
|
||||
|
||||
;; This shadows the processor_type enumeration, so changes must be made
|
||||
;; to i386.h at the same time.
|
||||
|
|
15
gcc/reload.c
15
gcc/reload.c
|
@ -2031,7 +2031,7 @@ operands_match_p (x, y)
|
|||
fmt = GET_RTX_FORMAT (code);
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
{
|
||||
int val;
|
||||
int val, j;
|
||||
switch (fmt[i])
|
||||
{
|
||||
case 'w':
|
||||
|
@ -2057,6 +2057,19 @@ operands_match_p (x, y)
|
|||
case '0':
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
if (XVECLEN (x, i) != XVECLEN (y, i))
|
||||
return 0;
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; --j)
|
||||
{
|
||||
val = operands_match_p (XVECEXP (x, i, j), XVECEXP (y, i, j));
|
||||
if (val == 0)
|
||||
return 0;
|
||||
if (val == 2)
|
||||
success_2 = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* It is believed that rtx's at this level will never
|
||||
contain anything but integers and other rtx's,
|
||||
except for within LABEL_REFs and SYMBOL_REFs. */
|
||||
|
|
Loading…
Add table
Reference in a new issue