Workaround PR middle-end/55142

gcc/

2012-11-19  H.J. Lu  <hongjiu.lu@intel.com>

	Backported from mainline
	2012-11-13  Eric Botcazou  <ebotcazou@adacore.com>
		    H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/55142
	* config/i386/i386.c (legitimize_pic_address): Properly handle
	REG + CONST.
	(ix86_print_operand_address): Set code to 'k' when forcing
	addr32 prefix.  For x32, zero-extend negative displacement if
	it < -16*1024*1024.

gcc/testsuite/

2012-11-19  H.J. Lu  <hongjiu.lu@intel.com>

	Backported from mainline
	2012-11-13  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/55142
	* gcc.target/i386/pr55142-1.c: New file.
	* gcc.target/i386/pr55142-2.c: Likewise.

From-SVN: r193635
This commit is contained in:
H.J. Lu 2012-11-19 19:17:05 +00:00 committed by H.J. Lu
parent ffafac224c
commit 7b7d1fb9b2
5 changed files with 133 additions and 9 deletions

View File

@ -1,3 +1,16 @@
2012-11-19 H.J. Lu <hongjiu.lu@intel.com>
Backported from mainline
2012-11-13 Eric Botcazou <ebotcazou@adacore.com>
H.J. Lu <hongjiu.lu@intel.com>
PR middle-end/55142
* config/i386/i386.c (legitimize_pic_address): Properly handle
REG + CONST.
(ix86_print_operand_address): Set code to 'k' when forcing
addr32 prefix. For x32, zero-extend negative displacement if
it < -16*1024*1024.
2012-11-12 Eric Botcazou <ebotcazou@adacore.com>
* common.opt (fvar-tracking-uninit): Document.

View File

@ -12330,7 +12330,6 @@ legitimize_pic_address (rtx orig, rtx reg)
{
rtx addr = orig;
rtx new_rtx = orig;
rtx base;
#if TARGET_MACHO
if (TARGET_MACHO && !TARGET_64BIT)
@ -12535,20 +12534,33 @@ legitimize_pic_address (rtx orig, rtx reg)
}
else
{
base = legitimize_pic_address (XEXP (addr, 0), reg);
new_rtx = legitimize_pic_address (XEXP (addr, 1),
base == reg ? NULL_RTX : reg);
rtx base = legitimize_pic_address (op0, reg);
enum machine_mode mode = GET_MODE (base);
new_rtx
= legitimize_pic_address (op1, base == reg ? NULL_RTX : reg);
if (CONST_INT_P (new_rtx))
new_rtx = plus_constant (base, INTVAL (new_rtx));
{
if (INTVAL (new_rtx) < -16*1024*1024
|| INTVAL (new_rtx) >= 16*1024*1024)
{
if (!x86_64_immediate_operand (new_rtx, mode))
new_rtx = force_reg (mode, new_rtx);
new_rtx
= gen_rtx_PLUS (mode, force_reg (mode, base), new_rtx);
}
else
new_rtx = plus_constant (base, INTVAL (new_rtx));
}
else
{
if (GET_CODE (new_rtx) == PLUS && CONSTANT_P (XEXP (new_rtx, 1)))
if (GET_CODE (new_rtx) == PLUS
&& CONSTANT_P (XEXP (new_rtx, 1)))
{
base = gen_rtx_PLUS (Pmode, base, XEXP (new_rtx, 0));
base = gen_rtx_PLUS (mode, base, XEXP (new_rtx, 0));
new_rtx = XEXP (new_rtx, 1);
}
new_rtx = gen_rtx_PLUS (Pmode, base, new_rtx);
new_rtx = gen_rtx_PLUS (mode, base, new_rtx);
}
}
}
@ -14642,7 +14654,30 @@ ix86_print_operand_address (FILE *file, rtx addr)
}
#endif
gcc_assert (!code);
code = 'l';
code = 'k';
}
else if (code == 0
&& TARGET_X32
&& disp
&& CONST_INT_P (disp)
&& INTVAL (disp) < -16*1024*1024)
{
/* X32 runs in 64-bit mode, where displacement, DISP, in
address DISP(%r64), is encoded as 32-bit immediate sign-
extended from 32-bit to 64-bit. For -0x40000300(%r64),
address is %r64 + 0xffffffffbffffd00. When %r64 <
0x40000300, like 0x37ffe064, address is 0xfffffffff7ffdd64,
which is invalid for x32. The correct address is %r64
- 0x40000300 == 0xf7ffdd64. To properly encode
-0x40000300(%r64) for x32, we zero-extend negative
displacement by forcing addr32 prefix which truncates
0xfffffffff7ffdd64 to 0xf7ffdd64. In theory, we should
zero-extend all negative displacements, including -1(%rsp).
However, for small negative displacements, sign-extension
won't cause overflow. We only zero-extend negative
displacements if they < -16*1024*1024, which is also used
to check legitimate address displacements for PIC. */
code = 'k';
}
if (ASSEMBLER_DIALECT == ASM_ATT)

View File

@ -1,3 +1,12 @@
2012-11-19 H.J. Lu <hongjiu.lu@intel.com>
Backported from mainline
2012-11-13 H.J. Lu <hongjiu.lu@intel.com>
PR middle-end/55142
* gcc.target/i386/pr55142-1.c: New file.
* gcc.target/i386/pr55142-2.c: Likewise.
2012-11-09 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/stack_check3.ad[sb]: New test.

View File

@ -0,0 +1,34 @@
/* { dg-do compile { target { ! { ia32 } } } } */
/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -mx32 -fpic" } */
typedef int int32_t;
typedef unsigned int uint32_t;
typedef int32_t Elf32_Sword;
typedef struct
{
Elf32_Sword d_tag;
} Elf32_Dyn;
struct link_map
{
Elf32_Dyn *l_ld;
Elf32_Dyn *l_info[34];
};
extern struct link_map _dl_rtld_map __attribute__ ((visibility ("hidden")));
static void elf_get_dynamic_info (struct link_map *l)
{
Elf32_Dyn *dyn = l->l_ld;
Elf32_Dyn **info;
info = l->l_info;
while (dyn->d_tag != 0)
{
if ((uint32_t) (0x6ffffeff - dyn->d_tag) < 11)
info[0x6ffffeff - dyn->d_tag + 12] = dyn;
++dyn;
}
}
void
foo (void)
{
elf_get_dynamic_info (&_dl_rtld_map);
}

View File

@ -0,0 +1,33 @@
/* { dg-do compile { target { ! { ia32 } } } } */
/* { dg-require-effective-target fpic } */
/* { dg-options "-O3 -mx32 -fpic" } */
/* { dg-final { scan-assembler-not "movl\[\\t \]*%.*,\[\\t \]*-1073742592\\(%r(.x|.i|.p|\[1-9\]*)\\)" } } */
typedef int int32_t;
typedef unsigned int uint32_t;
typedef uint32_t Elf32_Word;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Addr;
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
struct link_map {
Elf32_Dyn *l_ld;
Elf32_Dyn *l_info[34 + 16 + 3 + 12 + 11];
};
void
elf_get_dynamic_info (struct link_map *l)
{
Elf32_Dyn *dyn = l->l_ld;
Elf32_Dyn **info = l->l_info;
typedef Elf32_Word d_tag_utype;
while (dyn->d_tag != 0) {
if ((d_tag_utype) (0x6ffffeff - dyn->d_tag) < 11)
info[(0x6ffffeff - dyn->d_tag) + 34 + 16 + 3 + 12] = dyn;
++dyn;
}
}