This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[build] Fix Solaris 2/x86 GD/LD TLS code sequences with Sun ld
- From: Rainer Orth <ro at CeBiTec dot Uni-Bielefeld dot DE>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Uros Bizjak <ubizjak at gmail dot com>
- Date: Mon, 23 May 2011 19:22:00 +0200
- Subject: [build] Fix Solaris 2/x86 GD/LD TLS code sequences with Sun ld
As described in
[testsuite] Provide TLS access model testcases
http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01601.html
both the 32 and 64-bit TLS GD and LD execution tests fail on Solaris 2
with Sun ld unless you have a very recent Solaris 11 version (snv_164).
This happens because the code sequences emitted by GCC don't match those
expected by Sun ld:
32-bit x86: Thread-Local Variable Access
http://download.oracle.com/docs/cd/E19963-01/html/819-0690/chapter8-20.html#gentextid-20367
For GD, one needs to use call x@tlsgdplt here, but call ___tls_get_addr@plt
works, too.
For LD, one really needs call x@tlsldmplt.
The corresponding R_386_TLS_GD_PLT and R_386_TLS_LDM_PLT relocations are
not yet handled by binutils.
x64: Thread-Local Variable Access
http://download.oracle.com/docs/cd/E19963-01/html/819-0690/chapter8-20.html#chapter8-60
For both GD and LD, one needs to use call __tls_get_addr@plt.
The following patch handles this:
* It autoconfigures support for the @tlsgdplt and @tlsldmplt
relocations: Sun as supports them, while gas doesn't yet. I've got a
patch in the works to fix this: while the gas part is easy, I have
serious problems getting the ld side to work properly. Unfortunately,
I doubt the binutils maintainers will accept such partial support for
the relocs.
* I'm using a new 'p' code to control the printing of @plt. 'P' doesn't
work since this is needed in both PIC and non-PIC code.
Bootstrapped without regressions on i386-pc-solaris2.10.
Ok for mainline?
Rainer
2010-12-30 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure.ac (gcc_cv_as_ix86_tlsgdplt): Check for @tlsgdplt
(HAVE_AS_IX86_TLSGDPTL): Define.
(gcc_cv_as_ix86_tlsldmplt): Check for @tlsldmplt.
(HAVE_AS_IX86_TLSLDMPLT): Define.
* configure: Regenerate.
* config.in: Regenerate.
* config/i386/i386.c (output_pic_addr_const): Handle code 'p' like 'P'.
(ix86_print_operand): Handle code 'p'.
* config/i386/i386.md (*tls_global_dynamic_32_gnu): Use @tlsgdplt
if TARGET_SUN_TLS && HAVE_AS_IX86_TLSGDPLT.
Use 'p' code.
(*tls_global_dynamic_64): Use 'p' code.
(*tls_local_dynamic_base_32_gnu): Use @tlsldmplt if TARGET_SUN_TLS
&& HAVE_AS_IX86_TLSLDMPLT.
Use 'p' code.
(*tls_local_dynamic_base_64): Use 'p' code.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -13209,7 +13209,7 @@ output_pic_addr_const (FILE *file, rtx x
assemble_name (file, name);
}
if (!TARGET_MACHO && !(TARGET_64BIT && DEFAULT_ABI == MS_ABI)
- && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
+ && (code == 'P' || code == 'p') && ! SYMBOL_REF_LOCAL_P (x))
fputs ("@PLT", file);
break;
@@ -13917,6 +13917,7 @@ get_some_local_dynamic_name (void)
d -- print duplicated register operand for AVX instruction.
D -- print condition for SSE cmp instruction.
P -- if PIC, print an @PLT suffix.
+ p -- print an @PLT suffix for Sun ld.
X -- don't print any sort of PIC '@' suffix for a symbol.
& -- print some in-use local-dynamic symbol name.
H -- print a memory address offset by 8; used for sse high-parts
@@ -14122,6 +14123,7 @@ ix86_print_operand (FILE *file, rtx x, i
case 'x':
case 'X':
case 'P':
+ case 'p':
break;
case 's':
@@ -14426,7 +14428,8 @@ ix86_print_operand (FILE *file, rtx x, i
else if (MEM_P (x))
{
/* No `byte ptr' prefix for call instructions or BLKmode operands. */
- if (ASSEMBLER_DIALECT == ASM_INTEL && code != 'X' && code != 'P'
+ if (ASSEMBLER_DIALECT == ASM_INTEL
+ && code != 'X' && code != 'P' && code != 'p'
&& GET_MODE (x) != BLKmode)
{
const char * size;
@@ -14462,9 +14465,13 @@ ix86_print_operand (FILE *file, rtx x, i
x = XEXP (x, 0);
/* Avoid (%rip) for call operands. */
- if (CONSTANT_ADDRESS_P (x) && code == 'P'
+ if (CONSTANT_ADDRESS_P (x) && (code == 'P' || code == 'p')
&& !CONST_INT_P (x))
- output_addr_const (file, x);
+ {
+ output_addr_const (file, x);
+ if (code == 'p' && TARGET_SUN_TLS)
+ fputs ("@PLT", file);
+ }
else if (this_is_asm_operands && ! address_operand (x, VOIDmode))
output_operand_lossage ("invalid constraints for operand");
else
@@ -14521,7 +14528,7 @@ ix86_print_operand (FILE *file, rtx x, i
x = const0_rtx;
}
- if (code != 'P')
+ if (code != 'P' && code != 'p')
{
if (CONST_INT_P (x) || GET_CODE (x) == CONST_DOUBLE)
{
@@ -14542,7 +14549,11 @@ ix86_print_operand (FILE *file, rtx x, i
else if (flag_pic || MACHOPIC_INDIRECT)
output_pic_addr_const (file, x, code);
else
- output_addr_const (file, x);
+ {
+ output_addr_const (file, x);
+ if (code == 'p' && TARGET_SUN_TLS)
+ fputs ("@PLT", file);
+ }
}
}
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -53,6 +53,7 @@
;; d -- print duplicated register operand for AVX instruction.
;; D -- print condition for SSE cmp instruction.
;; P -- if PIC, print an @PLT suffix.
+;; p -- if Sun ld, print an @PLT suffix.
;; X -- don't print any sort of PIC '@' suffix for a symbol.
;; & -- print some in-use local-dynamic symbol name.
;; H -- print a memory address offset by 8; used for sse high-parts
@@ -12367,7 +12368,10 @@
{
output_asm_insn
("lea{l}\t{%a2@tlsgd(,%1,1), %0|%0, %a2@tlsgd[%1*1]}", operands);
- return "call\t%P3";
+ if (TARGET_SUN_TLS && HAVE_AS_IX86_TLSGDPLT)
+ return "call\t%a2@tlsgdplt";
+ else
+ return "call\t%p3";
}
[(set_attr "type" "multi")
(set_attr "length" "12")])
@@ -12397,7 +12401,7 @@
("lea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}", operands);
fputs (ASM_SHORT "0x6666\n", asm_out_file);
fputs ("\trex64\n", asm_out_file);
- return "call\t%P2";
+ return "call\t%p2";
}
[(set_attr "type" "multi")
(set_attr "length" "16")])
@@ -12424,7 +12428,10 @@
{
output_asm_insn
("lea{l}\t{%&@tlsldm(%1), %0|%0, %&@tlsldm[%1]}", operands);
- return "call\t%P2";
+ if (TARGET_SUN_TLS && HAVE_AS_IX86_TLSLDMPLT)
+ return "call\t%&@tlsldmplt";
+ else
+ return "call\t%p2";
}
[(set_attr "type" "multi")
(set_attr "length" "11")])
@@ -12450,7 +12457,7 @@
{
output_asm_insn
("lea{q}\t{%&@tlsld(%%rip), %%rdi|rdi, %&@tlsld[rip]}", operands);
- return "call\t%P1";
+ return "call\t%p1";
}
[(set_attr "type" "multi")
(set_attr "length" "12")])
diff --git a/gcc/configure.ac b/gcc/configure.ac
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3653,6 +3653,20 @@ foo: nop
[AC_DEFINE(HAVE_AS_IX86_REP_LOCK_PREFIX, 1,
[Define if the assembler supports 'rep <insn>, lock <insn>'.])])
+ gcc_GAS_CHECK_FEATURE([R_386_TLS_GD_PLT reloc],
+ gcc_cv_as_ix86_tlsgdplt,,,
+ [call tls_gd@tlsgdplt])
+ AC_DEFINE_UNQUOTED(HAVE_AS_IX86_TLSGDPLT,
+ [`if test $gcc_cv_as_ix86_tlsgdplt = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports @tlsgdplt.])
+
+ gcc_GAS_CHECK_FEATURE([R_386_TLS_LDM_PLT reloc],
+ gcc_cv_as_ix86_tlsldmplt,,,
+ [call tls_ld@tlsldmplt])
+ AC_DEFINE_UNQUOTED(HAVE_AS_IX86_TLSLDMPLT,
+ [`if test $gcc_cv_as_ix86_tlsldmplt = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports @tlsldmplt.])
+
;;
ia64*-*-*)
--
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University