[LLVMbugs] [Bug 19989] Change introduced in r207451 broke thread_local on Darwin

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Wed Jun 11 01:13:53 PDT 2014


M.E. O'Neill <oneill+llvmbugs at cs.hmc.edu> changed:

           What    |Removed                     |Added
             Status|RESOLVED                    |REOPENED
         Resolution|FIXED                       |---

--- Comment #8 from M.E. O'Neill <oneill+llvmbugs at cs.hmc.edu> ---
(In reply to comment #7)
> Fixed in r210632.

It doesn't quite produce the same output that earlier versions made, namely
before we had:

darwin% ~/llvm.199067/bin/clang++ -std=c++11 -stdlib=libc++ -c defn.cpp 
darwin% nm -m defn.o
0000000000000048 (__TEXT,__eh_frame) non-external EH_frame0
0000000000000000 (__TEXT,__text) private external __ZTW9perThread
0000000000000060 (__TEXT,__eh_frame) private external __ZTW9perThread.eh
                 (undefined) external __tlv_bootstrap
000000000000000f (__DATA,__thread_vars) non-external _perThread
0000000000000088 (__DATA,__thread_bss) non-external _perThread$tlv$init

and now we have

darwin% ~/llvm.210637/bin/clang++ -std=c++11 -stdlib=libc++ -c defn.cpp
darwin% nm -m defn.o
0000000000000048 (__TEXT,__eh_frame) non-external EH_frame0
0000000000000000 (__TEXT,__textcoal_nt) weak private external __ZTW9perThread
0000000000000060 (__TEXT,__eh_frame) weak private external __ZTW9perThread.eh
                 (undefined) external __tlv_bootstrap
000000000000000f (__DATA,__thread_vars) non-external _perThread
0000000000000088 (__DATA,__thread_bss) non-external _perThread$tlv$init

Thus, in the original __ZTW9perThread was not weak.  Presumably the idea was
that we know this is the definition of the variable and it can only appear
here.  (It might have to be weak if it were a template instantiation.)

Pretty much regardless of this flaw, thread_local still seems to be broken, and
perhaps has always been broken even since r180941.   If we combine a
translation unit that declares a thread_local variable with one that uses it,
the end result doesn't link! For example, given defn.cpp as above and use.cpp

extern thread_local int perThread;

int main()
    return perThread;

darwin% ~/llvm.210637/bin/clang++ -std=c++11 -stdlib=libc++ -c use.cpp
darwin% nm -m use.o
0000000000000090 (__TEXT,__eh_frame) non-external EH_frame0
                 (undefined) weak external __ZTH9perThread
0000000000000020 (__TEXT,__textcoal_nt) weak private external __ZTW9perThread
00000000000000d0 (__TEXT,__eh_frame) weak private external __ZTW9perThread.eh
0000000000000000 (__TEXT,__text) external _main
00000000000000a8 (__TEXT,__eh_frame) external _main.eh
                 (undefined) external _perThread
darwin% ~/llvm.210637/bin/clang++ -std=c++11 -stdlib=libc++ -o prog defn.o
Undefined symbols for architecture x86_64:
  "__ZTH9perThread", referenced from:
      __ZTW9perThread in use.o
  "_perThread", referenced from:
      __ZTW9perThread in use.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I see the same linker error with r182858 on the 3.3 branch, which is the oldest
clang version for which I still have an executable.

One part problem is that compiling use.cpp, it outputs a duplicate copy of the
thread-wrapper function __ZTW9perThread even though that was already output,
and that access function wants access to _perThread, which is non-external.

Interestingly, the thread-wrapper generated for use.o is also more complicated,
and calls a weakly-referenced function __ZTH9perThread (if it's non-null). 
This function is the thread-local init function -- presumably in the case of
the definition, it knew that no such function was required.

If instead it had relied on the code outputting the backing store for
_perThread to output the wrapper function and not tried to make its own copy,
it would have been fine.  Thus, in this case, it would have been fine to have
just said. 

    .section    __TEXT,__textcoal_nt,coalesced,pure_instructions
    .private_extern    __ZTW9perThread
    .globl    __ZTW9perThread
    .weak_reference    __ZTW9perThread

then it would have linked fine.

There are also issues with templates; trying to hide the backing store
interferes with coalescing resulting in duplicate copies of the storage and the
initialization function.  (It also has the same problem we saw earlier with
emitting a broken wrapper for translation units where the thread-local variable
is declared but not defined; again I think it should just not be doing that.)

What I find strange in all this is that __thread gets all of these things right
and works.  While it's true that the rules for thread_local are a bit more
complex because it allows dynamic initialization, it's not _that_ much

You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20140611/30be4a84/attachment.html>

More information about the llvm-bugs mailing list