[llvm-dev] Is there some sort of "@llvm.thread_ctors."?

James Y Knight via llvm-dev llvm-dev at lists.llvm.org
Thu Jan 9 11:29:17 PST 2020

On Thu, Jan 9, 2020 at 6:47 AM Yafei Liu via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> We know that in C++, the constructor of a static member will get called
> when the program starts up. I checked the generated IR code and found this
> is implemented by defining a __cxx_global_var_init() function and marked it
> as section ".text.startup" and assign it to @llvm.global_ctors.

The last is the important part. But that's just an abstraction across the
various global constructor mechanisms provided by the underlying platforms.

> We also know that in C++, the constructor of a static thread_local member
> will *not* get called when the program starts, but the first time this
> member is used, I also checked the IR code, this is implemented by calling
> it's constructor at the usage, and then call __cxa_thread_atexit to
> register it's destructor.

This behavior is not guaranteed by C++. It would also be acceptable
according to the standard to construct the thread-locals eagerly upon
thread startup, as you want to do. However, yes, clang does always lazy
initialize them.

> Now I want to add thread_local feature to my own language, and I want my
> thread_local member acts simlar like a static member, that is,  when a new
> thread is created, the constructors of thread_local members will
> automatically get called, instead get called when used?
> I read the LLVM Language Reference Manual, but it doesn't talk much
> in Thread Local Storage Models.

No platform I know of provides such a mechanism that you (or llvm) could
hook into. If you want this, you'll need to create your own thread-startup
routine that calls your own thread-local initializers.

The most obvious way to do this when there's no shared-libraries in the mix
would be to emit the initializer-function pointers into a custom named
section, and then iterate over that section in your thread startup routine.
The linker automatically creates __start_SECTIONNAME and __stop_SECTIONNAME
symbols, so you can just iterate on the pointers between them. (At least
this works in ELF, not sure if it's the same on COFF/MachO).

If you need to also support shared libraries, then finding all constructors
across all libraries gets somewhat more complex...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200109/518802ad/attachment.html>

More information about the llvm-dev mailing list