This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
x86_64 merger part 37 take II - PIC code
- To: patches at x86-64 dot org, rth at cygnus dot com, gcc-patches at gcc dot gnu dot org
- Subject: x86_64 merger part 37 take II - PIC code
- From: Jan Hubicka <jh at suse dot cz>
- Date: Wed, 19 Sep 2001 15:20:49 +0200
Hi,
here is updated patch for x86_64 PIC support as we would like to finish
merging soon and close our internal tree.
Honza
Wed Sep 19 15:16:33 CEST 2001 Jan Hubicka <jh@suse.cz>
* i386.md (indirect_jump): Allow Pmode operand.
(tablejump): LIkewise; perform expansion to 64bit mode.
* i386.c (symbolic_operand): Allow 64bit PIC references.
(pic_symbolic_operand): Likewise.
(ix86_find_base_term): Strip the 64bit PIC references.
(legitimate_pic_address_disp_p): Handle 64bit PIC.
(legitimize_pic_address): Likewise.
(i386_simplify_dwarf_addr): Strip down the 64bit PIC references.
Index: gcc/config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.304
diff -c -3 -p -r1.304 i386.c
*** i386.c 2001/09/14 17:19:04 1.304
--- i386.c 2001/09/19 13:07:48
*************** symbolic_operand (op, mode)
*** 1495,1502 ****
if (GET_CODE (op) == SYMBOL_REF
|| GET_CODE (op) == LABEL_REF
|| (GET_CODE (op) == UNSPEC
! && XINT (op, 1) >= 6
! && XINT (op, 1) <= 7))
return 1;
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
--- 1514,1522 ----
if (GET_CODE (op) == SYMBOL_REF
|| GET_CODE (op) == LABEL_REF
|| (GET_CODE (op) == UNSPEC
! && (XINT (op, 1) == 6
! || XINT (op, 1) == 7
! || XINT (op, 1) == 15)))
return 1;
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
*************** pic_symbolic_operand (op, mode)
*** 1529,1537 ****
register rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
! if (GET_CODE (op) == CONST)
{
! op = XEXP (op, 0);
if (GET_CODE (op) == UNSPEC)
return 1;
if (GET_CODE (op) != PLUS
--- 1549,1564 ----
register rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
! if (GET_CODE (op) != CONST)
! return 0;
! op = XEXP (op, 0);
! if (TARGET_64BIT)
{
! if (GET_CODE (XEXP (op, 0)) == UNSPEC)
! return 1;
! }
! else
! {
if (GET_CODE (op) == UNSPEC)
return 1;
if (GET_CODE (op) != PLUS
*************** ix86_find_base_term (x)
*** 3220,3225 ****
--- 3247,3275 ----
{
rtx term;
+ if (TARGET_64BIT)
+ {
+ if (GET_CODE (x) != CONST)
+ return x;
+ term = XEXP (x, 0);
+ if (GET_CODE (term) == PLUS
+ && (GET_CODE (XEXP (term, 1)) == CONST_INT
+ || GET_CODE (XEXP (term, 1)) == CONST_DOUBLE))
+ term = XEXP (term, 0);
+ if (GET_CODE (term) != UNSPEC
+ || XVECLEN (term, 0) != 1
+ || XINT (term, 1) != 15)
+ return x;
+
+ term = XVECEXP (term, 0, 0);
+
+ if (GET_CODE (term) != SYMBOL_REF
+ && GET_CODE (term) != LABEL_REF)
+ return x;
+
+ return term;
+ }
+
if (GET_CODE (x) != PLUS
|| XEXP (x, 0) != pic_offset_table_rtx
|| GET_CODE (XEXP (x, 1)) != CONST)
*************** int
*** 3251,3260 ****
--- 3301,3345 ----
legitimate_pic_address_disp_p (disp)
register rtx disp;
{
+ /* In 64bit mode we can allow direct addresses of symbols and labels
+ when they are not dynamic symbols. */
+ if (TARGET_64BIT)
+ {
+ rtx x = disp;
+ if (GET_CODE (disp) == CONST)
+ x = XEXP (disp, 0);
+ /* ??? Handle PIC code models */
+ if (GET_CODE (x) == PLUS
+ && (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && ix86_cmodel == CM_SMALL_PIC
+ && INTVAL (XEXP (x, 1)) < 1024*1024*1024
+ && INTVAL (XEXP (x, 1)) > -1024*1024*1024))
+ x = XEXP (x, 0);
+ if (GET_CODE (x) == LABEL_REF
+ || (GET_CODE (x) == SYMBOL_REF
+ && (CONSTANT_POOL_ADDRESS_P (x)
+ || SYMBOL_REF_FLAG (x))))
+ return 1;
+ }
if (GET_CODE (disp) != CONST)
return 0;
disp = XEXP (disp, 0);
+ if (TARGET_64BIT)
+ {
+ /* We are unsafe to allow PLUS expressions. This limit allowed distance
+ of GOT tables. We should not need these anyway. */
+ if (GET_CODE (disp) != UNSPEC
+ || XVECLEN (disp, 0) != 1
+ || XINT (disp, 1) != 15)
+ return 0;
+
+ if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
+ && GET_CODE (XVECEXP (disp, 0, 0)) != LABEL_REF)
+ return 0;
+ return 1;
+ }
+
if (GET_CODE (disp) == PLUS)
{
if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
*************** legitimize_pic_address (orig, reg)
*** 3576,3591 ****
if (local_symbolic_operand (op0, Pmode)
&& GET_CODE (op1) == CONST_INT)
{
! current_function_uses_pic_offset_table = 1;
! new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), 7);
! new = gen_rtx_PLUS (Pmode, new, op1);
! new = gen_rtx_CONST (Pmode, new);
! new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
! if (reg != 0)
{
! emit_move_insn (reg, new);
! new = reg;
}
}
else
--- 3661,3683 ----
if (local_symbolic_operand (op0, Pmode)
&& GET_CODE (op1) == CONST_INT)
{
! if (!TARGET_64BIT)
! {
! current_function_uses_pic_offset_table = 1;
! new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), 7);
! new = gen_rtx_PLUS (Pmode, new, op1);
! new = gen_rtx_CONST (Pmode, new);
! new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
! if (reg != 0)
! {
! emit_move_insn (reg, new);
! new = reg;
! }
! }
! else
{
! /* ??? We need to limit offsets here. */
}
}
else
*************** output_pic_addr_const (file, x, code)
*** 3900,3905 ****
--- 3992,4000 ----
case 8:
fputs ("@PLT", file);
break;
+ case 15:
+ fputs ("@GOTPCREL(%RIP)", file);
+ break;
default:
output_operand_lossage ("invalid UNSPEC as operand");
break;
*************** i386_simplify_dwarf_addr (orig_x)
*** 3936,3941 ****
--- 4031,4045 ----
rtx orig_x;
{
rtx x = orig_x;
+
+ if (TARGET_64BIT)
+ {
+ if (GET_CODE (x) != CONST
+ || GET_CODE (XEXP (x, 0)) != UNSPEC
+ || XINT (XEXP (x, 0), 1) != 15)
+ return orig_x;
+ return XVECEXP (XEXP (x, 0), 0, 0);
+ }
if (GET_CODE (x) != PLUS
|| GET_CODE (XEXP (x, 0)) != REG
Index: gcc/config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.h,v
retrieving revision 1.202
diff -c -3 -p -r1.202 i386.h
*** i386.h 2001/09/13 14:37:27 1.202
--- i386.h 2001/09/19 13:07:49
*************** while (0)
*** 2244,2250 ****
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
! #define CASE_VECTOR_MODE Pmode
/* Define as C expression which evaluates to nonzero if the tablejump
instruction expects the table to contain offsets from the address of the
--- 2245,2251 ----
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
! #define CASE_VECTOR_MODE (!TARGET_64BIT || flag_pic ? SImode : DImode)
/* Define as C expression which evaluates to nonzero if the tablejump
instruction expects the table to contain offsets from the address of the
Index: gcc/config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.293
diff -c -3 -p -r1.293 i386.md
*** i386.md 2001/08/24 15:28:54 1.293
--- i386.md 2001/09/19 13:07:54
***************
*** 12948,12961 ****
[(set_attr "type" "ibr")])
(define_insn "indirect_jump"
! [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
""
"jmp\t%A0"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
(define_expand "tablejump"
! [(parallel [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
(use (label_ref (match_operand 1 "" "")))])]
""
{
--- 12948,12961 ----
[(set_attr "type" "ibr")])
(define_insn "indirect_jump"
! [(set (pc) (match_operand:P 0 "nonimmediate_operand" "rm"))]
""
"jmp\t%A0"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
(define_expand "tablejump"
! [(parallel [(set (pc) (match_operand:P 0 "nonimmediate_operand" "rm"))
(use (label_ref (match_operand 1 "" "")))])]
""
{
***************
*** 12963,12972 ****
the relative address to an absolute address. */
if (flag_pic)
{
! operands[0] = expand_simple_binop (Pmode, MINUS, pic_offset_table_rtx,
! operands[0], NULL_RTX, 1,
! OPTAB_DIRECT);
! current_function_uses_pic_offset_table = 1;
}
})
--- 12963,12979 ----
the relative address to an absolute address. */
if (flag_pic)
{
! if (TARGET_64BIT)
! operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
! operands[1], NULL_RTX, 0,
! OPTAB_DIRECT);
! else
! {
! operands[0] = expand_simple_binop (Pmode, MINUS, pic_offset_table_rtx,
! operands[0], NULL_RTX, 1,
! OPTAB_DIRECT);
! current_function_uses_pic_offset_table = 1;
! }
}
})