This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Support TLS common symbols
- From: Ian Lance Taylor <iant at google dot com>
- To: binutils at sourceware dot org
- Date: Thu, 17 Apr 2008 00:12:29 -0700
- Subject: Support TLS common symbols
Looking at the failures from gcc's libgomp testsuite showed me that
gold doesn't support TLS common symbols. As far as I can tell, the
only way to get such a symbol is to use an OpenMP directive. This
patch adds support for TLS common symbols, with a test case.
(With this patch, the whole libgomp testsuite passes with gold.)
Ian
* common.cc (Symbol_table::allocate_commons): Remove options
parameter. Change caller.
(Symbol_table::do_allocate_commons): Remove options parameter.
Change caller. Just call do_allocate_commons_list twice.
(Symbol_table::do_allocate_commons_list): New function, broken out
of do_allocate_commons.
* common.h (class Allocate_commons_task): Remove options_ field.
Update constructor.
* symtab.cc (Symbol_table::Symbol_table): Initialize
tls_commons_.
(Symbol_table::add_from_object): Put TLS common symbols on
tls_commons_ list.
(Symbol_table::sized_finalize_symbol): Handle STT_TLS symbols
which are IN_OUTPUT_DATA.
* symtab.h (class Symbol_table): Add tls_commons_ field. Update
allocate_commons and do_allocate_commons declarations. Declare
do_allocate_commons_list.
* gold.cc (queue_middle_tasks): Update creation of
Allocate_commons_task to not pass options.
* testsuite/Makefile.am (INCLUDES): Add -I.. .
(TLS_TEST_C_FLAGS): New variable.
(tls_test_c_pic.o): New target.
(tls_test_shared.so): Link in tls_test_c_pic.o.
(tls_test_c_pic_ie.o): New target.
(tls_test_ie_shared.so): Link in tls_test_c_pic_ie.o.
(tls_test_DEPENDENCIES, tls_test_LDADD): Add tls_test_c.o.
(tls_test_c.o): New target.
(tls_pic_test_DEPENDENCIES): Add tls_test_c_pic.o.
(tls_pic_test_LDADD): Likewise.
(tls_shared_gd_to_ie_test_DEPENDENCIES): Add tls_test_c_pic.o.
(tls_shared_gd_to_ie_test_LDADD): Likewise.
(tls_test_c_gnu2.o): New target.
(tls_shared_gnu2_gd_to_ie_test_DEPENDENCIES): Add
tls_test_c_gnu2.o.
(tls_shared_gnu2_gd_to_ie_test_LDADD): Likewise.
(tls_test_gnu2_shared.so): Link in tls_test_c_gnu2.o.
(tls_test_shared_nonpic.so): Link in tls_test_c.o.
* testsuite/tls_test.cc: Include "config.h".
(t_last): Call t11_last.
* testsuite/tls_test.h (t11, t11_last): Declare.
* testsuite/tls_test_c.c: New file.
* testsuite/tls_test_main.cc (thread_routine): Call t11.
* configure.ac: Check for OpenMP support.
* configure, config.in, Makefile.in: Rebuild.
* testsuite/Makefile.in: Rebuild.
Index: common.cc
===================================================================
RCS file: /cvs/src/src/gold/common.cc,v
retrieving revision 1.15
diff -u -p -r1.15 common.cc
--- common.cc 27 Mar 2008 19:57:41 -0000 1.15
+++ common.cc 17 Apr 2008 07:09:06 -0000
@@ -60,7 +60,7 @@ Allocate_commons_task::locks(Task_locker
void
Allocate_commons_task::run(Workqueue*)
{
- this->symtab_->allocate_commons(this->options_, this->layout_);
+ this->symtab_->allocate_commons(this->layout_);
}
// This class is used to sort the common symbol by size. We put the
@@ -117,12 +117,12 @@ Sort_commons<size>::operator()(const Sym
// Allocate the common symbols.
void
-Symbol_table::allocate_commons(const General_options& options, Layout* layout)
+Symbol_table::allocate_commons(Layout* layout)
{
if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
- this->do_allocate_commons<32>(options, layout);
+ this->do_allocate_commons<32>(layout);
#else
gold_unreachable();
#endif
@@ -130,7 +130,7 @@ Symbol_table::allocate_commons(const Gen
else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
- this->do_allocate_commons<64>(options, layout);
+ this->do_allocate_commons<64>(layout);
#else
gold_unreachable();
#endif
@@ -143,8 +143,19 @@ Symbol_table::allocate_commons(const Gen
template<int size>
void
-Symbol_table::do_allocate_commons(const General_options&,
- Layout* layout)
+Symbol_table::do_allocate_commons(Layout* layout)
+{
+ this->do_allocate_commons_list<size>(layout, false, &this->commons_);
+ this->do_allocate_commons_list<size>(layout, true, &this->tls_commons_);
+}
+
+// Allocate the common symbols in a list. IS_TLS indicates whether
+// these are TLS common symbols.
+
+template<int size>
+void
+Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls,
+ Commons_type* commons)
{
typedef typename Sized_symbol<size>::Value_type Value_type;
typedef typename Sized_symbol<size>::Size_type Size_type;
@@ -154,8 +165,8 @@ Symbol_table::do_allocate_commons(const
// forwarder. First remove all non-common symbols.
bool any = false;
uint64_t addralign = 0;
- for (Commons_type::iterator p = this->commons_.begin();
- p != this->commons_.end();
+ for (Commons_type::iterator p = commons->begin();
+ p != commons->end();
++p)
{
Symbol* sym = *p;
@@ -179,22 +190,27 @@ Symbol_table::do_allocate_commons(const
// Sort the common symbols by size, so that they pack better into
// memory.
- std::sort(this->commons_.begin(), this->commons_.end(),
+ std::sort(commons->begin(), commons->end(),
Sort_commons<size>(this));
- // Place them in a newly allocated .bss section.
+ // Place them in a newly allocated BSS section.
Output_data_space *poc = new Output_data_space(addralign);
- layout->add_output_section_data(".bss", elfcpp::SHT_NOBITS,
- elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC,
- poc);
+ const char* name = ".bss";
+ elfcpp::Elf_Xword flags = elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC;
+ if (is_tls)
+ {
+ name = ".tbss";
+ flags |= elfcpp::SHF_TLS;
+ }
+ layout->add_output_section_data(name, elfcpp::SHT_NOBITS, flags, poc);
// Allocate them all.
off_t off = 0;
- for (Commons_type::iterator p = this->commons_.begin();
- p != this->commons_.end();
+ for (Commons_type::iterator p = commons->begin();
+ p != commons->end();
++p)
{
Symbol* sym = *p;
@@ -208,7 +224,7 @@ Symbol_table::do_allocate_commons(const
poc->set_current_data_size(off);
- this->commons_.clear();
+ commons->clear();
}
} // End namespace gold.
Index: common.h
===================================================================
RCS file: /cvs/src/src/gold/common.h,v
retrieving revision 1.5
diff -u -p -r1.5 common.h
--- common.h 13 Mar 2008 21:04:21 -0000 1.5
+++ common.h 17 Apr 2008 07:09:06 -0000
@@ -28,7 +28,6 @@
namespace gold
{
-class General_options;
class Symbol_table;
// This task is used to allocate the common symbols.
@@ -36,11 +35,10 @@ class Symbol_table;
class Allocate_commons_task : public Task
{
public:
- Allocate_commons_task(const General_options& options, Symbol_table* symtab,
- Layout* layout, Task_token* symtab_lock,
- Task_token* blocker)
- : options_(options), symtab_(symtab), layout_(layout),
- symtab_lock_(symtab_lock), blocker_(blocker)
+ Allocate_commons_task(Symbol_table* symtab, Layout* layout,
+ Task_token* symtab_lock, Task_token* blocker)
+ : symtab_(symtab), layout_(layout), symtab_lock_(symtab_lock),
+ blocker_(blocker)
{ }
// The standard Task methods.
@@ -59,7 +57,6 @@ class Allocate_commons_task : public Tas
{ return "Allocate_commons_task"; }
private:
- const General_options& options_;
Symbol_table* symtab_;
Layout* layout_;
Task_token* symtab_lock_;
Index: configure.ac
===================================================================
RCS file: /cvs/src/src/gold/configure.ac,v
retrieving revision 1.31
diff -u -p -r1.31 configure.ac
--- configure.ac 17 Apr 2008 05:52:32 -0000 1.31
+++ configure.ac 17 Apr 2008 07:09:07 -0000
@@ -221,6 +221,22 @@ error
AM_CONDITIONAL(STATIC_TLS, test "$gold_cv_lib_glibc24" = "yes")
+dnl Test for #pragma omp threadprivate
+AC_CACHE_CHECK([for omp support], [gold_cv_c_threadprivate],
+[save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fopenmp"
+AC_COMPILE_IFELSE([
+#include <omp.h>
+int i;
+#pragma omp threadprivate (i)
+], [gold_cv_c_threadprivate=yes], [gold_cv_c_threadprivate=no])
+CFLAGS="$save_CFLAGS"])
+if test "$gold_cv_c_threadprivate" = "yes"; then
+ AC_DEFINE(HAVE_OMP_SUPPORT, 1,
+ [Define if compiler supports #pragma omp threadprivate])
+fi
+AM_CONDITIONAL(OMP_SUPPORT, test "$gold_cv_c_threadprivate" = "yes")
+
dnl Test for the -ftls-dialect=gnu2 option.
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -mtls-dialect=gnu2"
Index: gold.cc
===================================================================
RCS file: /cvs/src/src/gold/gold.cc,v
retrieving revision 1.52
diff -u -p -r1.52 gold.cc
--- gold.cc 15 Apr 2008 04:06:40 -0000 1.52
+++ gold.cc 17 Apr 2008 07:09:07 -0000
@@ -260,8 +260,8 @@ queue_middle_tasks(const General_options
if (parameters->options().define_common())
{
blocker->add_blocker();
- workqueue->queue(new Allocate_commons_task(options, symtab, layout,
- symtab_lock, blocker));
+ workqueue->queue(new Allocate_commons_task(symtab, layout, symtab_lock,
+ blocker));
}
// When all those tasks are complete, we can start laying out the
Index: symtab.cc
===================================================================
RCS file: /cvs/src/src/gold/symtab.cc,v
retrieving revision 1.91
diff -u -p -r1.91 symtab.cc
--- symtab.cc 17 Apr 2008 02:00:54 -0000 1.91
+++ symtab.cc 17 Apr 2008 07:09:07 -0000
@@ -360,7 +360,7 @@ Symbol::set_output_section(Output_sectio
Symbol_table::Symbol_table(unsigned int count,
const Version_script_info& version_script)
: saw_undefined_(0), offset_(0), table_(count), namepool_(),
- forwarders_(), commons_(), forced_locals_(), warnings_(),
+ forwarders_(), commons_(), tls_commons_(), forced_locals_(), warnings_(),
version_script_(version_script)
{
namepool_.reserve(count);
@@ -715,7 +715,12 @@ Symbol_table::add_from_object(Object* ob
// Keep track of common symbols, to speed up common symbol
// allocation.
if (!was_common && ret->is_common())
- this->commons_.push_back(ret);
+ {
+ if (ret->type() != elfcpp::STT_TLS)
+ this->commons_.push_back(ret);
+ else
+ this->tls_commons_.push_back(ret);
+ }
if (def)
ret->set_is_default();
@@ -1830,7 +1835,15 @@ Symbol_table::sized_finalize_symbol(Symb
case Symbol::IN_OUTPUT_DATA:
{
Output_data* od = sym->output_data();
- value = sym->value() + od->address();
+ value = sym->value();
+ if (sym->type() != elfcpp::STT_TLS)
+ value += od->address();
+ else
+ {
+ Output_section* os = od->output_section();
+ gold_assert(os != NULL);
+ value += os->tls_offset() + (od->address() - os->address());
+ }
if (sym->offset_is_from_end())
value += od->data_size();
}
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gold/symtab.h,v
retrieving revision 1.73
diff -u -p -r1.73 symtab.h
--- symtab.h 17 Apr 2008 00:14:36 -0000 1.73
+++ symtab.h 17 Apr 2008 07:09:07 -0000
@@ -1104,7 +1104,7 @@ class Symbol_table
// Allocate the common symbols
void
- allocate_commons(const General_options&, Layout*);
+ allocate_commons(Layout*);
// Add a warning for symbol NAME in object OBJ. WARNING is the text
// of the warning.
@@ -1180,6 +1180,9 @@ class Symbol_table
Symbol_table(const Symbol_table&);
Symbol_table& operator=(const Symbol_table&);
+ // The type of the list of common symbols.
+ typedef std::vector<Symbol*> Commons_type;
+
// Make FROM a forwarder symbol to TO.
void
make_forwarder(Symbol* from, Symbol* to);
@@ -1282,7 +1285,12 @@ class Symbol_table
// Allocate the common symbols, sized version.
template<int size>
void
- do_allocate_commons(const General_options&, Layout*);
+ do_allocate_commons(Layout*);
+
+ // Allocate the common symbols from one list.
+ template<int size>
+ void
+ do_allocate_commons_list(Layout*, bool is_tls, Commons_type*);
// Implement detect_odr_violations.
template<int size, bool big_endian>
@@ -1347,9 +1355,6 @@ class Symbol_table
typedef Unordered_map<Symbol_table_key, Symbol*, Symbol_table_hash,
Symbol_table_eq> Symbol_table_type;
- // The type of the list of common symbols.
- typedef std::vector<Symbol*> Commons_type;
-
// The type of the list of symbols which have been forced local.
typedef std::vector<Symbol*> Forced_locals;
@@ -1416,6 +1421,9 @@ class Symbol_table
// symbol is no longer a common symbol. It may also have become a
// forwarder.
Commons_type commons_;
+ // This is like the commons_ field, except that it holds TLS common
+ // symbols.
+ Commons_type tls_commons_;
// A list of symbols which have been forced to be local. We don't
// expect there to be very many of them, so we keep a list of them
// rather than walking the whole table to find them.
Index: testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.63
diff -u -p -r1.63 Makefile.am
--- testsuite/Makefile.am 17 Apr 2008 00:14:36 -0000 1.63
+++ testsuite/Makefile.am 17 Apr 2008 07:09:07 -0000
@@ -13,7 +13,7 @@ AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CFL
INCLUDES = \
-I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../include \
- -I$(srcdir)/../../elfcpp \
+ -I$(srcdir)/../../elfcpp -I.. \
-DLOCALEDIR="\"$(datadir)/locale\"" \
@INCINTL@
@@ -26,6 +26,10 @@ if THREADS
THREADSLIB = -lpthread
endif
+if OMP_SUPPORT
+TLS_TEST_C_CFLAGS = -fopenmp
+endif
+
# 'make clean' is good about deleting some intermediate files (such as
# .o's), but not all of them (such as .so's and .err files). We
# improve on that here. automake-1.9 info docs say "mostlyclean" is
@@ -433,8 +437,10 @@ tls_test_pic.o: tls_test.cc
$(CXXCOMPILE) -c -fpic -o $@ $<
tls_test_file2_pic.o: tls_test_file2.cc
$(CXXCOMPILE) -c -fpic -o $@ $<
-tls_test_shared.so: tls_test_pic.o tls_test_file2_pic.o gcctestdir/ld
- $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic.o tls_test_file2_pic.o
+tls_test_c_pic.o: tls_test_c.c
+ $(COMPILE) -c -fpic $(TLS_TEST_C_CFLAGS) -o $@ $<
+tls_test_shared.so: tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o
tls_test_shared2.so: tls_test_file2_pic.o gcctestdir/ld
$(CXXLINK) -Bgcctestdir/ -shared tls_test_file2_pic.o
@@ -442,18 +448,24 @@ tls_test_pic_ie.o: tls_test.cc
$(CXXCOMPILE) -c -fpic -ftls-model=initial-exec -o $@ $<
tls_test_file2_pic_ie.o: tls_test_file2.cc
$(CXXCOMPILE) -c -fpic -ftls-model=initial-exec -o $@ $<
-tls_test_ie_shared.so: tls_test_pic_ie.o tls_test_file2_pic_ie.o gcctestdir/ld
- $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic_ie.o tls_test_file2_pic_ie.o
+tls_test_c_pic_ie.o: tls_test_c.c
+ $(COMPILE) -c -fpic -ftls-model=initial-exec $(TLS_TEST_C_CFLAGS) -o $@ $<
+tls_test_ie_shared.so: tls_test_pic_ie.o tls_test_file2_pic_ie.o tls_test_c_pic_ie.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic_ie.o tls_test_file2_pic_ie.o tls_test_c_pic_ie.o
tls_test_SOURCES = tls_test.cc tls_test_file2.cc tls_test_main.cc tls_test.h
-tls_test_DEPENDENCIES = gcctestdir/ld
+tls_test_DEPENDENCIES = gcctestdir/ld tls_test_c.o
tls_test_LDFLAGS = -Bgcctestdir/
-tls_test_LDADD = -lpthread
+tls_test_LDADD = tls_test_c.o -lpthread
+tls_test_c.o: tls_test_c.c
+ $(COMPILE) -c $(TLS_TEST_C_CFLAGS) -o $@ $<
tls_pic_test_SOURCES = tls_test_main.cc
-tls_pic_test_DEPENDENCIES = gcctestdir/ld tls_test_pic.o tls_test_file2_pic.o
+tls_pic_test_DEPENDENCIES = gcctestdir/ld tls_test_pic.o tls_test_file2_pic.o \
+ tls_test_c_pic.o
tls_pic_test_LDFLAGS = -Bgcctestdir/
-tls_pic_test_LDADD = tls_test_pic.o tls_test_file2_pic.o -lpthread
+tls_pic_test_LDADD = tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o \
+ -lpthread
tls_shared_test_SOURCES = tls_test_main.cc
tls_shared_test_DEPENDENCIES = gcctestdir/ld tls_test_shared.so
@@ -466,9 +478,11 @@ tls_shared_ie_test_LDFLAGS = -Bgcctestdi
tls_shared_ie_test_LDADD = tls_test_ie_shared.so -lpthread
tls_shared_gd_to_ie_test_SOURCES = tls_test_main.cc
-tls_shared_gd_to_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_pic.o tls_test_shared2.so
+tls_shared_gd_to_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_pic.o \
+ tls_test_c_pic.o tls_test_shared2.so
tls_shared_gd_to_ie_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
-tls_shared_gd_to_ie_test_LDADD = tls_test_pic.o tls_test_shared2.so -lpthread
+tls_shared_gd_to_ie_test_LDADD = tls_test_pic.o tls_test_c_pic.o \
+ tls_test_shared2.so -lpthread
if TLS_GNU2_DIALECT
@@ -478,20 +492,24 @@ tls_test_gnu2.o: tls_test.cc
$(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $<
tls_test_file2_gnu2.o: tls_test_file2.cc
$(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $<
+tls_test_c_gnu2.o: tls_test_c.c
+ $(COMPILE) -c -fpic -mtls-dialect=gnu2 $(TLS_TEST_C_CFLAGS) -o $@ $<
tls_test_gnu2_shared2.so: tls_test_file2_gnu2.o gcctestdir/ld
$(CXXLINK) -Bgcctestdir/ -shared tls_test_file2_gnu2.o
tls_shared_gnu2_gd_to_ie_test_SOURCES = tls_test_main.cc
-tls_shared_gnu2_gd_to_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_gnu2.o tls_test_gnu2_shared2.so
+tls_shared_gnu2_gd_to_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_gnu2.o \
+ tls_test_c_gnu2.o tls_test_gnu2_shared2.so
tls_shared_gnu2_gd_to_ie_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
-tls_shared_gnu2_gd_to_ie_test_LDADD = tls_test_gnu2.o tls_test_gnu2_shared2.so -lpthread
+tls_shared_gnu2_gd_to_ie_test_LDADD = tls_test_gnu2.o tls_test_c_gnu2.o \
+ tls_test_gnu2_shared2.so -lpthread
if TLS_DESCRIPTORS
check_PROGRAMS += tls_shared_gnu2_test
-tls_test_gnu2_shared.so: tls_test_gnu2.o tls_test_file2_gnu2.o gcctestdir/ld
- $(CXXLINK) -Bgcctestdir/ -shared tls_test_gnu2.o tls_test_file2_gnu2.o
+tls_test_gnu2_shared.so: tls_test_gnu2.o tls_test_file2_gnu2.o tls_test_c_gnu2.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -shared tls_test_gnu2.o tls_test_file2_gnu2.o tls_test_c_gnu2.o
tls_shared_gnu2_test_SOURCES = tls_test_main.cc
tls_shared_gnu2_test_DEPENDENCIES = gcctestdir/ld tls_test_gnu2_shared.so
@@ -519,8 +537,8 @@ endif
if FN_PTRS_IN_SO_WITHOUT_PIC
check_PROGRAMS += tls_shared_nonpic_test
-tls_test_shared_nonpic.so: tls_test.o tls_test_file2.o gcctestdir/ld
- $(CXXLINK) -Bgcctestdir/ -shared tls_test.o tls_test_file2.o
+tls_test_shared_nonpic.so: tls_test.o tls_test_file2.o tls_test_c.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -shared tls_test.o tls_test_file2.o tls_test_c.o
tls_shared_nonpic_test_SOURCES = tls_test_main.cc
tls_shared_nonpic_test_DEPENDENCIES = gcctestdir/ld tls_test_shared_nonpic.so
Index: testsuite/tls_test.cc
===================================================================
RCS file: /cvs/src/src/gold/testsuite/tls_test.cc,v
retrieving revision 1.5
diff -u -p -r1.5 tls_test.cc
--- testsuite/tls_test.cc 19 Mar 2008 21:41:38 -0000 1.5
+++ testsuite/tls_test.cc 17 Apr 2008 07:09:08 -0000
@@ -45,6 +45,7 @@
#include <cstdio>
+#include "config.h"
#include "tls_test.h"
#define CHECK_EQ_OR_RETURN(var, expected) \
@@ -197,5 +198,7 @@ t_last()
CHECK_EQ_OR_RETURN(o1, -10);
CHECK_EQ_OR_RETURN(o2, -20);
CHECK_EQ_OR_RETURN(o3, -30);
+ int check = t11_last();
+ CHECK_EQ_OR_RETURN(check, 1);
return true;
}
Index: testsuite/tls_test.h
===================================================================
RCS file: /cvs/src/src/gold/testsuite/tls_test.h,v
retrieving revision 1.4
diff -u -p -r1.4 tls_test.h
--- testsuite/tls_test.h 13 Mar 2008 21:04:21 -0000 1.4
+++ testsuite/tls_test.h 17 Apr 2008 07:09:08 -0000
@@ -43,6 +43,9 @@ extern int* f10a();
extern void f10b(int*);
extern bool t10();
+extern "C" int t11();
+extern "C" int t11_last();
+
extern bool t_last();
// These variables are defined in tls_test_file2.cc
Index: testsuite/tls_test_c.c
===================================================================
RCS file: testsuite/tls_test_c.c
diff -N testsuite/tls_test_c.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/tls_test_c.c 17 Apr 2008 07:09:08 -0000
@@ -0,0 +1,62 @@
+/* tls_test_c.c -- test TLS common symbol
+
+ Copyright 2008 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <iant@google.com>
+
+ This file is part of gold.
+
+ This program 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 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* The only way I know to get gcc to generate a TLS common symbol is
+ to use a C file and an OpenMP directive. */
+
+#include <stdio.h>
+#include "config.h"
+
+#define CHECK_EQ_OR_RETURN(var, expected) \
+ do \
+ { \
+ if ((var) != (expected)) \
+ { \
+ printf(#var ": expected %d, found %d\n", expected, var); \
+ return 0; \
+ } \
+ } \
+ while (0)
+
+#ifdef HAVE_OMP_SUPPORT
+int v7;
+#pragma omp threadprivate (v7)
+#endif
+
+int
+t11()
+{
+#ifdef HAVE_OMP_SUPPORT
+ CHECK_EQ_OR_RETURN(v7, 0);
+ v7 = 70;
+#endif
+ return 1;
+}
+
+int
+t11_last()
+{
+#ifdef HAVE_OMP_SUPPORT
+ CHECK_EQ_OR_RETURN(v7, 70);
+#endif
+ return 1;
+}
Index: testsuite/tls_test_main.cc
===================================================================
RCS file: /cvs/src/src/gold/testsuite/tls_test_main.cc,v
retrieving revision 1.5
diff -u -p -r1.5 tls_test_main.cc
--- testsuite/tls_test_main.cc 13 Mar 2008 21:04:21 -0000 1.5
+++ testsuite/tls_test_main.cc 17 Apr 2008 07:09:08 -0000
@@ -99,6 +99,7 @@ thread_routine(void* arg)
check("t9", t9());
f10b(f10a());
check("t10", t10());
+ check("t11", t11() != 0);
check("t_last", t_last());
// Unlock the second mutex.