Reland "[ORC] Track __emutls_t definitions in IRMaterializationUnit" (#207161) - #209717
Conversation
…lvm#207161) llvm#207161 was reverted in llvm#207775, relanded in llvm#208413, then reverted again in llvm#209260: the reland resolved __emutls_get_address only on Darwin (#ifdef __APPLE__ + isOSBinFormatMachO), but clang-repl forces emulated TLS on every target (JITTargetMachineBuilder), so any host that cannot resolve __emutls_get_address through process-symbol lookup hits the same failure. Arm's toolchain CI caught it on Linux/AArch64 built with -rtlib=compiler-rt (no libgcc_s), where the symbol lives only in the compiler-rt builtins static archive. The IRMaterializationUnit fix (Layer.cpp) and the test are unchanged from llvm#208413. This reland broadens the IncrementalExecutor.cpp workaround from Darwin-only to all in-process Unix hosts: force-link __emutls_get_address (gated on LLVM_ON_UNIX, excluding Emscripten and AIX/z/OS whose runtimes may not provide it) and define it as an absolute symbol in the process-symbols JITDylib regardless of target binary format. Where process-symbol lookup already resolves it (glibc/libgcc_s) the absolute definition is harmless -- an already-defined symbol shadows the generator, following the MinGW __main precedent in lli.cpp. Co-developed-with-the-help-of: Claude Code (Claude Opus 4.8, human in the loop)
|
@vgvassilev @lhames — this is the reland of #208413 (reverted in #209260 just before the 23.x cut). The Darwin-only symbol fix left the same |
|
Can we ask the bot owners who found the regression to review? |
Makes sense, @pawosm-arm, @vrukesh, this should pass through your CI now if you'd like to review |
I doubt this CI is capable of verifying an arbitrary upstream commit: things need to be pulled in from the |
vgvassilev
left a comment
There was a problem hiding this comment.
Looks reasonable to me but I’d like to wait for @lhames.
|
@lhames gentle ping — this reland has been sitting green for a couple of weeks; would appreciate a look when you get a chance. Thanks! |
|
@vgvassilev, @lhames, more than happy to massage this one if there is something that needs to be addressed, anything here look off to you guys? |
|
Let's move forward and rely on post merge feedback. |
|
This broke the build on FreeBSD where __emutls_get_address is not provided. This seems sufficient to fix the build: Whatever tool did the line wrapping of the commit message is appalling. It's basically unreadable. :( |
Sorry about that. I noticed the formatting but I thought it was only on my end. Do you mind committing that fix of yours? |
I don't have commit permissions, but I've created #217004 |
|
Approved but let’s wait for the pre-merge checks! |
@brooksdavis, I just double-checked and it was a pass of |
|
this is also breaking us in Google. We are LLVM_ON_UNIX and we don't have __emutls_get_address in our runtime. |
|
My colleague @rupprecht suggested cmake variable to guard this with. Could we have some HAS_EMUTLS or similar for this instead of current approach which forces downstream compilers to provide definition of emutls_get_address? |
That seems to be a good way forward. Do we have a PR with it upstream? |
Relands #207161 (the
IRMaterializationUnit::discardfix for duplicated__emutls_t.<var>symbols). History: #207161 merged, reverted in #207775,relanded in #208413, reverted again in #209260 (a day before the 23.x cut).
Why #208413 was reverted
clang-repl's JIT lowers
thread_localto emulated TLS on every target(
JITTargetMachineBuilderforcesEmulatedTLS), so JIT'd code alwaysreferences
__emutls_get_address. #208413 only made that symbol resolvable onDarwin (
#ifdef __APPLE__+isOSBinFormatMachO()), where it lives in thecompiler-rt builtins static archive. The same gap exists on any host that
links compiler-rt builtins instead of libgcc_s: the arm-toolchain CI hit it on
Linux/AArch64 built with
-rtlib=compiler-rt(no libgcc_s), where__emutls_get_addressis only in the static archive and process-symbol lookupcannot find it —
JIT session error: Symbols not found: [ __emutls_get_address ].(glibc bots pass because libgcc_s.so exports it.)
This reland
The
IRMaterializationUnitfix (Layer.cpp) and the test are unchanged from#208413. The
IncrementalExecutor.cppworkaround is broadened from Darwin-onlyto all in-process Unix hosts:
__emutls_get_addressunderLLVM_ON_UNIX(excluding Emscripten,AIX, and z/OS) to force-link it from whichever compiler runtime the toolchain
uses (libgcc_s or the compiler-rt builtins archive), and
target binary format.
This is target-independent: emulated-TLS lowering emits the accessor name from
shared codegen (
TargetLowering), so a single symbol covers every arch. Theprevious
isOSBinFormatMachO()guard is dropped — with emulated TLS forced on,a target-format check is vestigial and can only re-exclude the exact hosts that
fail. Where process-symbol lookup already resolves the symbol (glibc), the
absolute definition is a harmless shadow (an already-defined symbol is dropped
from generation candidates before the process-symbol generator runs), following
the MinGW
__mainprecedent inlli.cpp. In-process only — a host address ismeaningless for an out-of-process executor. The
UNSUPPORTED: target=loongarchline from #208886 is retained (LoongArch rejects emulated TLS outright).
The reference resolves from the toolchain's compiler runtime; hosts with no
guaranteed emulated-TLS runtime on the link line (MSVC, Emscripten, AIX, z/OS)
are excluded and fall back to process-symbol lookup, as before.
Alternatives considered
static-library definition generator, as
lli --extra-archivedoes) instead offorce-linking + defining the symbol. This avoids the build-time link
dependency and generalizes to other builtins, at the cost of runtime discovery
of the builtins archive path (resource dir / sysroot / cross-compiles /
libgcc-only toolchains) plus plumbing to reach the in-process JIT path. It's a
reasonable alternative and a clean follow-on; this PR takes the smaller,
target-independent route to get the discard fix relanded, and I'm happy to
switch to it if reviewers prefer.
in-process-only constraint), tracked by the TODO added next to the workaround.
Out of scope here.
Testing
Verified on Linux/x86-64: full
check-clangclean;clang/test/Interpreter/emulated-tls.cpppasses. Darwin verified by the author on aarch64.
🤖 Done with the help of Claude Code (Claude Opus 4.8, human in the loop)