public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Nathan Sidwell <nathan@codesourcery.com>
To: GCC Patches <gcc-patches@gcc.gnu.org>
Subject: [ARM] TLS Descriptor support
Date: Tue, 10 May 2011 11:23:00 -0000	[thread overview]
Message-ID: <4DC8DFF6.4000600@codesourcery.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1050 bytes --]

This patch implements TLS descriptor support in GCC.  TLS descriptors are 
described at http://www.codesourcery.com/publications/RFC-TLSDESC-ARM.txt and 
blessed by ARM, who have reserved the relocation numbers.

Binutils and GLIBC patches are already committed (there is an orthogonal glibc 
patch to do with make dependencies that I need to post though).

This patch adds a --with-tls={arm|gnu} configuration option, to specify the 
default scheme.  It can be overridden with a -mtls-dialect={arm|gnu} option 
(this is the name used by the x86 backend, which also has tlsdescriptor 
support).  I have not added --with-tls support to the x86 bits of config.gcc 
etc, but it would be simple to do so.

The arm.{c,h,md} changes are fairly mechanical -- a new tls pattern and smarts 
to emit it appropriately.

This patch has been tested for both default arm and default gnu tls schemes 
using the gcc and glibc testsuites for an arm-linux-gnueabi target.

ok?

nathan

-- 
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery


[-- Attachment #2: gcc.patch --]
[-- Type: text/x-patch, Size: 14706 bytes --]

2011-05-10  Nathan Sidwell  <nathan@codesourcery.com>

	* doc/invoke.texi (ARM Options): Document -mtls-dialect option.
	* doc/install.texi (Configuration): Document --with-tls.
	* config.gcc (arm*-*-linux*): Default to arm-style tls.
	(arm*-*-*): Add --with-tls option.
	(all_defaults): Add 'tls'.
	* config/arm/arm.c (target_tls_dialect): New.
	(enum tls_reloc): Add TLS_DESCSEQ.
	(arm_override_options): Process target_tls_dialect_switch value.
	(arm_call_tls_get_addr): Clean up. Assert not tls descriptor.
	(arm_tls_descseq_addr): New.
	(legitimize_tls_address): Add tlsdesc support.
	(arm_cannot_copy_insn_p): Check for tlscall.
	(arm_emit_tls_decoration): Likewise.
	* config/arm/arm.h (TARGET_ARM_TLS, TARGET_GNU_TLS): New.
	(OPTION_DEFAULT_SPECS): Add with-tls support.
	(enum arm_tls_type): New.
	(target_tls_dialect): New.
	* config/arm/arm.opt (mtls-dialect): New switch.
	* config/arm/arm.md (tlscall): New.

	testsuite/
	* gcc.target/arm/tlscall.c: New.

Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 172962)
+++ doc/invoke.texi	(working copy)
@@ -469,7 +469,7 @@ Objective-C and Objective-C++ Dialects}.
 -mthumb  -marm @gol
 -mtpcs-frame  -mtpcs-leaf-frame @gol
 -mcaller-super-interworking  -mcallee-super-interworking @gol
--mtp=@var{name} @gol
+-mtp=@var{name} -mtls-dialect=@var{dialect} @gol
 -mword-relocations @gol
 -mfix-cortex-m3-ldrd}
 
@@ -10332,6 +10332,17 @@ models are @option{soft}, which generate
 best available method for the selected processor.  The default setting is
 @option{auto}.
 
+@item -mtls-dialect=@var{dialect}
+@opindex mtls-dialect
+Specify the dialect to use for accessing thread local storage.  Two
+dialects are supported - @option{arm} and @option{gnu}.  The
+@option{arm} dialect selects the ARM EABI scheme for supporting local
+and global dynamic tls models.  The @option{gnu} dialect selects the
+experimental GNU scheme.  The GNU scheme is compatible with the ARM
+scheme, but does require new assembler, linker and library
+support.  Initial and local exec TLS models are unaffected by this
+option and use the ARM EABI scheme.
+
 @item -mword-relocations
 @opindex mword-relocations
 Only generate absolute relocations on word sized values (i.e. R_ARM_ABS32).
Index: doc/install.texi
===================================================================
--- doc/install.texi	(revision 172962)
+++ doc/install.texi	(working copy)
@@ -1003,6 +1003,12 @@ information normally used on 386 SVR4 pl
 workable alternative.  This requires gas and gdb, as the normal SVR4
 tools can not generate or interpret stabs.
 
+@item --with-tls=@var{dialect}
+Specify the default tls dialect, for systems were there is a choice.
+For ARM targets, possible values for @var{dialect} are @code{arm} or
+@code{gnu}, which select between the ARM EABI dialect and the GNU TLS
+descriptor-based dialect.
+
 @item --disable-multilib
 Specify that multiple target
 libraries to support different target variants, calling
Index: testsuite/gcc.target/arm/tlscall.c
===================================================================
--- testsuite/gcc.target/arm/tlscall.c	(revision 0)
+++ testsuite/gcc.target/arm/tlscall.c	(revision 0)
@@ -0,0 +1,31 @@
+/* Test non-duplication of tlscall insn */
+
+/* { dg-do assemble } */
+/* { dg-options "-O2 -fPIC -mtls-dialect=gnu" } */
+
+typedef struct _IO_FILE FILE;
+
+extern int foo(void);
+extern int bar(void);
+
+void uuid__generate_time()
+{
+ static int has_init = 0;
+ static __thread int state_fd = -2;
+ static __thread FILE *state_f;
+
+ if (!has_init) {
+   foo();
+   has_init = 1;
+ }
+
+ if (state_fd == -2) {
+  if (!state_f) {
+   state_fd = -1;
+  }
+ }
+ if (state_fd >= 0) {
+  while (bar() < 0) {}
+ }
+
+}
Index: config.gcc
===================================================================
--- config.gcc	(revision 172962)
+++ config.gcc	(working copy)
@@ -813,6 +813,7 @@ arm*-*-linux*)			# ARM GNU/Linux with EL
 	    tmake_file="$tmake_file arm/t-linux"
 	    ;;
 	esac
+	with_tls=${with_tls:arm}
 	tm_file="$tm_file arm/aout.h arm/arm.h"
 	tmake_file="${tmake_file} arm/t-arm-softfp soft-fp/t-softfp"
 	;;
@@ -3064,7 +3065,7 @@ case "${target}" in
 		;;
 
 	arm*-*-*)
-		supported_defaults="arch cpu float tune fpu abi mode"
+		supported_defaults="arch cpu float tune fpu abi mode tls"
 		for which in cpu tune; do
 			# See if it matches any of the entries in arm-cores.def
 			eval "val=\$with_$which"
@@ -3147,6 +3148,17 @@ case "${target}" in
 			;;
 		esac
 
+		case "$with_tls" in
+		"" \
+		| arm | gnu)
+			# OK
+			;;
+		*)
+			echo "Unknown TLS method used in --with-tls=$with_tls" 1>&2
+			exit 1
+			;;
+		esac
+
 		if test "x$with_arch" != x && test "x$with_cpu" != x; then
 			echo "Warning: --with-arch overrides --with-cpu=$with_cpu" 1>&2
 		fi
@@ -3624,7 +3636,7 @@ case ${target} in
 esac
 
 t=
-all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu divide llsc mips-plt synci"
+all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu divide llsc mips-plt synci tls"
 for option in $all_defaults
 do
 	eval "val=\$with_"`echo $option | sed s/-/_/g`
Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c	(revision 172962)
+++ config/arm/arm.c	(working copy)
@@ -644,6 +644,9 @@ enum arm_abi_type arm_abi;
 /* Which thread pointer model to use.  */
 enum arm_tp_type target_thread_pointer = TP_AUTO;
 
+/* Which tls dialect to use.  */
+enum arm_tls_type target_tls_dialect = TLS_ARM;
+
 /* Used to parse -mstructure_size_boundary command line option.  */
 int    arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
 
@@ -1031,7 +1034,8 @@ enum tls_reloc {
   TLS_LDM32,
   TLS_LDO32,
   TLS_IE32,
-  TLS_LE32
+  TLS_LE32,
+  TLS_DESCSEQ	/* GNU scheme */
 };
 
 /* The maximum number of insns to be used when loading a constant.  */
@@ -1755,6 +1759,17 @@ arm_option_override (void)
 	error ("invalid thread pointer option: -mtp=%s", target_thread_switch);
     }
 
+  if (target_tls_dialect_switch)
+    {
+      if (strcmp (target_tls_dialect_switch, "arm") == 0)
+	target_tls_dialect = TLS_ARM;
+      else if (strcmp (target_tls_dialect_switch, "gnu") == 0)
+	target_tls_dialect = TLS_GNU;
+      else
+	error ("invalid thread dialect option: -mtls-dialect=%s",
+	       target_tls_dialect_switch);
+    }
+
   /* Use the cp15 method if it is available.  */
   if (target_thread_pointer == TP_AUTO)
     {
@@ -5957,6 +5972,7 @@ arm_call_tls_get_addr (rtx x, rtx reg, r
 {
   rtx insns, label, labelno, sum;
 
+  gcc_assert (reloc != TLS_DESCSEQ);
   start_sequence ();
 
   labelno = GEN_INT (pic_labelno++);
@@ -5971,20 +5987,42 @@ arm_call_tls_get_addr (rtx x, rtx reg, r
 
   if (TARGET_ARM)
     emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno));
-  else if (TARGET_THUMB2)
-    emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
-  else /* TARGET_THUMB1 */
+  else
     emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
-
-  *valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX, LCT_PURE, /* LCT_CONST?  */
+  
+  *valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX,
+				     LCT_PURE, /* LCT_CONST?  */
 				     Pmode, 1, reg, Pmode);
-
+  
   insns = get_insns ();
   end_sequence ();
 
   return insns;
 }
 
+static rtx
+arm_tls_descseq_addr (rtx x, rtx reg)
+{
+  rtx labelno = GEN_INT (pic_labelno++);
+  rtx label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
+  rtx sum = gen_rtx_UNSPEC (Pmode,
+			    gen_rtvec (4, x, GEN_INT (TLS_DESCSEQ),
+				       gen_rtx_CONST (VOIDmode, label),
+				       GEN_INT (!TARGET_ARM)),
+			    UNSPEC_TLS);
+  rtx reg0 = load_tls_operand (sum, gen_rtx_REG (SImode, 0));
+  
+  emit_insn (gen_tlscall (x, labelno));
+  if (!reg)
+    reg = gen_reg_rtx (SImode);
+  else
+    gcc_assert (REGNO (reg) != 0);
+
+  emit_move_insn (reg, reg0);
+
+  return reg;
+}
+
 rtx
 legitimize_tls_address (rtx x, rtx reg)
 {
@@ -5994,26 +6032,49 @@ legitimize_tls_address (rtx x, rtx reg)
   switch (model)
     {
     case TLS_MODEL_GLOBAL_DYNAMIC:
-      insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32);
-      dest = gen_reg_rtx (Pmode);
-      emit_libcall_block (insns, dest, ret, x);
-      return dest;
+      if (TARGET_ARM_TLS)
+	{
+	  insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32);
+	  dest = gen_reg_rtx (Pmode);
+	  emit_libcall_block (insns, dest, ret, x);
+	  return dest;
+	}
+      else
+	{
+	  reg = arm_tls_descseq_addr (x, reg);
 
-    case TLS_MODEL_LOCAL_DYNAMIC:
-      insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32);
+	  tp = arm_load_tp (NULL_RTX);
+	  
+	  return gen_rtx_PLUS (Pmode, tp, reg);
+	}
 
-      /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
-	 share the LDM result with other LD model accesses.  */
-      eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx),
-			    UNSPEC_TLS);
-      dest = gen_reg_rtx (Pmode);
-      emit_libcall_block (insns, dest, ret, eqv);
+    case TLS_MODEL_LOCAL_DYNAMIC:
+      if (TARGET_ARM_TLS)
+	{
+	  insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32);
+	  
+	  /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+	     share the LDM result with other LD model accesses.  */
+	  eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx),
+				UNSPEC_TLS);
+	  dest = gen_reg_rtx (Pmode);
+	  emit_libcall_block (insns, dest, ret, eqv);
+	  
+	  /* Load the addend.  */
+	  addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x,
+						     GEN_INT (TLS_LDO32)),
+				   UNSPEC_TLS);
+	  addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
+	  return gen_rtx_PLUS (Pmode, dest, addend);
+	}
+      else
+	{
+	  reg = arm_tls_descseq_addr (x, reg);
 
-      /* Load the addend.  */
-      addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_LDO32)),
-			       UNSPEC_TLS);
-      addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
-      return gen_rtx_PLUS (Pmode, dest, addend);
+	  tp = arm_load_tp (NULL_RTX);
+	  
+	  return gen_rtx_PLUS (Pmode, tp, reg);
+	}
 
     case TLS_MODEL_INITIAL_EXEC:
       labelno = GEN_INT (pic_labelno++);
@@ -9445,6 +9506,11 @@ arm_note_pic_base (rtx *x, void *date AT
 static bool
 arm_cannot_copy_insn_p (rtx insn)
 {
+  /* The tls call insn cannot be copied, as it is paired with a data
+     word.  */
+  if (recog_memoized (insn) == CODE_FOR_tlscall)
+    return true;
+  
   return for_each_rtx (&PATTERN (insn), arm_note_pic_base, NULL);
 }
 
@@ -22985,6 +23051,9 @@ arm_emit_tls_decoration (FILE *fp, rtx x
     case TLS_LE32:
       fputs ("(tpoff)", fp);
       break;
+    case TLS_DESCSEQ:
+      fputs ("(tlsdesc)", fp);
+      break;
     default:
       gcc_unreachable ();
     }
@@ -22994,9 +23063,11 @@ arm_emit_tls_decoration (FILE *fp, rtx x
     case TLS_GD32:
     case TLS_LDM32:
     case TLS_IE32:
+    case TLS_DESCSEQ:
       fputs (" + (. - ", fp);
       output_addr_const (fp, XVECEXP (x, 0, 2));
-      fputs (" - ", fp);
+      /* For DESCSEQ the 3rd operand encodes thumbness, and is added */
+      fputs (reloc == TLS_DESCSEQ ? " + " : " - ", fp);
       output_addr_const (fp, XVECEXP (x, 0, 3));
       fputc (')', fp);
       break;
Index: config/arm/arm.h
===================================================================
--- config/arm/arm.h	(revision 172962)
+++ config/arm/arm.h	(working copy)
@@ -218,6 +218,8 @@ extern void (*arm_lang_output_object_att
 
 #define TARGET_HARD_TP			(target_thread_pointer == TP_CP15)
 #define TARGET_SOFT_TP			(target_thread_pointer == TP_SOFT)
+#define TARGET_ARM_TLS			(target_tls_dialect == TLS_ARM)
+#define TARGET_GNU_TLS			(target_tls_dialect == TLS_GNU)
 
 /* Only 16-bit thumb code.  */
 #define TARGET_THUMB1			(TARGET_THUMB && !arm_arch_thumb2)
@@ -306,7 +308,8 @@ extern void (*arm_lang_output_object_att
      by -march).
    --with-float is ignored if -mfloat-abi is specified.
    --with-fpu is ignored if -mfpu is specified.
-   --with-abi is ignored is -mabi is specified.  */
+   --with-abi is ignored if -mabi is specified.
+   --with-tls is ignored if -mtls-dialect is specified. */
 #define OPTION_DEFAULT_SPECS \
   {"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \
   {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
@@ -314,7 +317,8 @@ extern void (*arm_lang_output_object_att
   {"float", "%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}" }, \
   {"fpu", "%{!mfpu=*:-mfpu=%(VALUE)}"}, \
   {"abi", "%{!mabi=*:-mabi=%(VALUE)}"}, \
-  {"mode", "%{!marm:%{!mthumb:-m%(VALUE)}}"},
+  {"mode", "%{!marm:%{!mthumb:-m%(VALUE)}}"}, \
+  {"tls", "%{!mtls-dialect:-mtls-dialect=%(VALUE)}"},
 
 /* Which floating point model to use.  */
 enum arm_fp_model
@@ -400,7 +404,13 @@ enum arm_tp_type {
   TP_CP15
 };
 
+enum arm_tls_type {
+  TLS_ARM,
+  TLS_GNU
+};
+
 extern enum arm_tp_type target_thread_pointer;
+extern enum arm_tls_type target_tls_dialect;
 
 /* Nonzero if this chip supports the ARM Architecture 3M extensions.  */
 extern int arm_arch3m;
Index: config/arm/arm.opt
===================================================================
--- config/arm/arm.opt	(revision 172962)
+++ config/arm/arm.opt	(working copy)
@@ -138,6 +138,10 @@ mthumb-interwork
 Target Report Mask(INTERWORK)
 Support calls between Thumb and ARM instruction sets
 
+mtls-dialect=
+Target RejectNegative Joined Var(target_tls_dialect_switch)
+Specify thread local storage scheme
+
 mtp=
 Target RejectNegative Joined Var(target_thread_switch)
 Specify how to access the thread pointer
Index: config/arm/arm.md
===================================================================
--- config/arm/arm.md	(revision 172962)
+++ config/arm/arm.md	(working copy)
@@ -10620,6 +10620,28 @@
   [(set_attr "conds" "clob")]
 )
 
+;; tls descriptor call
+(define_insn "tlscall"
+  [(set (reg:SI 0) (unspec:SI [(reg:SI 0)
+                               (match_operand:SI 0 "" "X")
+			       (match_operand 1 "" "")] UNSPEC_TLS))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI LR_REGNUM))
+   (clobber (reg:SI CC_REGNUM))]
+  "TARGET_GNU_TLS"
+  {
+    targetm.asm_out.internal_label (asm_out_file, "LPIC",
+				    INTVAL (operands[1]));
+    /* The + is to avoid an assembly parse ambiguity with symbols that
+       look like register names, which is unsuccessfully recovered from.  */
+    return TARGET_THUMB2 ? "blx\\t%c0(tlscall)" : "bl\\t+%c0(tlscall)";
+  }
+  [(set_attr "conds" "clob")
+   (set_attr "length" "4")]
+)
+
+;;
+
 ;; We only care about the lower 16 bits of the constant 
 ;; being inserted into the upper 16 bits of the register.
 (define_insn "*arm_movtas_ze" 

             reply	other threads:[~2011-05-10  6:49 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-10 11:23 Nathan Sidwell [this message]
2011-05-10 13:14 ` Joseph S. Myers
2011-05-11 15:43   ` Nathan Sidwell
2011-05-26  9:32 ` Nathan Sidwell
2011-05-27  4:43 ` Ramana Radhakrishnan
2011-05-31 13:03   ` Nathan Sidwell
2011-06-03 22:50     ` Ramana Radhakrishnan
2011-06-06  9:50       ` Nathan Sidwell
2011-06-06  9:54         ` Ramana Radhakrishnan
2011-06-06  9:56           ` Nathan Sidwell
2011-06-06 16:10             ` Ramana Radhakrishnan
2011-06-06 16:27 ` Richard Earnshaw
2011-06-07  6:11   ` Nathan Sidwell
2011-06-07 13:08     ` Richard Earnshaw
2011-06-21  8:42 ` Nathan Sidwell
2011-06-21 18:03   ` Ramana Radhakrishnan
2011-06-22 17:52     ` Nathan Sidwell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4DC8DFF6.4000600@codesourcery.com \
    --to=nathan@codesourcery.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).