xcoffout.c (xcoff_tls_data_section_name): Define.

* xcoffout.c (xcoff_tls_data_section_name): Define.
        * xcoffout.h (xcoff_tls_data_section_name): Declare.
        * config/rs6000/rs6000.c (tls_data_section): Define.
        (TARGET_USE_BLOCKS_FOR_DECL_P): Define.
        (rs6000_legitimize_tls_address_aix): New function.
        (rs6000_legitimize_tls_address): Use new function for AIX.
        (rs6000_cannot_force_const_mem): No sum in TLS TOC symbols.
        Allow TLS symbol in constant pool other than ELF.
        (rs6000_legitimate_address_p): Allow TLS symbol other than ELF.
        (rs6000_assemble_visibility): Do not emit anything on AIX.
        (output_toc): Handle alias of TLS general-dynamic symbols.
        Emit TLS decorations on symbols.
        (rs6000_use_blocks_for_decl_p): New function.
        (rs6000_xcoff_output_tls_section_asm_op): New function.
        (rs6000_xcoff_asm_init_sections): Initialize tls_data_section.
        (rs6000_xcoff_select_section): Choose tls_data_section for
        thread-local storage.
        (rs6000_xcoff_file_start): Generate xcoff_tls_data_section_name.
        (rs6000_legitimate_constant_p): Allow TLS symbol other than ELF.
        * config/rs6000/rs6000.md (tls_tls_): Restrict to ELF.
        (tls_get_tpointer): New.
        (tle_get_tpointer_internal): New.
        (tls_get_addr<mode>): New.
        (tls_get_addr_internal<mode>): New.

From-SVN: r194003
This commit is contained in:
David Edelsohn 2012-11-30 17:54:07 +00:00 committed by David Edelsohn
parent 2730ada7a0
commit b09cba37bf
5 changed files with 228 additions and 5 deletions

View file

@ -1,3 +1,30 @@
2012-11-30 David Edelsohn <dje.gcc@gmail.com>
* xcoffout.c (xcoff_tls_data_section_name): Define.
* xcoffout.h (xcoff_tls_data_section_name): Declare.
* config/rs6000/rs6000.c (tls_data_section): Define.
(TARGET_USE_BLOCKS_FOR_DECL_P): Define.
(rs6000_legitimize_tls_address_aix): New function.
(rs6000_legitimize_tls_address): Use new function for AIX.
(rs6000_cannot_force_const_mem): No sum in TLS TOC symbols.
Allow TLS symbol in constant pool other than ELF.
(rs6000_legitimate_address_p): Allow TLS symbol other than ELF.
(rs6000_assemble_visibility): Do not emit anything on AIX.
(output_toc): Handle alias of TLS general-dynamic symbols.
Emit TLS decorations on symbols.
(rs6000_use_blocks_for_decl_p): New function.
(rs6000_xcoff_output_tls_section_asm_op): New function.
(rs6000_xcoff_asm_init_sections): Initialize tls_data_section.
(rs6000_xcoff_select_section): Choose tls_data_section for
thread-local storage.
(rs6000_xcoff_file_start): Generate xcoff_tls_data_section_name.
(rs6000_legitimate_constant_p): Allow TLS symbol other than ELF.
* config/rs6000/rs6000.md (tls_tls_): Restrict to ELF.
(tls_get_tpointer): New.
(tle_get_tpointer_internal): New.
(tls_get_addr<mode>): New.
(tls_get_addr_internal<mode>): New.
2012-11-30 Teresa Johnson <tejohnson@google.com>
* lto-cgraph.c (output_profile_summary): Stream out sum_all

View file

@ -208,6 +208,7 @@ static short cached_can_issue_more;
static GTY(()) section *read_only_data_section;
static GTY(()) section *private_data_section;
static GTY(()) section *tls_data_section;
static GTY(()) section *read_only_private_data_section;
static GTY(()) section *sdata2_section;
static GTY(()) section *toc_section;
@ -1405,6 +1406,8 @@ static const struct attribute_spec rs6000_attribute_table[] =
#define TARGET_MAX_ANCHOR_OFFSET 0x7fffffff
#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
#define TARGET_USE_BLOCKS_FOR_CONSTANT_P rs6000_use_blocks_for_constant_p
#undef TARGET_USE_BLOCKS_FOR_DECL_P
#define TARGET_USE_BLOCKS_FOR_DECL_P rs6000_use_blocks_for_decl_p
#undef TARGET_BUILTIN_RECIPROCAL
#define TARGET_BUILTIN_RECIPROCAL rs6000_builtin_reciprocal
@ -5882,6 +5885,75 @@ rs6000_got_sym (void)
return rs6000_got_symbol;
}
/* AIX Thread-Local Address support. */
static rtx
rs6000_legitimize_tls_address_aix (rtx addr, enum tls_model model)
{
rtx sym, mem, tocref, tlsreg, tmpreg, dest;
/* Place addr into TOC constant pool. */
sym = force_const_mem (GET_MODE (addr), addr);
/* Output the TOC entry and create the MEM referencing the value. */
if (constant_pool_expr_p (XEXP (sym, 0))
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (XEXP (sym, 0)), Pmode))
{
tocref = create_TOC_reference (XEXP (sym, 0), NULL_RTX);
mem = gen_const_mem (Pmode, tocref);
set_mem_alias_set (mem, get_TOC_alias_set ());
}
else
return sym;
/* Use global-dynamic for local-dynamic. */
if (model == TLS_MODEL_GLOBAL_DYNAMIC
|| model == TLS_MODEL_LOCAL_DYNAMIC)
{
rtx module = gen_reg_rtx (Pmode);
/* Create new TOC reference for @m symbol. */
const char *name = XSTR (XVECEXP (XEXP (mem, 0), 0, 0), 0);
char *name2 = XALLOCAVEC (char, strlen (name) + 1);
strcpy (name2, "*LCM");
strcat (name2, name + 3);
tocref = create_TOC_reference (gen_rtx_SYMBOL_REF (Pmode,
ggc_alloc_string (name2,
strlen (name2))),
NULL_RTX);
rtx mem2 = gen_const_mem (Pmode, tocref);
set_mem_alias_set (mem2, get_TOC_alias_set ());
dest = gen_reg_rtx (Pmode);
tmpreg = gen_reg_rtx (Pmode);
emit_insn (gen_rtx_SET (VOIDmode, tmpreg, mem));
emit_insn (gen_rtx_SET (VOIDmode, module, mem2));
if (TARGET_32BIT)
emit_insn (gen_tls_get_addrsi (dest, module, tmpreg));
else
emit_insn (gen_tls_get_addrdi (dest, module, tmpreg));
return dest;
}
/* Obtain TLS pointer: 32 bit call or 64 bit GPR 13. */
else if (TARGET_32BIT)
{
tlsreg = gen_reg_rtx (SImode);
emit_insn (gen_tls_get_tpointer (tlsreg));
}
else
tlsreg = gen_rtx_REG (DImode, 13);
/* Load the TOC value into temporary register. */
tmpreg = gen_reg_rtx (Pmode);
emit_insn (gen_rtx_SET (VOIDmode, tmpreg, mem));
set_unique_reg_note (get_last_insn (), REG_EQUAL,
gen_rtx_MINUS (Pmode, addr, tlsreg));
/* Add TOC symbol value to TLS pointer. */
dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tmpreg, tlsreg));
return dest;
}
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
this (thread-local) address. */
@ -5890,6 +5962,9 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
{
rtx dest, insn;
if (TARGET_XCOFF)
return rs6000_legitimize_tls_address_aix (addr, model);
dest = gen_reg_rtx (Pmode);
if (model == TLS_MODEL_LOCAL_EXEC && rs6000_tls_size == 16)
{
@ -6085,7 +6160,15 @@ rs6000_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
&& GET_CODE (XEXP (x, 0)) == UNSPEC)
return true;
return rs6000_tls_referenced_p (x);
/* A TLS symbol in the TOC cannot contain a sum. */
if (GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (XEXP (XEXP (x, 0), 0)) != 0)
return true;
/* Do not place an ELF TLS symbol in the constant pool. */
return TARGET_ELF && rs6000_tls_referenced_p (x);
}
/* Return 1 if *X is a thread-local symbol. This is the same as
@ -6380,7 +6463,7 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
&& INTVAL (XEXP (x, 1)) == -16)
x = XEXP (x, 0);
if (RS6000_SYMBOL_REF_TLS_P (x))
if (TARGET_ELF && RS6000_SYMBOL_REF_TLS_P (x))
return 0;
if (legitimate_indirect_address_p (x, reg_ok_strict))
return 1;
@ -15486,6 +15569,9 @@ rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p)
static void
rs6000_assemble_visibility (tree decl, int vis)
{
if (TARGET_XCOFF)
return;
/* Functions need to have their entry point symbol visibility set as
well as their descriptor symbol visibility. */
if (DEFAULT_ABI == ABI_AIX
@ -21934,6 +22020,20 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
fprintf (file, "%d\n", ((*(const struct toc_hash_struct **)
found)->labelno));
#ifdef HAVE_AS_TLS
if (TARGET_XCOFF && GET_CODE (x) == SYMBOL_REF
&& (SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_GLOBAL_DYNAMIC
|| SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC))
{
fputs ("\t.set ", file);
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LCM");
fprintf (file, "%d,", labelno);
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LCM");
fprintf (file, "%d\n", ((*(const struct toc_hash_struct **)
found)->labelno));
}
#endif
return;
}
}
@ -22206,6 +22306,29 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
}
else
output_addr_const (file, x);
#if HAVE_AS_TLS
if (TARGET_XCOFF && GET_CODE (base) == SYMBOL_REF)
{
if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_EXEC)
fputs ("[TL]@le", file);
else if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_INITIAL_EXEC)
fputs ("[TL]@ie", file);
/* Use global-dynamic for local-dynamic. */
else if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_GLOBAL_DYNAMIC
|| SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_DYNAMIC)
{
fputs ("[TL]\n", file);
(*targetm.asm_out.internal_label) (file, "LCM", labelno);
fputs ("\t.tc .", file);
RS6000_OUTPUT_BASENAME (file, name);
fputs ("[TC],", file);
output_addr_const (file, x);
fputs ("[TL]@m", file);
}
}
#endif
putc ('\n', file);
}
@ -24884,6 +25007,14 @@ rs6000_use_blocks_for_constant_p (enum machine_mode mode, const_rtx x)
{
return !ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode);
}
/* Do not place thread-local symbols refs in the object blocks. */
static bool
rs6000_use_blocks_for_decl_p (const_tree decl)
{
return !DECL_THREAD_LOCAL_P (decl);
}
/* Return a REG that occurs in ADDR with coefficient 1.
ADDR can be effectively incremented by incrementing REG.
@ -25516,6 +25647,14 @@ rs6000_xcoff_output_readwrite_section_asm_op (const void *directive)
XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
}
static void
rs6000_xcoff_output_tls_section_asm_op (const void *directive)
{
fprintf (asm_out_file, "\t.csect %s[TL],%s\n",
*(const char *const *) directive,
XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
}
/* A get_unnamed_section callback, used for switching to toc_section. */
static void
@ -25553,6 +25692,11 @@ rs6000_xcoff_asm_init_sections (void)
rs6000_xcoff_output_readwrite_section_asm_op,
&xcoff_private_data_section_name);
tls_data_section
= get_unnamed_section (SECTION_TLS,
rs6000_xcoff_output_tls_section_asm_op,
&xcoff_tls_data_section_name);
read_only_private_data_section
= get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
&xcoff_private_data_section_name);
@ -25604,7 +25748,12 @@ rs6000_xcoff_select_section (tree decl, int reloc,
}
else
{
if (TREE_PUBLIC (decl))
#if HAVE_AS_TLS
if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
return tls_data_section;
else
#endif
if (TREE_PUBLIC (decl))
return data_section;
else
return private_data_section;
@ -25700,6 +25849,8 @@ rs6000_xcoff_file_start (void)
main_input_filename, ".bss_");
rs6000_gen_section_name (&xcoff_private_data_section_name,
main_input_filename, ".rw_");
rs6000_gen_section_name (&xcoff_tls_data_section_name,
main_input_filename, ".tls_");
rs6000_gen_section_name (&xcoff_read_only_section_name,
main_input_filename, ".ro_");
@ -28164,7 +28315,7 @@ rs6000_address_for_altivec (rtx x)
static bool
rs6000_legitimate_constant_p (enum machine_mode mode, rtx x)
{
if (rs6000_tls_referenced_p (x))
if (TARGET_ELF && rs6000_tls_referenced_p (x))
return false;
return ((GET_CODE (x) != CONST_DOUBLE && GET_CODE (x) != CONST_VECTOR)

View file

@ -9983,8 +9983,51 @@
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTLS))]
"HAVE_AS_TLS"
"TARGET_ELF && HAVE_AS_TLS"
"add %0,%1,%2@tls")
(define_expand "tls_get_tpointer"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(unspec:SI [(const_int 0)] UNSPEC_TLSTLS))]
"TARGET_XCOFF && HAVE_AS_TLS"
"
{
emit_insn (gen_tls_get_tpointer_internal ());
emit_move_insn (operands[0], gen_rtx_REG (SImode, 3));
DONE;
}")
(define_insn "tls_get_tpointer_internal"
[(set (reg:SI 3)
(unspec:SI [(const_int 0)] UNSPEC_TLSTLS))
(clobber (reg:SI LR_REGNO))]
"TARGET_XCOFF && HAVE_AS_TLS"
"bla __get_tpointer")
(define_expand "tls_get_addr<mode>"
[(set (match_operand:P 0 "gpc_reg_operand" "")
(unspec:P [(match_operand:P 1 "gpc_reg_operand" "")
(match_operand:P 2 "gpc_reg_operand" "")] UNSPEC_TLSTLS))]
"TARGET_XCOFF && HAVE_AS_TLS"
"
{
emit_move_insn (gen_rtx_REG (Pmode, 3), operands[1]);
emit_move_insn (gen_rtx_REG (Pmode, 4), operands[2]);
emit_insn (gen_tls_get_addr_internal<mode> ());
emit_move_insn (operands[0], gen_rtx_REG (Pmode, 3));
DONE;
}")
(define_insn "tls_get_addr_internal<mode>"
[(set (reg:P 3)
(unspec:P [(reg:P 3) (reg:P 4)] UNSPEC_TLSTLS))
(clobber (reg:P 0))
(clobber (reg:P 5))
(clobber (reg:P 11))
(clobber (reg:CC CR0_REGNO))
(clobber (reg:P LR_REGNO))]
"TARGET_XCOFF && HAVE_AS_TLS"
"bla __tls_get_addr")
;; Next come insns related to the calling sequence.
;;

View file

@ -66,6 +66,7 @@ static const char *xcoff_current_function_file;
char *xcoff_bss_section_name;
char *xcoff_private_data_section_name;
char *xcoff_tls_data_section_name;
char *xcoff_read_only_section_name;
/* Last source file name mentioned in a NOTE insn. */

View file

@ -126,6 +126,7 @@ extern const char *xcoff_current_include_file;
extern char *xcoff_bss_section_name;
extern char *xcoff_private_data_section_name;
extern char *xcoff_tls_data_section_name;
extern char *xcoff_read_only_section_name;
/* Last source file name mentioned in a NOTE insn. */