Commit ccdc2164 by Nathan Sidwell Committed by Nathan Sidwell

invoke.texi (ARM Options): Document -mtls-dialect option.

	* doc/invoke.texi (ARM Options): Document -mtls-dialect option.
	* doc/install.texi (Configuration): Document --with-tls.
	* config.gcc (arm*-*-linux*): Default to gnu tls.
	(arm*-*-*): Add --with-tls option.
	(all_defaults): Add 'tls'.
	* config/arm/arm.c (enum tls_reloc): Add TLS_DESCSEQ.
	(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_GNU2_TLS): New.
	(OPTION_DEFAULT_SPECS): Add with-tls support.
	* config/arm/arm.md (R1_REGNUM): Define.
	(tlscall): New.
	* config/arm/arm.opt (tls_type): New enumeration type and values.
	(mtls-dialect): New switch.
	* config/arm/arm-opts.h (enum tls_type): New.

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

From-SVN: r175287
parent 70e41a6a
2011-06-22 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 gnu tls.
(arm*-*-*): Add --with-tls option.
(all_defaults): Add 'tls'.
* config/arm/arm.c (enum tls_reloc): Add TLS_DESCSEQ.
(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_GNU2_TLS): New.
(OPTION_DEFAULT_SPECS): Add with-tls support.
* config/arm/arm.md (R1_REGNUM): Define.
(tlscall): New.
* config/arm/arm.opt (tls_type): New enumeration type and values.
(mtls-dialect): New switch.
* config/arm/arm-opts.h (enum tls_type): New.
2011-06-21 Nicola Pero <nicola.pero@meta-innovation.com> 2011-06-21 Nicola Pero <nicola.pero@meta-innovation.com>
* attribs.c (register_attribute): Added assert to check that all * attribs.c (register_attribute): Added assert to check that all
......
...@@ -68,4 +68,9 @@ enum arm_tp_type { ...@@ -68,4 +68,9 @@ enum arm_tp_type {
TP_CP15 TP_CP15
}; };
/* Which TLS scheme to use. */
enum arm_tls_type {
TLS_GNU,
TLS_GNU2
};
#endif #endif
...@@ -1009,7 +1009,8 @@ enum tls_reloc { ...@@ -1009,7 +1009,8 @@ enum tls_reloc {
TLS_LDM32, TLS_LDM32,
TLS_LDO32, TLS_LDO32,
TLS_IE32, TLS_IE32,
TLS_LE32 TLS_LE32,
TLS_DESCSEQ /* GNU scheme */
}; };
/* The maximum number of insns to be used when loading a constant. */ /* The maximum number of insns to be used when loading a constant. */
...@@ -5881,6 +5882,7 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc) ...@@ -5881,6 +5882,7 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
{ {
rtx insns, label, labelno, sum; rtx insns, label, labelno, sum;
gcc_assert (reloc != TLS_DESCSEQ);
start_sequence (); start_sequence ();
labelno = GEN_INT (pic_labelno++); labelno = GEN_INT (pic_labelno++);
...@@ -5895,12 +5897,11 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc) ...@@ -5895,12 +5897,11 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
if (TARGET_ARM) if (TARGET_ARM)
emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno)); emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno));
else if (TARGET_THUMB2) else
emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
else /* TARGET_THUMB1 */
emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno)); 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); Pmode, 1, reg, Pmode);
insns = get_insns (); insns = get_insns ();
...@@ -5909,6 +5910,29 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc) ...@@ -5909,6 +5910,29 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
return insns; 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 rtx
legitimize_tls_address (rtx x, rtx reg) legitimize_tls_address (rtx x, rtx reg)
{ {
...@@ -5918,12 +5942,34 @@ legitimize_tls_address (rtx x, rtx reg) ...@@ -5918,12 +5942,34 @@ legitimize_tls_address (rtx x, rtx reg)
switch (model) switch (model)
{ {
case TLS_MODEL_GLOBAL_DYNAMIC: case TLS_MODEL_GLOBAL_DYNAMIC:
if (TARGET_GNU2_TLS)
{
reg = arm_tls_descseq_addr (x, reg);
tp = arm_load_tp (NULL_RTX);
dest = gen_rtx_PLUS (Pmode, tp, reg);
}
else
{
/* Original scheme */
insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32); insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32);
dest = gen_reg_rtx (Pmode); dest = gen_reg_rtx (Pmode);
emit_libcall_block (insns, dest, ret, x); emit_libcall_block (insns, dest, ret, x);
}
return dest; return dest;
case TLS_MODEL_LOCAL_DYNAMIC: case TLS_MODEL_LOCAL_DYNAMIC:
if (TARGET_GNU2_TLS)
{
reg = arm_tls_descseq_addr (x, reg);
tp = arm_load_tp (NULL_RTX);
dest = gen_rtx_PLUS (Pmode, tp, reg);
}
else
{
insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32); insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32);
/* Attach a unique REG_EQUIV, to allow the RTL optimizers to /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
...@@ -5934,10 +5980,13 @@ legitimize_tls_address (rtx x, rtx reg) ...@@ -5934,10 +5980,13 @@ legitimize_tls_address (rtx x, rtx reg)
emit_libcall_block (insns, dest, ret, eqv); emit_libcall_block (insns, dest, ret, eqv);
/* Load the addend. */ /* Load the addend. */
addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_LDO32)), addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x,
GEN_INT (TLS_LDO32)),
UNSPEC_TLS); UNSPEC_TLS);
addend = force_reg (SImode, gen_rtx_CONST (SImode, addend)); addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
return gen_rtx_PLUS (Pmode, dest, addend); dest = gen_rtx_PLUS (Pmode, dest, addend);
}
return dest;
case TLS_MODEL_INITIAL_EXEC: case TLS_MODEL_INITIAL_EXEC:
labelno = GEN_INT (pic_labelno++); labelno = GEN_INT (pic_labelno++);
...@@ -9384,6 +9433,11 @@ arm_note_pic_base (rtx *x, void *date ATTRIBUTE_UNUSED) ...@@ -9384,6 +9433,11 @@ arm_note_pic_base (rtx *x, void *date ATTRIBUTE_UNUSED)
static bool static bool
arm_cannot_copy_insn_p (rtx insn) 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); return for_each_rtx (&PATTERN (insn), arm_note_pic_base, NULL);
} }
...@@ -22912,6 +22966,9 @@ arm_emit_tls_decoration (FILE *fp, rtx x) ...@@ -22912,6 +22966,9 @@ arm_emit_tls_decoration (FILE *fp, rtx x)
case TLS_LE32: case TLS_LE32:
fputs ("(tpoff)", fp); fputs ("(tpoff)", fp);
break; break;
case TLS_DESCSEQ:
fputs ("(tlsdesc)", fp);
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -22921,9 +22978,11 @@ arm_emit_tls_decoration (FILE *fp, rtx x) ...@@ -22921,9 +22978,11 @@ arm_emit_tls_decoration (FILE *fp, rtx x)
case TLS_GD32: case TLS_GD32:
case TLS_LDM32: case TLS_LDM32:
case TLS_IE32: case TLS_IE32:
case TLS_DESCSEQ:
fputs (" + (. - ", fp); fputs (" + (. - ", fp);
output_addr_const (fp, XVECEXP (x, 0, 2)); 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)); output_addr_const (fp, XVECEXP (x, 0, 3));
fputc (')', fp); fputc (')', fp);
break; break;
......
...@@ -220,6 +220,7 @@ extern void (*arm_lang_output_object_attributes_hook)(void); ...@@ -220,6 +220,7 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
#define TARGET_HARD_TP (target_thread_pointer == TP_CP15) #define TARGET_HARD_TP (target_thread_pointer == TP_CP15)
#define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT) #define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT)
#define TARGET_GNU2_TLS (target_tls_dialect == TLS_GNU2)
/* Only 16-bit thumb code. */ /* Only 16-bit thumb code. */
#define TARGET_THUMB1 (TARGET_THUMB && !arm_arch_thumb2) #define TARGET_THUMB1 (TARGET_THUMB && !arm_arch_thumb2)
...@@ -313,7 +314,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void); ...@@ -313,7 +314,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
by -march). by -march).
--with-float is ignored if -mfloat-abi is specified. --with-float is ignored if -mfloat-abi is specified.
--with-fpu is ignored if -mfpu 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 \ #define OPTION_DEFAULT_SPECS \
{"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \ {"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \
{"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \ {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
...@@ -321,7 +323,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void); ...@@ -321,7 +323,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
{"float", "%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}" }, \ {"float", "%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}" }, \
{"fpu", "%{!mfpu=*:-mfpu=%(VALUE)}"}, \ {"fpu", "%{!mfpu=*:-mfpu=%(VALUE)}"}, \
{"abi", "%{!mabi=*:-mabi=%(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. */ /* Which floating point model to use. */
enum arm_fp_model enum arm_fp_model
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
;; Register numbers ;; Register numbers
(define_constants (define_constants
[(R0_REGNUM 0) ; First CORE register [(R0_REGNUM 0) ; First CORE register
(R1_REGNUM 1) ; Second CORE register
(IP_REGNUM 12) ; Scratch register (IP_REGNUM 12) ; Scratch register
(SP_REGNUM 13) ; Stack pointer (SP_REGNUM 13) ; Stack pointer
(LR_REGNUM 14) ; Return address register (LR_REGNUM 14) ; Return address register
...@@ -10719,6 +10720,27 @@ ...@@ -10719,6 +10720,27 @@
[(set_attr "conds" "clob")] [(set_attr "conds" "clob")]
) )
;; tls descriptor call
(define_insn "tlscall"
[(set (reg:SI R0_REGNUM)
(unspec:SI [(reg:SI R0_REGNUM)
(match_operand:SI 0 "" "X")
(match_operand 1 "" "")] UNSPEC_TLS))
(clobber (reg:SI R1_REGNUM))
(clobber (reg:SI LR_REGNUM))
(clobber (reg:SI CC_REGNUM))]
"TARGET_GNU2_TLS"
{
targetm.asm_out.internal_label (asm_out_file, "LPIC",
INTVAL (operands[1]));
return "bl\\t%c0(tlscall)";
}
[(set_attr "conds" "clob")
(set_attr "length" "4")]
)
;;
;; We only care about the lower 16 bits of the constant ;; We only care about the lower 16 bits of the constant
;; being inserted into the upper 16 bits of the register. ;; being inserted into the upper 16 bits of the register.
(define_insn "*arm_movtas_ze" (define_insn "*arm_movtas_ze"
......
...@@ -21,6 +21,16 @@ ...@@ -21,6 +21,16 @@
HeaderInclude HeaderInclude
config/arm/arm-opts.h config/arm/arm-opts.h
Enum
Name(tls_type) Type(enum arm_tls_type)
TLS dialect to use:
EnumValue
Enum(tls_type) String(gnu) Value(TLS_GNU)
EnumValue
Enum(tls_type) String(gnu2) Value(TLS_GNU2)
mabi= mabi=
Target RejectNegative Joined Enum(arm_abi_type) Var(arm_abi) Init(ARM_DEFAULT_ABI) Target RejectNegative Joined Enum(arm_abi_type) Var(arm_abi) Init(ARM_DEFAULT_ABI)
Specify an ABI Specify an ABI
...@@ -190,6 +200,10 @@ mthumb-interwork ...@@ -190,6 +200,10 @@ mthumb-interwork
Target Report Mask(INTERWORK) Target Report Mask(INTERWORK)
Support calls between Thumb and ARM instruction sets Support calls between Thumb and ARM instruction sets
mtls-dialect=
Target RejectNegative Joined Enum(tls_type) Var(target_tls_dialect) Init(TLS_GNU)
Specify thread local storage scheme
mtp= mtp=
Target RejectNegative Joined Enum(arm_tp_type) Var(target_thread_pointer) Init(TP_AUTO) Target RejectNegative Joined Enum(arm_tp_type) Var(target_thread_pointer) Init(TP_AUTO)
Specify how to access the thread pointer Specify how to access the thread pointer
......
...@@ -1016,6 +1016,12 @@ information normally used on 386 SVR4 platforms; stabs provide a ...@@ -1016,6 +1016,12 @@ information normally used on 386 SVR4 platforms; stabs provide a
workable alternative. This requires gas and gdb, as the normal SVR4 workable alternative. This requires gas and gdb, as the normal SVR4
tools can not generate or interpret stabs. 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{gnu} or
@code{gnu2}, which select between the original GNU dialect and the GNU TLS
descriptor-based dialect.
@item --disable-multilib @item --disable-multilib
Specify that multiple target Specify that multiple target
libraries to support different target variants, calling libraries to support different target variants, calling
......
...@@ -477,7 +477,7 @@ Objective-C and Objective-C++ Dialects}. ...@@ -477,7 +477,7 @@ Objective-C and Objective-C++ Dialects}.
-mthumb -marm @gol -mthumb -marm @gol
-mtpcs-frame -mtpcs-leaf-frame @gol -mtpcs-frame -mtpcs-leaf-frame @gol
-mcaller-super-interworking -mcallee-super-interworking @gol -mcaller-super-interworking -mcallee-super-interworking @gol
-mtp=@var{name} @gol -mtp=@var{name} -mtls-dialect=@var{dialect} @gol
-mword-relocations @gol -mword-relocations @gol
-mfix-cortex-m3-ldrd} -mfix-cortex-m3-ldrd}
...@@ -10471,6 +10471,18 @@ models are @option{soft}, which generates calls to @code{__aeabi_read_tp}, ...@@ -10471,6 +10471,18 @@ models are @option{soft}, which generates calls to @code{__aeabi_read_tp},
best available method for the selected processor. The default setting is best available method for the selected processor. The default setting is
@option{auto}. @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{gnu} and @option{gnu2}. The
@option{gnu} dialect selects the original GNU scheme for supporting
local and global dynamic TLS models. The @option{gnu2} dialect
selects the GNU descriptor scheme, which provides better performance
for shared libraries. The GNU descriptor scheme is compatible with
the original scheme, but does require new assembler, linker and
library support. Initial and local exec TLS models are unaffected by
this option and always use the original scheme.
@item -mword-relocations @item -mword-relocations
@opindex mword-relocations @opindex mword-relocations
Only generate absolute relocations on word sized values (i.e. R_ARM_ABS32). Only generate absolute relocations on word sized values (i.e. R_ARM_ABS32).
......
2011-06-22 Nathan Sidwell <nathan@codesourcery.com>
* gcc.target/arm/tlscall.c: New.
2011-06-21 Jason Merrill <jason@redhat.com> 2011-06-21 Jason Merrill <jason@redhat.com>
PR c++/49172 PR c++/49172
......
/* Test non-duplication of tlscall insn */
/* { dg-do assemble } */
/* { dg-options "-O2 -fPIC -mtls-dialect=gnu2" } */
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) {}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment