Revert emutls patch.
From-SVN: r117578
This commit is contained in:
parent
5771bd91ec
commit
a98d4769d5
47 changed files with 97 additions and 597 deletions
|
@ -1,3 +1,7 @@
|
|||
2006-10-09 Richard Henderson <rth@redhat.com>
|
||||
|
||||
Revert emutls patch.
|
||||
|
||||
2006-10-09 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/29254
|
||||
|
|
|
@ -1422,9 +1422,9 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) specs \
|
|||
LIBGCOV='$(LIBGCOV)' \
|
||||
LIB2ADD='$(LIB2ADD)' \
|
||||
LIB2ADD_ST='$(LIB2ADD_ST)' \
|
||||
LIB2ADDEH='$(LIB2ADDEH) $(srcdir)/emutls.c' \
|
||||
LIB2ADDEHSTATIC='$(LIB2ADDEHSTATIC) $(srcdir)/emutls.c' \
|
||||
LIB2ADDEHSHARED='$(LIB2ADDEHSHARED) $(srcdir)/emutls.c' \
|
||||
LIB2ADDEH='$(LIB2ADDEH)' \
|
||||
LIB2ADDEHSTATIC='$(LIB2ADDEHSTATIC)' \
|
||||
LIB2ADDEHSHARED='$(LIB2ADDEHSHARED)' \
|
||||
LIB2ADDEHDEP='$(LIB2ADDEHDEP)' \
|
||||
LIB2_SIDITI_CONV_FUNCS='$(LIB2_SIDITI_CONV_FUNCS)' \
|
||||
LIBUNWIND='$(LIBUNWIND)' \
|
||||
|
@ -1469,8 +1469,8 @@ LIBGCC_DEPS = $(GCC_PASSES) stmp-int-hdrs $(STMP_FIXPROTO) \
|
|||
$(MACHMODE_H) longlong.h gbl-ctors.h config.status $(srcdir)/libgcc2.h \
|
||||
tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
|
||||
config/dfp-bit.h config/dfp-bit.c \
|
||||
$(LIB2ADD_ST) $(LIB2ADDEH) $(srcdir)/emutls.c $(LIB2ADDEHDEP) \
|
||||
$(EXTRA_PARTS) $(srcdir)/config/$(LIB1ASMSRC) \
|
||||
$(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
|
||||
$(srcdir)/config/$(LIB1ASMSRC) \
|
||||
$(srcdir)/gcov-io.h $(srcdir)/gcov-io.c gcov-iov.h $(SFP_MACHINE)
|
||||
|
||||
libgcov.a: libgcc.a; @true
|
||||
|
|
|
@ -75,7 +75,7 @@ DEF_PRIMITIVE_TYPE (BT_LONGLONG, long_long_integer_type_node)
|
|||
DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
|
||||
DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 0))
|
||||
DEF_PRIMITIVE_TYPE (BT_FLOAT, float_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_DOUBLE, double_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE, long_double_type_node)
|
||||
|
@ -376,8 +376,6 @@ DEF_FUNCTION_TYPE_4 (BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG,
|
|||
BT_INT, BT_FILEPTR, BT_INT, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
|
||||
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
|
||||
BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
|
||||
|
||||
DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* This file contains the definitions and documentation for the
|
||||
builtins used in the GNU compiler.
|
||||
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
@ -723,10 +723,6 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_VPRINTF_CHK, "__vprintf_chk", BT_FN_INT_INT_CON
|
|||
DEF_BUILTIN_STUB (BUILT_IN_PROFILE_FUNC_ENTER, "profile_func_enter")
|
||||
DEF_BUILTIN_STUB (BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit")
|
||||
|
||||
/* TLS emulation. */
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_EMUTLS_GET_ADDRESS, "__emutls_get_address", BT_FN_PTR_PTR, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_EMUTLS_REGISTER_COMMON, "__emutls_register_common", BT_FN_VOID_PTR_WORD_WORD_PTR, ATTR_NOTHROW_LIST)
|
||||
|
||||
/* Synchronization Primitives. */
|
||||
#include "sync-builtins.def"
|
||||
|
||||
|
|
|
@ -4838,7 +4838,14 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
}
|
||||
|
||||
if (threadp)
|
||||
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
|
||||
{
|
||||
if (targetm.have_tls)
|
||||
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
|
||||
else
|
||||
/* A mere warning is sure to result in improper semantics
|
||||
at runtime. Don't bother to allow this to compile. */
|
||||
error ("thread-local storage not supported for this target");
|
||||
}
|
||||
}
|
||||
|
||||
if (storage_class == csc_extern
|
||||
|
|
|
@ -7801,6 +7801,9 @@ c_parser_omp_threadprivate (c_parser *parser)
|
|||
c_parser_consume_pragma (parser);
|
||||
vars = c_parser_omp_var_list_parens (parser, 0, NULL);
|
||||
|
||||
if (!targetm.have_tls)
|
||||
sorry ("threadprivate variables not supported in this target");
|
||||
|
||||
/* Mark every variable in VARS to be assigned thread local storage. */
|
||||
for (t = vars; t; t = TREE_CHAIN (t))
|
||||
{
|
||||
|
|
13
gcc/cgraph.c
13
gcc/cgraph.c
|
@ -939,7 +939,7 @@ bool
|
|||
decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
|
||||
{
|
||||
/* If the user told us it is used, then it must be so. */
|
||||
if (node->externally_visible || node->force_output)
|
||||
if (node->externally_visible)
|
||||
return true;
|
||||
if (!flag_unit_at_a_time
|
||||
&& lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
|
||||
|
@ -963,17 +963,6 @@ decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
|
|||
&& !DECL_EXTERNAL (decl))
|
||||
return true;
|
||||
|
||||
/* When emulating tls, we actually see references to the control
|
||||
variable, rather than the user-level variable. */
|
||||
if (!targetm.have_tls
|
||||
&& TREE_CODE (decl) == VAR_DECL
|
||||
&& DECL_THREAD_LOCAL_P (decl))
|
||||
{
|
||||
tree control = emutls_decl (decl);
|
||||
if (decide_is_variable_needed (cgraph_varpool_node (control), control))
|
||||
return true;
|
||||
}
|
||||
|
||||
/* When not reordering top level variables, we have to assume that
|
||||
we are going to keep everything. */
|
||||
if (flag_unit_at_a_time && flag_toplevel_reorder)
|
||||
|
|
|
@ -328,7 +328,10 @@ cgraph_varpool_remove_unreferenced_decls (void)
|
|||
node->needed = 0;
|
||||
|
||||
if (node->finalized
|
||||
&& (decide_is_variable_needed (node, decl)
|
||||
&& ((DECL_ASSEMBLER_NAME_SET_P (decl)
|
||||
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|
||||
|| node->force_output
|
||||
|| decide_is_variable_needed (node, decl)
|
||||
/* ??? Cgraph does not yet rule the world with an iron hand,
|
||||
and does not control the emission of debug information.
|
||||
After a variable has its DECL_RTL set, we must assume that
|
||||
|
@ -1709,7 +1712,6 @@ cgraph_build_static_cdtor (char which, tree body, int priority)
|
|||
{
|
||||
tree_lowering_passes (decl);
|
||||
tree_rest_of_compilation (decl);
|
||||
cgraph_varpool_assemble_pending_decls ();
|
||||
}
|
||||
else
|
||||
cgraph_finalize_function (decl, 0);
|
||||
|
|
|
@ -89,7 +89,7 @@ Boston, MA 02110-1301, USA. */
|
|||
{ \
|
||||
HOST_WIDE_INT size; \
|
||||
\
|
||||
if (targetm.have_tls && DECL_THREAD_LOCAL_P (DECL)) \
|
||||
if (DECL_THREAD_LOCAL_P (DECL)) \
|
||||
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "tls_object"); \
|
||||
else \
|
||||
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2006-10-09 Richard Henderson <rth@redhat.com>
|
||||
|
||||
Revert emutls patch.
|
||||
|
||||
2006-10-04 Richard Henderson <rth@redhat.com>
|
||||
Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
|
|
|
@ -6321,7 +6321,14 @@ grokvardecl (tree type,
|
|||
}
|
||||
|
||||
if (declspecs->specs[(int)ds_thread])
|
||||
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
|
||||
{
|
||||
if (targetm.have_tls)
|
||||
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
|
||||
else
|
||||
/* A mere warning is sure to result in improper semantics
|
||||
at runtime. Don't bother to allow this to compile. */
|
||||
error ("thread-local storage not supported for this target");
|
||||
}
|
||||
|
||||
if (TREE_PUBLIC (decl))
|
||||
{
|
||||
|
@ -8449,7 +8456,15 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
DECL_EXTERNAL (decl) = 1;
|
||||
|
||||
if (thread_p)
|
||||
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
|
||||
{
|
||||
if (targetm.have_tls)
|
||||
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
|
||||
else
|
||||
/* A mere warning is sure to result in improper
|
||||
semantics at runtime. Don't bother to allow this to
|
||||
compile. */
|
||||
error ("thread-local storage not supported for this target");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -18964,6 +18964,9 @@ cp_parser_omp_threadprivate (cp_parser *parser, cp_token *pragma_tok)
|
|||
vars = cp_parser_omp_var_list (parser, 0, NULL);
|
||||
cp_parser_require_pragma_eol (parser, pragma_tok);
|
||||
|
||||
if (!targetm.have_tls)
|
||||
sorry ("threadprivate variables not supported in this target");
|
||||
|
||||
finish_omp_threadprivate (vars);
|
||||
}
|
||||
|
||||
|
|
|
@ -9130,7 +9130,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
|
|||
rtx rtl;
|
||||
|
||||
/* If this is not defined, we have no way to emit the data. */
|
||||
if (!targetm.have_tls || !targetm.asm_out.output_dwarf_dtprel)
|
||||
if (!targetm.asm_out.output_dwarf_dtprel)
|
||||
return 0;
|
||||
|
||||
/* The way DW_OP_GNU_push_tls_address is specified, we can only
|
||||
|
|
193
gcc/emutls.c
193
gcc/emutls.c
|
@ -1,193 +0,0 @@
|
|||
/* TLS emulation.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
In addition to the permissions in the GNU General Public License, the
|
||||
Free Software Foundation gives you unlimited permission to link the
|
||||
compiled version of this file into combinations with other programs,
|
||||
and to distribute those combinations without any restriction coming
|
||||
from the use of this file. (The General Public License restrictions
|
||||
do apply in other respects; for example, they cover modification of
|
||||
the file, and distribution when not linked into a combine
|
||||
executable.)
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "tconfig.h"
|
||||
#include "tsystem.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "gthr.h"
|
||||
|
||||
typedef unsigned int word __attribute__((mode(word)));
|
||||
typedef unsigned int pointer __attribute__((mode(pointer)));
|
||||
|
||||
struct __emutls_object
|
||||
{
|
||||
word size;
|
||||
word align;
|
||||
union {
|
||||
pointer offset;
|
||||
void *ptr;
|
||||
} loc;
|
||||
void *templ;
|
||||
};
|
||||
|
||||
#ifdef __GTHREADS
|
||||
#ifdef __GTHREAD_MUTEX_INIT
|
||||
static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT;
|
||||
#else
|
||||
static __gthread_mutex_t emutls_mutex;
|
||||
#endif
|
||||
static __gthread_key_t emutls_key;
|
||||
static pointer emutls_size;
|
||||
|
||||
static void
|
||||
emutls_destroy (void *ptr)
|
||||
{
|
||||
void ***arr = (void ***) ptr;
|
||||
unsigned long int size = (unsigned long int) arr[0];
|
||||
++arr;
|
||||
while (--size)
|
||||
{
|
||||
if (*arr)
|
||||
free ((*arr)[-1]);
|
||||
++arr;
|
||||
}
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
emutls_init (void)
|
||||
{
|
||||
#ifndef __GTHREAD_MUTEX_INIT
|
||||
__GTHREAD_MUTEX_INIT_FUNCTION (&emutls_mutex);
|
||||
#endif
|
||||
if (__gthread_key_create (&emutls_key, emutls_destroy) != 0)
|
||||
abort ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *
|
||||
emutls_alloc (struct __emutls_object *obj)
|
||||
{
|
||||
void *ptr;
|
||||
void *ret;
|
||||
|
||||
/* We could use here posix_memalign if available and adjust
|
||||
emutls_destroy accordingly. */
|
||||
if (obj->align <= sizeof (void *))
|
||||
{
|
||||
ptr = malloc (obj->size + sizeof (void *));
|
||||
if (ptr == NULL)
|
||||
abort ();
|
||||
((void **) ptr)[0] = ptr;
|
||||
ret = ptr + sizeof (void *);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = malloc (obj->size + sizeof (void *) + obj->align - 1);
|
||||
if (ptr == NULL)
|
||||
abort ();
|
||||
ret = (void *) (((pointer) (ptr + sizeof (void *) + obj->align - 1))
|
||||
& ~(pointer)(obj->align - 1));
|
||||
((void **) ret)[-1] = ptr;
|
||||
}
|
||||
|
||||
if (obj->templ)
|
||||
memcpy (ret, obj->templ, obj->size);
|
||||
else
|
||||
memset (ret, 0, obj->size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *
|
||||
__emutls_get_address (struct __emutls_object *obj)
|
||||
{
|
||||
if (! __gthread_active_p ())
|
||||
{
|
||||
if (__builtin_expect (obj->loc.ptr == NULL, 0))
|
||||
obj->loc.ptr = emutls_alloc (obj);
|
||||
return obj->loc.ptr;
|
||||
}
|
||||
|
||||
#ifndef __GTHREADS
|
||||
abort ();
|
||||
#else
|
||||
pointer offset;
|
||||
|
||||
if (__builtin_expect (obj->loc.offset == 0, 0))
|
||||
{
|
||||
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
|
||||
__gthread_once (&once, emutls_init);
|
||||
__gthread_mutex_lock (&emutls_mutex);
|
||||
offset = ++emutls_size;
|
||||
obj->loc.offset = offset;
|
||||
__gthread_mutex_unlock (&emutls_mutex);
|
||||
}
|
||||
else
|
||||
offset = obj->loc.offset;
|
||||
|
||||
void **arr = (void **) __gthread_getspecific (emutls_key);
|
||||
if (__builtin_expect (arr == NULL, 0))
|
||||
{
|
||||
pointer size = offset + 32;
|
||||
arr = calloc (size, sizeof (void *));
|
||||
if (arr == NULL)
|
||||
abort ();
|
||||
arr[0] = (void *) size;
|
||||
__gthread_setspecific (emutls_key, (void *) arr);
|
||||
}
|
||||
else if (__builtin_expect (offset >= (pointer) arr[0], 0))
|
||||
{
|
||||
pointer orig_size = (pointer) arr[0];
|
||||
pointer size = orig_size * 2;
|
||||
if (offset >= size)
|
||||
size = offset + 32;
|
||||
arr = realloc (arr, size * sizeof (void *));
|
||||
if (arr == NULL)
|
||||
abort ();
|
||||
memset (arr + orig_size, 0, (size - orig_size) * sizeof (void *));
|
||||
__gthread_setspecific (emutls_key, (void *) arr);
|
||||
}
|
||||
|
||||
void *ret = arr[offset];
|
||||
if (__builtin_expect (ret == NULL, 0))
|
||||
{
|
||||
ret = emutls_alloc (obj);
|
||||
arr[offset] = ret;
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
__emutls_register_common (struct __emutls_object *obj,
|
||||
word size, word align, void *templ)
|
||||
{
|
||||
if (obj->size < size)
|
||||
{
|
||||
obj->size = size;
|
||||
obj->templ = NULL;
|
||||
}
|
||||
if (obj->align < align)
|
||||
obj->align = align;
|
||||
if (templ && size == obj->size)
|
||||
obj->templ = templ;
|
||||
}
|
35
gcc/expr.c
35
gcc/expr.c
|
@ -6360,19 +6360,6 @@ highest_pow2_factor_for_target (tree target, tree exp)
|
|||
return MAX (factor, target_align);
|
||||
}
|
||||
|
||||
/* Return &VAR expression for emulated thread local VAR. */
|
||||
|
||||
static tree
|
||||
emutls_var_address (tree var)
|
||||
{
|
||||
tree emuvar = emutls_decl (var);
|
||||
tree fn = built_in_decls [BUILT_IN_EMUTLS_GET_ADDRESS];
|
||||
tree arg = build_fold_addr_expr_with_type (emuvar, ptr_type_node);
|
||||
tree arglist = build_tree_list (NULL_TREE, arg);
|
||||
tree call = build_function_call_expr (fn, arglist);
|
||||
return fold_convert (build_pointer_type (TREE_TYPE (var)), call);
|
||||
}
|
||||
|
||||
/* Expands variable VAR. */
|
||||
|
||||
void
|
||||
|
@ -6501,18 +6488,6 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
|
|||
inner = TREE_OPERAND (exp, 0);
|
||||
break;
|
||||
|
||||
case VAR_DECL:
|
||||
/* TLS emulation hook - replace __thread VAR's &VAR with
|
||||
__emutls_get_address (&_emutls.VAR). */
|
||||
if (! targetm.have_tls
|
||||
&& TREE_CODE (exp) == VAR_DECL
|
||||
&& DECL_THREAD_LOCAL_P (exp))
|
||||
{
|
||||
exp = emutls_var_address (exp);
|
||||
return expand_expr (exp, target, tmode, modifier);
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
default:
|
||||
/* If the object is a DECL, then expand it for its rtl. Don't bypass
|
||||
expand_expr, as that can have various side effects; LABEL_DECLs for
|
||||
|
@ -6878,16 +6853,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
|||
&& (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
|
||||
layout_decl (exp, 0);
|
||||
|
||||
/* TLS emulation hook - replace __thread vars with
|
||||
*__emutls_get_address (&_emutls.var). */
|
||||
if (! targetm.have_tls
|
||||
&& TREE_CODE (exp) == VAR_DECL
|
||||
&& DECL_THREAD_LOCAL_P (exp))
|
||||
{
|
||||
exp = build_fold_indirect_ref (emutls_var_address (exp));
|
||||
return expand_expr_real_1 (exp, target, tmode, modifier, NULL);
|
||||
}
|
||||
|
||||
/* ... fall through ... */
|
||||
|
||||
case FUNCTION_DECL:
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2006-10-09 Richard Henderson <rth@redhat.com>
|
||||
|
||||
Revert emutls patch.
|
||||
|
||||
2006-10-09 Francois-Xavier Coudert <coudert@clipper.ens.fr>
|
||||
|
||||
* intrinsic.c (add_sym_0s, add_sym_1s, add_sym_2s, add_sym_3s,
|
||||
|
|
|
@ -1102,14 +1102,6 @@ gfc_init_builtin_functions (void)
|
|||
BUILT_IN_TRAP, NULL, false);
|
||||
TREE_THIS_VOLATILE (built_in_decls[BUILT_IN_TRAP]) = 1;
|
||||
|
||||
gfc_define_builtin ("__emutls_get_address",
|
||||
builtin_types[BT_FN_PTR_PTR], BUILT_IN_EMUTLS_GET_ADDRESS,
|
||||
"__emutls_get_address", true);
|
||||
gfc_define_builtin ("__emutls_register_common",
|
||||
builtin_types[BT_FN_VOID_PTR_WORD_WORD_PTR],
|
||||
BUILT_IN_EMUTLS_REGISTER_COMMON,
|
||||
"__emutls_register_common", false);
|
||||
|
||||
build_common_builtin_nodes ();
|
||||
targetm.init_builtins ();
|
||||
}
|
||||
|
|
|
@ -465,6 +465,12 @@ gfc_match_omp_threadprivate (void)
|
|||
if (m != MATCH_YES)
|
||||
return m;
|
||||
|
||||
if (!targetm.have_tls)
|
||||
{
|
||||
sorry ("threadprivate variables not supported in this target");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
m = gfc_match_symbol (&sym, 0);
|
||||
|
|
|
@ -388,7 +388,7 @@ build_common_decl (gfc_common_head *com, tree union_type, bool is_init)
|
|||
|
||||
gfc_set_decl_location (decl, &com->where);
|
||||
|
||||
if (com->threadprivate)
|
||||
if (com->threadprivate && targetm.have_tls)
|
||||
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
|
||||
|
||||
/* Place the back end declaration for this common block in
|
||||
|
|
|
@ -522,7 +522,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
|
|||
TREE_STATIC (decl) = 1;
|
||||
|
||||
/* Handle threadprivate variables. */
|
||||
if (sym->attr.threadprivate
|
||||
if (sym->attr.threadprivate && targetm.have_tls
|
||||
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
|
||||
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ DEF_PRIMITIVE_TYPE (BT_BOOL, boolean_type_node)
|
|||
DEF_PRIMITIVE_TYPE (BT_INT, integer_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_UINT, unsigned_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_LONG, long_integer_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
|
||||
|
||||
DEF_PRIMITIVE_TYPE (BT_I1, builtin_type_for_size (BITS_PER_UNIT*1, 1))
|
||||
DEF_PRIMITIVE_TYPE (BT_I2, builtin_type_for_size (BITS_PER_UNIT*2, 1))
|
||||
|
@ -82,7 +81,6 @@ DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTR, BT_VOID, BT_PTR)
|
|||
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_PTR_PTR, BT_PTR, BT_PTR)
|
||||
|
||||
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
|
||||
|
||||
|
@ -115,8 +113,6 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
|
|||
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
|
||||
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
|
||||
BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
|
||||
|
||||
DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
|
||||
BT_BOOL, BT_LONG, BT_LONG, BT_LONG,
|
||||
|
|
|
@ -273,6 +273,4 @@ GCC_4.2.0 {
|
|||
__floatuntixf
|
||||
__floatuntitf
|
||||
_Unwind_GetIPInfo
|
||||
__emutls_get_address
|
||||
__emutls_register_common
|
||||
}
|
||||
|
|
|
@ -158,9 +158,6 @@ extern void merge_weak (tree, tree);
|
|||
/* Emit any pending weak declarations. */
|
||||
extern void weak_finish (void);
|
||||
|
||||
/* Emit any pending emutls declarations and initializations. */
|
||||
extern void emutls_finish (void);
|
||||
|
||||
/* Decode an `asm' spec for a declaration as a register name.
|
||||
Return the register number, or -1 if nothing specified,
|
||||
or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized,
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2006-10-09 Richard Henderson <rth@redhat.com>
|
||||
|
||||
Revert emutls patch.
|
||||
|
||||
2006-10-09 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/29254
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* { dg-do link } */
|
||||
/* { dg-require-alias "" } */
|
||||
/* { dg-require-visibility "" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
/* Test that encode_section_info handles the change from externally
|
||||
defined to locally defined (via hidden). Extracted from glibc. */
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* { dg-options "-Werror" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
__thread int i;
|
||||
|
||||
int foo ()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* { dg-do assemble } */
|
||||
/* { dg-options "-g" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
__thread int i;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Valid __thread specifiers. */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
__thread int g1;
|
||||
extern __thread int g2;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Invalid __thread specifiers. */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
__thread extern int g1; /* { dg-error "'__thread' before 'extern'" } */
|
||||
__thread static int g2; /* { dg-error "'__thread' before 'static'" } */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Report invalid extern and __thread combinations. */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
extern int j; /* { dg-error "previous declaration" } */
|
||||
__thread int j; /* { dg-error "follows non-thread-local" } */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* Invalid __thread specifiers. As diag-4.c but some cases in
|
||||
different orders. */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
__thread typedef int g4; /* { dg-error "'__thread' used with 'typedef'" } */
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* __thread specifiers on empty declarations. */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
__thread struct foo; /* { dg-warning "warning: useless '__thread' in empty declaration" } */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Invalid initializations. */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
extern __thread int i;
|
||||
int *p = &i; /* { dg-error "initializer element is not constant" } */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftls-model=initial-exec" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
extern __thread long e1;
|
||||
extern __thread int e2;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O3 -fpic" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
/* The web pass was creating unrecognisable pic_load_dot_plus_four insns
|
||||
on ARM. */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
/* Sched1 moved {load_tp} pattern between strlen call and the copy
|
||||
of the hard return value to its pseudo. This resulted in a
|
||||
reload abort, since the hard register was not spillable. */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* PR 18910 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
static __thread void *foo [2];
|
||||
void
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* PR 21412 */
|
||||
/* { dg-do compile */
|
||||
/* { dg-options "-O2 -fPIC" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
struct S { int x[10]; };
|
||||
extern __thread struct S s;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fpic -ftls-model=global-dynamic" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
extern __thread long e1;
|
||||
extern __thread int e2;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
to allow addends for @dtpoff relocs or not. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fpic" } */
|
||||
/* { dg-require-effective-target tls } */
|
||||
|
||||
struct S {
|
||||
int s0, s1, s2, s3;
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
/* { dg-require-effective-target tls } */
|
||||
|
||||
__thread int i;
|
||||
|
|
|
@ -384,7 +384,7 @@ proc check_effective_target_pcc_bitfield_type_matters { } {
|
|||
}]
|
||||
}
|
||||
|
||||
# Return 1 if *native* thread local storage (TLS) is supported, 0 otherwise.
|
||||
# Return 1 if thread local storage (TLS) is supported, 0 otherwise.
|
||||
#
|
||||
# This won't change for different subtargets so cache the result.
|
||||
|
||||
|
@ -406,19 +406,11 @@ proc check_effective_target_tls {} {
|
|||
close $f
|
||||
|
||||
# Test for thread-local data supported by the platform.
|
||||
set comp_output [${tool}_target_compile $src $asm assembly ""]
|
||||
set comp_output \
|
||||
[${tool}_target_compile $src $asm assembly ""]
|
||||
file delete $src
|
||||
if { [string match "*not supported*" $comp_output] } {
|
||||
set et_tls_saved 0
|
||||
} else {
|
||||
set fd [open $asm r]
|
||||
set text [read $fd]
|
||||
close $fd
|
||||
if { [string match "*emutls*" $text]} {
|
||||
set et_tls_saved 0
|
||||
} else {
|
||||
set et_tls_saved 1
|
||||
}
|
||||
}
|
||||
remove-build-file $asm
|
||||
}
|
||||
|
|
|
@ -1056,14 +1056,11 @@ compile_file (void)
|
|||
if (flag_mudflap)
|
||||
mudflap_finish_file ();
|
||||
|
||||
/* Likewise for emulated thread-local storage. */
|
||||
if (!targetm.have_tls)
|
||||
emutls_finish ();
|
||||
|
||||
output_shared_constant_pool ();
|
||||
output_object_blocks ();
|
||||
|
||||
/* Write out any pending weak symbol declarations. */
|
||||
|
||||
weak_finish ();
|
||||
|
||||
/* Do dbx symbols. */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Memory address lowering and addressing mode selection.
|
||||
Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
|
@ -134,15 +134,10 @@ gen_addr_rtx (rtx symbol, rtx base, rtx index, rtx step, rtx offset,
|
|||
act_elem = symbol;
|
||||
if (offset)
|
||||
{
|
||||
act_elem = gen_rtx_PLUS (Pmode, act_elem, offset);
|
||||
|
||||
act_elem = gen_rtx_CONST (Pmode,
|
||||
gen_rtx_PLUS (Pmode, act_elem, offset));
|
||||
if (offset_p)
|
||||
*offset_p = &XEXP (act_elem, 1);
|
||||
|
||||
if (GET_CODE (symbol) == SYMBOL_REF
|
||||
|| GET_CODE (symbol) == LABEL_REF
|
||||
|| GET_CODE (symbol) == CONST)
|
||||
act_elem = gen_rtx_CONST (Pmode, act_elem);
|
||||
*offset_p = &XEXP (XEXP (act_elem, 0), 1);
|
||||
}
|
||||
|
||||
if (*addr)
|
||||
|
|
|
@ -4460,7 +4460,6 @@ extern void set_user_assembler_name (tree, const char *);
|
|||
extern void process_pending_assemble_externals (void);
|
||||
extern void finish_aliases_1 (void);
|
||||
extern void finish_aliases_2 (void);
|
||||
extern tree emutls_decl (tree);
|
||||
|
||||
/* In stmt.c */
|
||||
extern void expand_computed_goto (tree);
|
||||
|
|
294
gcc/varasm.c
294
gcc/varasm.c
|
@ -53,7 +53,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
|||
#include "cgraph.h"
|
||||
#include "cfglayout.h"
|
||||
#include "basic-block.h"
|
||||
#include "tree-iterator.h"
|
||||
|
||||
#ifdef XCOFF_DEBUGGING_INFO
|
||||
#include "xcoffout.h" /* Needed for external data
|
||||
|
@ -201,236 +200,6 @@ static GTY(()) int anchor_labelno;
|
|||
/* A pool of constants that can be shared between functions. */
|
||||
static GTY(()) struct rtx_constant_pool *shared_constant_pool;
|
||||
|
||||
/* TLS emulation. */
|
||||
|
||||
static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
|
||||
htab_t emutls_htab;
|
||||
static GTY (()) tree emutls_object_type;
|
||||
|
||||
#ifndef NO_DOT_IN_LABEL
|
||||
# define EMUTLS_VAR_PREFIX "__emutls_v."
|
||||
# define EMUTLS_TMPL_PREFIX "__emutls_t."
|
||||
#elif !defined NO_DOLLAR_IN_LABEL
|
||||
# define EMUTLS_VAR_PREFIX "__emutls_v$"
|
||||
# define EMUTLS_TMPL_PREFIX "__emutls_t$"
|
||||
#else
|
||||
# define EMUTLS_VAR_PREFIX "__emutls_v_"
|
||||
# define EMUTLS_TMPL_PREFIX "__emutls_t_"
|
||||
#endif
|
||||
|
||||
/* Create an identifier for the struct __emutls_object, given an identifier
|
||||
of the DECL_ASSEMBLY_NAME of the original object. */
|
||||
|
||||
static tree
|
||||
get_emutls_object_name (tree name)
|
||||
{
|
||||
char *toname = alloca (strlen (IDENTIFIER_POINTER (name))
|
||||
+ sizeof (EMUTLS_VAR_PREFIX));
|
||||
strcpy (toname, EMUTLS_VAR_PREFIX);
|
||||
strcpy (toname + sizeof (EMUTLS_VAR_PREFIX) - 1, IDENTIFIER_POINTER (name));
|
||||
|
||||
return get_identifier (toname);
|
||||
}
|
||||
|
||||
/* Create the structure for struct __emutls_object. This should match the
|
||||
structure at the top of emutls.c, modulo the union there. */
|
||||
|
||||
static tree
|
||||
get_emutls_object_type (void)
|
||||
{
|
||||
tree type, type_name, field, next_field, word_type_node;
|
||||
|
||||
type = emutls_object_type;
|
||||
if (type)
|
||||
return type;
|
||||
|
||||
emutls_object_type = type = lang_hooks.types.make_type (RECORD_TYPE);
|
||||
type_name = get_identifier ("__emutls_object");
|
||||
type_name = build_decl (TYPE_DECL, type_name, type);
|
||||
TYPE_NAME (type) = type_name;
|
||||
|
||||
field = build_decl (FIELD_DECL, get_identifier ("__templ"), ptr_type_node);
|
||||
DECL_CONTEXT (field) = type;
|
||||
next_field = field;
|
||||
|
||||
field = build_decl (FIELD_DECL, get_identifier ("__offset"), ptr_type_node);
|
||||
DECL_CONTEXT (field) = type;
|
||||
TREE_CHAIN (field) = next_field;
|
||||
next_field = field;
|
||||
|
||||
word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
|
||||
field = build_decl (FIELD_DECL, get_identifier ("__align"), word_type_node);
|
||||
DECL_CONTEXT (field) = type;
|
||||
TREE_CHAIN (field) = next_field;
|
||||
next_field = field;
|
||||
|
||||
field = build_decl (FIELD_DECL, get_identifier ("__size"), word_type_node);
|
||||
DECL_CONTEXT (field) = type;
|
||||
TREE_CHAIN (field) = next_field;
|
||||
|
||||
TYPE_FIELDS (type) = field;
|
||||
layout_type (type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Create a read-only variable like DECL, with the same DECL_INITIAL.
|
||||
This will be used for initializing the emulated tls data area. */
|
||||
|
||||
static tree
|
||||
get_emutls_init_templ_addr (tree decl)
|
||||
{
|
||||
tree name, to;
|
||||
char *toname;
|
||||
|
||||
if (!DECL_INITIAL (decl))
|
||||
return null_pointer_node;
|
||||
|
||||
name = DECL_ASSEMBLER_NAME (decl);
|
||||
toname = alloca (strlen (IDENTIFIER_POINTER (name))
|
||||
+ sizeof (EMUTLS_TMPL_PREFIX));
|
||||
strcpy (toname, EMUTLS_TMPL_PREFIX);
|
||||
strcpy (toname + sizeof (EMUTLS_TMPL_PREFIX) - 1, IDENTIFIER_POINTER (name));
|
||||
name = get_identifier (toname);
|
||||
|
||||
to = build_decl (VAR_DECL, name, TREE_TYPE (decl));
|
||||
SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
|
||||
|
||||
DECL_ARTIFICIAL (to) = 1;
|
||||
TREE_USED (to) = TREE_USED (decl);
|
||||
TREE_READONLY (to) = 1;
|
||||
DECL_IGNORED_P (to) = 1;
|
||||
DECL_CONTEXT (to) = DECL_CONTEXT (decl);
|
||||
DECL_WEAK (to) = DECL_WEAK (decl);
|
||||
if (DECL_ONE_ONLY (decl))
|
||||
{
|
||||
make_decl_one_only (to);
|
||||
TREE_STATIC (to) = TREE_STATIC (decl);
|
||||
TREE_PUBLIC (to) = TREE_PUBLIC (decl);
|
||||
DECL_VISIBILITY (to) = DECL_VISIBILITY (decl);
|
||||
}
|
||||
else
|
||||
TREE_STATIC (to) = 1;
|
||||
|
||||
DECL_INITIAL (to) = DECL_INITIAL (decl);
|
||||
DECL_INITIAL (decl) = NULL;
|
||||
|
||||
cgraph_varpool_finalize_decl (to);
|
||||
return build_fold_addr_expr (to);
|
||||
}
|
||||
|
||||
/* When emulating tls, we use a control structure for use by the runtime.
|
||||
Create and return this structure. */
|
||||
|
||||
tree
|
||||
emutls_decl (tree decl)
|
||||
{
|
||||
tree name, to;
|
||||
struct tree_map *h, in;
|
||||
void **loc;
|
||||
|
||||
if (targetm.have_tls || decl == NULL || decl == error_mark_node
|
||||
|| TREE_CODE (decl) != VAR_DECL || ! DECL_THREAD_LOCAL_P (decl))
|
||||
return decl;
|
||||
|
||||
/* Look up the object in the hash; return the control structure if
|
||||
it has already been created. */
|
||||
if (! emutls_htab)
|
||||
emutls_htab = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0);
|
||||
|
||||
name = DECL_ASSEMBLER_NAME (decl);
|
||||
|
||||
/* Note that we use the hash of the decl's name, rather than a hash
|
||||
of the decl's pointer. In emutls_finish we iterate through the
|
||||
hash table, and we want this traversal to be predictable. */
|
||||
in.hash = htab_hash_string (IDENTIFIER_POINTER (name));
|
||||
in.from = decl;
|
||||
loc = htab_find_slot_with_hash (emutls_htab, &in, in.hash, INSERT);
|
||||
h = *loc;
|
||||
if (h != NULL)
|
||||
to = h->to;
|
||||
else
|
||||
{
|
||||
to = build_decl (VAR_DECL, get_emutls_object_name (name),
|
||||
get_emutls_object_type ());
|
||||
|
||||
h = ggc_alloc (sizeof (struct tree_map));
|
||||
h->hash = in.hash;
|
||||
h->from = decl;
|
||||
h->to = to;
|
||||
*(struct tree_map **) loc = h;
|
||||
|
||||
DECL_ARTIFICIAL (to) = 1;
|
||||
DECL_IGNORED_P (to) = 1;
|
||||
TREE_READONLY (to) = 0;
|
||||
|
||||
SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
|
||||
if (DECL_ONE_ONLY (decl))
|
||||
make_decl_one_only (to);
|
||||
DECL_CONTEXT (to) = DECL_CONTEXT (decl);
|
||||
}
|
||||
|
||||
/* Note that these fields may need to be updated from time to time from
|
||||
the original decl. Consider:
|
||||
extern __thread int i;
|
||||
int foo() { return i; }
|
||||
__thread int i = 1;
|
||||
in which I goes from external to locally defined and initialized. */
|
||||
|
||||
TREE_STATIC (to) = TREE_STATIC (decl);
|
||||
TREE_USED (to) = TREE_USED (decl);
|
||||
TREE_PUBLIC (to) = TREE_PUBLIC (decl);
|
||||
DECL_EXTERNAL (to) = DECL_EXTERNAL (decl);
|
||||
DECL_COMMON (to) = DECL_COMMON (decl);
|
||||
DECL_WEAK (to) = DECL_WEAK (decl);
|
||||
DECL_VISIBILITY (to) = DECL_VISIBILITY (decl);
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
static int
|
||||
emutls_common_1 (void **loc, void *xstmts)
|
||||
{
|
||||
struct tree_map *h = *(struct tree_map **) loc;
|
||||
tree args, x, *pstmts = (tree *) xstmts;
|
||||
tree word_type_node;
|
||||
|
||||
if (!DECL_COMMON (h->from))
|
||||
return 1;
|
||||
|
||||
word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
|
||||
|
||||
x = get_emutls_init_templ_addr (h->from);
|
||||
args = tree_cons (NULL, x, NULL);
|
||||
x = build_int_cst (word_type_node, DECL_ALIGN_UNIT (h->from));
|
||||
args = tree_cons (NULL, x, args);
|
||||
x = fold_convert (word_type_node, DECL_SIZE_UNIT (h->from));
|
||||
args = tree_cons (NULL, x, args);
|
||||
x = build_fold_addr_expr (h->to);
|
||||
args = tree_cons (NULL, x, args);
|
||||
|
||||
x = built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON];
|
||||
x = build_function_call_expr (x, args);
|
||||
|
||||
append_to_statement_list (x, pstmts);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
emutls_finish (void)
|
||||
{
|
||||
tree body = NULL_TREE;
|
||||
|
||||
if (emutls_htab == NULL)
|
||||
return;
|
||||
|
||||
htab_traverse_noresize (emutls_htab, emutls_common_1, &body);
|
||||
if (body == NULL_TREE)
|
||||
return;
|
||||
|
||||
cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
|
||||
}
|
||||
|
||||
/* Helper routines for maintaining section_htab. */
|
||||
|
||||
static int
|
||||
|
@ -1964,50 +1733,6 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
|
|||
rtx decl_rtl, symbol;
|
||||
section *sect;
|
||||
|
||||
if (! targetm.have_tls
|
||||
&& TREE_CODE (decl) == VAR_DECL
|
||||
&& DECL_THREAD_LOCAL_P (decl))
|
||||
{
|
||||
tree to = emutls_decl (decl);
|
||||
|
||||
/* If this variable is defined locally, then we need to initialize the
|
||||
control structure with size and alignment information. We do this
|
||||
at the last moment because tentative definitions can take a locally
|
||||
defined but uninitialized variable and initialize it later, which
|
||||
would result in incorrect contents. */
|
||||
if (! DECL_EXTERNAL (to) && ! DECL_COMMON (to))
|
||||
{
|
||||
VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 4);
|
||||
constructor_elt *elt;
|
||||
tree type = TREE_TYPE (to);
|
||||
tree field = TYPE_FIELDS (type);
|
||||
|
||||
elt = VEC_quick_push (constructor_elt, v, NULL);
|
||||
elt->index = field;
|
||||
elt->value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl));
|
||||
|
||||
elt = VEC_quick_push (constructor_elt, v, NULL);
|
||||
field = TREE_CHAIN (field);
|
||||
elt->index = field;
|
||||
elt->value = build_int_cst (TREE_TYPE (field),
|
||||
DECL_ALIGN_UNIT (decl));
|
||||
|
||||
elt = VEC_quick_push (constructor_elt, v, NULL);
|
||||
field = TREE_CHAIN (field);
|
||||
elt->index = field;
|
||||
elt->value = null_pointer_node;
|
||||
|
||||
elt = VEC_quick_push (constructor_elt, v, NULL);
|
||||
field = TREE_CHAIN (field);
|
||||
elt->index = field;
|
||||
elt->value = get_emutls_init_templ_addr (decl);
|
||||
|
||||
DECL_INITIAL (to) = build_constructor (type, v);
|
||||
}
|
||||
|
||||
decl = to;
|
||||
}
|
||||
|
||||
if (lang_hooks.decls.prepare_assemble_variable)
|
||||
lang_hooks.decls.prepare_assemble_variable (decl);
|
||||
|
||||
|
@ -5135,14 +4860,6 @@ do_assemble_alias (tree decl, tree target)
|
|||
{
|
||||
ultimate_transparent_alias_target (&target);
|
||||
|
||||
if (!targetm.have_tls
|
||||
&& TREE_CODE (decl) == VAR_DECL
|
||||
&& DECL_THREAD_LOCAL_P (decl))
|
||||
{
|
||||
decl = emutls_decl (decl);
|
||||
target = get_emutls_object_name (target);
|
||||
}
|
||||
|
||||
if (!TREE_SYMBOL_REFERENCED (target))
|
||||
weakref_targets = tree_cons (decl, target, weakref_targets);
|
||||
|
||||
|
@ -5160,14 +4877,6 @@ do_assemble_alias (tree decl, tree target)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!targetm.have_tls
|
||||
&& TREE_CODE (decl) == VAR_DECL
|
||||
&& DECL_THREAD_LOCAL_P (decl))
|
||||
{
|
||||
decl = emutls_decl (decl);
|
||||
target = get_emutls_object_name (target);
|
||||
}
|
||||
|
||||
#ifdef ASM_OUTPUT_DEF
|
||||
/* Make name accessible from other files, if appropriate. */
|
||||
|
||||
|
@ -6050,8 +5759,7 @@ default_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
|
|||
flags |= SYMBOL_FLAG_FUNCTION;
|
||||
if (targetm.binds_local_p (decl))
|
||||
flags |= SYMBOL_FLAG_LOCAL;
|
||||
if (targetm.have_tls && TREE_CODE (decl) == VAR_DECL
|
||||
&& DECL_THREAD_LOCAL_P (decl))
|
||||
if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
|
||||
flags |= DECL_TLS_MODEL (decl) << SYMBOL_FLAG_TLS_SHIFT;
|
||||
else if (targetm.in_small_data_p (decl))
|
||||
flags |= SYMBOL_FLAG_SMALL;
|
||||
|
|
Loading…
Add table
Reference in a new issue