summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r--gcc/config/rs6000/rs6000.c124
1 files changed, 99 insertions, 25 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index d25c63c4310..bc663eabcc0 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -209,6 +209,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 *tls_private_data_section;
static GTY(()) section *read_only_private_data_section;
static GTY(()) section *sdata2_section;
static GTY(()) section *toc_section;
@@ -5825,6 +5826,15 @@ rs6000_delegitimize_address (rtx orig_x)
}
#endif
y = XVECEXP (y, 0, 0);
+
+#ifdef HAVE_AS_TLS
+ /* Do not associate thread-local symbols with the original
+ constant pool symbol. */
+ if (TARGET_XCOFF
+ && SYMBOL_REF_TLS_MODEL (get_pool_constant (y)) >= TLS_MODEL_REAL)
+ return orig_x;
+#endif
+
if (offset != NULL_RTX)
y = gen_rtx_PLUS (Pmode, y, offset);
if (!MEM_P (orig_x))
@@ -5898,10 +5908,29 @@ rs6000_got_sym (void)
static rtx
rs6000_legitimize_tls_address_aix (rtx addr, enum tls_model model)
{
- rtx sym, mem, tocref, tlsreg, tmpreg, dest;
+ rtx sym, mem, tocref, tlsreg, tmpreg, dest, tlsaddr;
+ const char *name;
+ char *tlsname;
+
+ name = XSTR (addr, 0);
+ /* Append TLS CSECT qualifier, unless the symbol already is qualified
+ or the symbol will be in TLS private data section. */
+ if (name[strlen (name) - 1] != ']'
+ && (TREE_PUBLIC (SYMBOL_REF_DECL (addr))
+ || bss_initializer_p (SYMBOL_REF_DECL (addr))))
+ {
+ tlsname = XALLOCAVEC (char, strlen (name) + 4);
+ strcpy (tlsname, name);
+ strcat (tlsname,
+ bss_initializer_p (SYMBOL_REF_DECL (addr)) ? "[UL]" : "[TL]");
+ tlsaddr = copy_rtx (addr);
+ XSTR (tlsaddr, 0) = ggc_strdup (tlsname);
+ }
+ else
+ tlsaddr = addr;
/* Place addr into TOC constant pool. */
- sym = force_const_mem (GET_MODE (addr), addr);
+ sym = force_const_mem (GET_MODE (tlsaddr), tlsaddr);
/* Output the TOC entry and create the MEM referencing the value. */
if (constant_pool_expr_p (XEXP (sym, 0))
@@ -5918,27 +5947,28 @@ rs6000_legitimize_tls_address_aix (rtx addr, enum tls_model model)
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 ());
+ name = XSTR (XVECEXP (XEXP (mem, 0), 0, 0), 0);
+ tlsname = XALLOCAVEC (char, strlen (name) + 1);
+ strcpy (tlsname, "*LCM");
+ strcat (tlsname, name + 3);
+ rtx modaddr = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (tlsname));
+ SYMBOL_REF_FLAGS (modaddr) |= SYMBOL_FLAG_LOCAL;
+ tocref = create_TOC_reference (modaddr, NULL_RTX);
+ rtx modmem = gen_const_mem (Pmode, tocref);
+ set_mem_alias_set (modmem, get_TOC_alias_set ());
- dest = gen_reg_rtx (Pmode);
+ rtx modreg = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (VOIDmode, modreg, modmem));
+
tmpreg = gen_reg_rtx (Pmode);
emit_insn (gen_rtx_SET (VOIDmode, tmpreg, mem));
- emit_insn (gen_rtx_SET (VOIDmode, module, mem2));
+
+ dest = gen_reg_rtx (Pmode);
if (TARGET_32BIT)
- emit_insn (gen_tls_get_addrsi (dest, module, tmpreg));
+ emit_insn (gen_tls_get_addrsi (dest, modreg, tmpreg));
else
- emit_insn (gen_tls_get_addrdi (dest, module, tmpreg));
+ emit_insn (gen_tls_get_addrdi (dest, modreg, tmpreg));
return dest;
}
/* Obtain TLS pointer: 32 bit call or 64 bit GPR 13. */
@@ -22316,23 +22346,24 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
output_addr_const (file, x);
#if HAVE_AS_TLS
- if (TARGET_XCOFF && GET_CODE (base) == SYMBOL_REF)
+ if (TARGET_XCOFF && GET_CODE (base) == SYMBOL_REF
+ && SYMBOL_REF_TLS_MODEL (base) != 0)
{
if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_EXEC)
- fputs ("[TL]@le", file);
+ fputs ("@le", file);
else if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_INITIAL_EXEC)
- fputs ("[TL]@ie", file);
+ fputs ("@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);
+ putc ('\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);
+ fputs ("@m", file);
}
}
#endif
@@ -25705,6 +25736,11 @@ rs6000_xcoff_asm_init_sections (void)
rs6000_xcoff_output_tls_section_asm_op,
&xcoff_tls_data_section_name);
+ tls_private_data_section
+ = get_unnamed_section (SECTION_TLS,
+ rs6000_xcoff_output_tls_section_asm_op,
+ &xcoff_private_data_section_name);
+
read_only_private_data_section
= get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
&xcoff_private_data_section_name);
@@ -25758,7 +25794,18 @@ rs6000_xcoff_select_section (tree decl, int reloc,
{
#if HAVE_AS_TLS
if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
- return tls_data_section;
+ {
+ if (TREE_PUBLIC (decl))
+ return tls_data_section;
+ else if (bss_initializer_p (decl))
+ {
+ /* Convert to COMMON to emit in BSS. */
+ DECL_COMMON (decl) = 1;
+ return tls_comm_section;
+ }
+ else
+ return tls_private_data_section;
+ }
else
#endif
if (TREE_PUBLIC (decl))
@@ -25857,10 +25904,12 @@ 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_");
+ rs6000_gen_section_name (&xcoff_tls_data_section_name,
+ main_input_filename, ".tls_");
+ rs6000_gen_section_name (&xcoff_tbss_section_name,
+ main_input_filename, ".tbss_[UL]");
fputs ("\t.file\t", asm_out_file);
output_quoted_string (asm_out_file, main_input_filename);
@@ -25886,6 +25935,31 @@ rs6000_xcoff_file_end (void)
? "\t.long _section_.text\n" : "\t.llong _section_.text\n",
asm_out_file);
}
+
+#ifdef HAVE_AS_TLS
+static void
+rs6000_xcoff_encode_section_info (tree decl, rtx rtl, int first)
+{
+ rtx symbol;
+ int flags;
+
+ default_encode_section_info (decl, rtl, first);
+
+ /* Careful not to prod global register variables. */
+ if (!MEM_P (rtl))
+ return;
+ symbol = XEXP (rtl, 0);
+ if (GET_CODE (symbol) != SYMBOL_REF)
+ return;
+
+ flags = SYMBOL_REF_FLAGS (symbol);
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
+ flags &= ~SYMBOL_FLAG_HAS_BLOCK_INFO;
+
+ SYMBOL_REF_FLAGS (symbol) = flags;
+}
+#endif /* HAVE_AS_TLS */
#endif /* TARGET_XCOFF */
/* Compute a (partial) cost for rtx X. Return true if the complete