Update to the latest release/23.x branch - #199
Merged
nikic merged 224 commits intoAug 21, 2026
Merged
Conversation
(cherry picked from commit 617e4f5)
…m#208356) 762b77a moved the definition of "xindex" out of the header, and in the process dropped the _LIBCPP_HAS_THREADS check. Re-add the check to maintain the status quo. The discussion on llvm#198994 indicates it's not clear whether LIBCXX_ENABLE_THREADS=OFF is actually supposed to mean single-threaded. But it clearly does in practice: atomic_support.h uses non-atomic ops when threads are disabled, and a few other APIs have explicit non-atomic fallback paths. My team ran into this trying to run libc++ tests for a RISC-V core without the "a" extension. (cherry picked from commit 3eb929b)
…ates (llvm#209693) This fixes another case of member functions where we overlooked template depths when only abbreviated template parameters are involved. This mirrors previous fix cfb2520, but I don't intend to put it in ParseTrailingRequiresClause because we might want the similar fix for e.g. noexcept expressions, so let's keep it inline for future refactor. The example comes from llvm#205557. (cherry picked from commit 3485d85)
…delete (llvm#209585) PR llvm#188372 made Clang's MSVC-ABI deleting-destructor path route global deletes through compiler-generated __global_delete / __global_array_delete wrappers instead of referencing ::operator delete directly. This lets a deleting destructor be emitted in environments (e.g. kernel mode) where no global ::operator delete exists: each wrapper defaults to a trapping __empty_global_delete fallback, and a real forwarding body that calls ::operator delete is materialized only when the program actually uses ::delete. This change refines how those wrappers and their fallbacks are emitted, fixing two problems that made the llvm#188372 mechanism fail in practice. New behavior: - The trapping fallback is now emitted as a weak GlobalAlias to __empty_global_delete rather than via an /alternatename directive. This lowers to a COFF weak-external-with-default -- exactly what MSVC emits -- so a real __global_delete defined in any TU overrides the fallback in every other TU at link time. - A ::delete expression now registers the wrapper for its resolved global operator delete directly (in EmitCXXDeleteExpr), so the strong forwarding body is emitted in that TU regardless of where the class's deleting destructor is defined. This matches MSVC, which emits the forwarder at every ::delete site. Bugs fixed: 1. Arm64EC (miscompile -> LNK2019). /alternatename only names the plain symbol, not the backend-generated "$$h" hybrid EC symbol referenced by the exit thunk, so Arm64EC images left __global_delete$exit_thunk unresolved. The weak GlobalAlias correctly produces the "$$h" symbol, exit thunk, and plain alias (verified on both x64 and Arm64EC). 2. Cross-TU ::delete (runtime crash). Previously the forwarding body was only emitted in a TU that *both* emitted a matching vector deleting destructor and contained a ::delete. A TU that only performed `::delete p` -- with the class defined elsewhere -- emitted no forwarder, so nothing overrode the weak-alias trap and the program executed a trapping __empty_global_delete at runtime (STATUS_ILLEGAL_INSTRUCTION). Registering the wrapper at the ::delete site fixes this. To share wrapper-creation logic between the deleting-destructor path and the delete-expression path, getOrCreateMSVCGlobalDeleteWrapper is promoted from a static helper in CGClass.cpp to a CodeGenModule method. Verified end-to-end: a weak alias in one TU and a strong forwarder in another resolve to the forwarder under both lld-link and MSVC link.exe, and the previously-crashing delete-only TU now runs cleanly.
Similar to llvm#209194, this was previously hitting an error with an illegal FP_ROUND_MERGE_PASSTHRU. This time we lower the fptrunc to a scalable fptrunc and let it legalize naturally. On SVE systems a f64->bf16 fptrunc will fail to legalize, but lowers successfully with sve2 with fcvtn. A store(fptrunc) -> truncstore combine was disabled too as it fails with bf16. (cherry picked from commit 50f2b94)
…g exit thunks (llvm#209581) ARM64EC vararg functions receive all types of the first four arguments in x0-x3. Because x86_64 expects floating-point arguments in FP registers, always copy x0-x3 to d0-d3 in the exit thunks, matching MSVC's behavior. (cherry picked from commit 9c6a9f5)
We found out that the new mechanism for detecting overriden functions does not support Arm Pointer Authentication (PAuth). Addressing this limitation is going to require changes to Clang. In the meantime, we switched back to the old mechanism when PAuth is enabled. (cherry picked from commit db7356d)
…t library (llvm#210311) In mingw mode, when linking against a DLL, the user can either provide a regular import library, or provide the actual DLL. When linking against an ARM64X image, add both native and EC views to the symbol table on EC targets. Also getMachine() on such images returns ARM64X, treat it as ARM64 instead. (cherry picked from commit 30f270e)
…#210347) The PR llvm#208552 has introduced a regression where brace initialization was not taken into account `auto foo{12}`. It was also breaking `dcl.type.general` p2 rules, which is also now tested. (cherry picked from commit d592aa5)
…vm#210151) ActOnUninitializedDecl dereferenced the std::optional<Token> from Lexer::findNextToken() unconditionally when diagnosing a structured binding with no initializer. Guard the optional and fall back to the declaration's location. (cherry picked from commit 0e3852f)
Add DAG pattern to recognize the optimized IR form of BLSIC: (xor (and x, -x), -1) Fixes llvm#209718 - matches the IR form produced after InstCombine optimizations Added tests for both 32-bit and 64-bit BLSIC patterns Assisted by: Claude Code, helped me understand pattern-matching/intrinsics, and some file structure. As well as how testing for LLVM works. (cherry picked from commit 466503d)
Addressing regression introduced by llvm#205844 in which a significantly slower SVE tail loop is generated. The cost model for the case where the interleave factor is larger than the VF has been adjusted to more accurately reflect the cost of the uzp instructions generated by the deinterleave tree, and the cost of legalizing the type of each subvector. (cherry picked from commit 79e05f4)
…lignment A destination alloca's alignment could have been unconditionally overwritten, letting a lower-aligned source incorrectly undo a previous alignment increase. This issue has been addressed by considering the maximum alignment between the new source target and current destination, adhering to what the existing comment already promises.
…MOVMSK signbit reduction (llvm#210281) VectorCombine may have folded: icmp_eq(vecreduce_or(splatsign(x)),0) --> icmp_sgt(vecreduce_umax(x),-1) which DAG folds to: srl(vecreduce_umax(x),bw-1). This match attempts to lower: srl(vecreduce_umax(x),bw-1) --> icmp_ne(movmsk(x),0) "any_of negative" srl(not(vecreduce_umax(x)),bw-1) --> icmp_eq(movmsk(x),0) "none_of negative" The correct fix would be to improve vecreduce_or costs to prevent VectorCombine doing this, but that change is far too big to be merged into 23.x - so I've created the narrow backend fix. Fixes llvm#209714 (cherry picked from commit 8abc269)
As in title. This adds support for using apxf in attribute target. Individual features are not supported for FMV but are supported for enabling a feature for the function Patch done with usage of Claude Code. (cherry picked from commit 1d55a81)
…210570) This was introduced as part of llvm#94977. Rather than suppressing the warning with `#pragma clang diagnostic ignored`, we use `reinterpret_cast` to avoid the implicit conversion. (cherry picked from commit 16ffd27)
) CompileUnit::getDirAndFilenameFromLineTable reads and mutates the unit's FileNames DenseMap without synchronization. During the parallel type-name assignment phase a unit's cache is touched both by its own worker and, through cross-unit type-name references (addReferencedODRDies calling addDieNameFromDeclFileAndDeclLine) by other units' workers. The concurrent find/insert/grow corrupts the map and trips the assertion: ``` Assertion failed: (TheBucket), function findBucketForInsertion, DenseMap.h ``` Guard the cache with a mutex. Store each entry in a heap-allocated pair so the StringRefs handed back to callers stay valid across a concurrent rehash. Otherwise a short (small-string-optimized) file name would move when another insertion grows the map, dangling a StringRef already returned. (cherry picked from commit 499b69c)
…llvm#209553) (cherry picked from commit 6bcdcb3)
…mpound statement (llvm#209229) <https://eel.is/c++draft/stmt.expand#nt:expansion-statement>: _expansion-statement_: template for ( _init-statement<sub>opt</sub>_ _for-range-declaration_ : _expansion-initializer_ ) _compound-statement_ (cherry picked from commit d13b862)
This will cause the TokenFactor to be split into nodes of at most SDNode::getMaxNumOperands() size. This fixes llvm#189161 but I have not added a test case as the output is in excess of 160000 lines long. (cherry picked from commit ba83659)
`Process::GetState()` calls `PolicyStack::Get().Current()` on every prompt redraw, so the previous unconditional LLDB_LOG at the read site fired on every keypress once `log enable lldb process` was on, drowning out any other process log output. Keep the dump for when it's actually wanted, but only fire it if the log is set to verbose. Signed-off-by: Med Ismail Bennani <ismail@bennani.ma> (cherry picked from commit c7a0afe)
…r array-to-pointer decay (llvm#210649) ProcessInitializer() strips implicit casts from a CXXCtorInitializer's init expression via IgnoreImplicit(), then decides whether to treat the initializer as a direct array-to-array member copy by checking Init->getType()->isArrayType(). For a pointer member initialized via array-to-pointer decay of a reference-to-array constructor parameter (e.g. `Foo(T (&arr)[N]) : ptr_(arr) {}`), IgnoreImplicit() strips the ArrayToPointerDecay cast, exposing the underlying array-typed expression, so this check misfires even though the field itself is a pointer, not an array. That branch fetches the raw region address of the whole array, bypassing the normal decay logic (which produces an ElementRegion), so the pointer member ends up holding the address of the whole array typed as the array itself, instead of an ElementRegion at index 0. Later, dereferencing and storing through that mistyped pointer routes into RegionStoreManager::bindArray() (instead of bindScalar()), which unconditionally casts its Init value to nonloc::CompoundVal, asserting in a debug build and segfaulting in a release build when Init is anything else, e.g. a nonloc::LocAsInteger produced by round-tripping a pointer through an integer type. Fix the actual bug by checking the field's type instead of the initializer expression's type. Also generalize bindArray()'s existing guard (added by llvm#178923 for issue llvm#178797) from an enumeration of specific SVal kinds to the same exhaustive `!isa<nonloc::CompoundVal>()` check already used by its siblings bindStruct() and bindVector(), so it doesn't need to be extended again every time a new SVal kind reaches this path -- this is what actually catches our case (nonloc::LocAsInteger), which the prior enumeration didn't cover. This is the same underlying bug behind llvm#147686 (fixed by llvm#153177, which its own author noted was "more of a workaround") and llvm#178797 (fixed by llvm#178923); both those fixes patched symptoms at bindArray() without addressing the ProcessInitializer() root cause. Fixing the root cause also resolves two FIXME-annotated precision gaps in clang/test/Analysis/initializer.cpp's gh147686 regression test. Fixes llvm#210183 AI tool use disclosure: Claude Code (Anthropic) assisted in reducing the original crash to a minimal, dependency-free reproducer (via creduce plus manual bisection, verifying each reduction step against the actual crash), which informed root-causing this bug in RegionStoreManager::bindArray and ExprEngine::ProcessInitializer. The commits made here were drafted with Claude's assistance and reviewed by me before being pushed. I've reviewed all AI-assisted contributions here and take full responsibility for the correctness of this change. --------- Co-authored-by: Andy Ames <andy.ames@joby.aero> Co-authored-by: Balázs Benics <benicsbalazs@gmail.com> (cherry picked from commit 5b1fa37)
…llvm#210167) When `std::get` is called on a dereferenced integer-to-pointer cast, the checker `alpha.core.StdVariant` crashes. Minimal reproducer: ``` std::get<int>(*(std::variant<int, char> *)11); ``` Godbolt reproducer - https://godbolt.org/z/4EKe1PrKb The root cause is that `StdVariantChecker::handleStdGetCall()` calls `SVal::getType()` on any non-unknown argument, then calls `getPointeeType()` on the result while assuming it is a pointer type. In the case of a concrete integer cast to a pointer and then dereferenced, it is modeled as `loc::ConcreteInt`, whose recovered type is an integer. `getPointeeType()` on such an input returns a null QualType, on which `getTypePtr()` crashes. Fix the crash by using the argument's static type rather than recovering its SVal, eliminating the need to guard and call `getPointeeType()`. (cherry picked from commit accd1ed)
Ensure that `llvm-readobj` / `llvm-readelf` processes and dumps all
SHT_LLVM_CALL_GRAPH sections present in an object file, rather
than just the first one.
**Motivation:**
Consider this `foo.s` file
```
.pushsection .text, "axG", %progbits, foo
.globl foo
foo:
ret
.pushsection .llvm.callgraph, "?", %llvm_call_graph
.byte 0, 0
.dc.a foo
.quad 0
.popsection
.popsection
.pushsection .text, "axG", %progbits, bar
.globl foo
bar:
ret
.pushsection .llvm.callgraph, "?", %llvm_call_graph
.byte 0, 0
.dc.a bar
.quad 0
.popsection
.popsection
```
`clang -c foo.s && llvm-readelf --elf-output-style=JSON --pretty-print
--call-graph-info foo.o` on that shows that there is only one record
reported because the current implementation just looked at the first
SHT_LLVM_CALL_GRAPH section and then ignored all others. This patch will
address this gap by iterating over all the SHT_LLVM_CALL_GRAPH sections.
(cherry picked from commit eb76774)
…nsts (llvm#210955) `expandCCOpToCMov` was only accepting signed 5-bit immediates before forming `Xqcicm` conditional-move pseudos. Valid `uimm5` operands for unsigned compare forms such as `QC_MVGEUI` and `QC_MVLTUI` were not being handled leading to a crash. Track whether the selected conditional-move opcode expects a signed or unsigned immediate, and validate the RHS against the matching range. (cherry picked from commit 9bcb851)
…llvm#211019) The pre-RA Zilsd optimizer allowed a pair when both stored values came from the same virtual register if that virtual register was defined by a copy from X0. This is only valid when the virtual register class can actually contain X0. Check the virtual register class before treating the value as `x0_pair`. This prevents forming an invalid paired store for register classes such as `GPRNoX0`. Without this change we were hitting the following assertion in `RISCVLoadStoreOptimizer`: ``` assert( FirstReg != SecondReg && "First register and second register is impossible to be same register"); ``` (cherry picked from commit 6b408bf)
…wering (llvm#209701) **Summary** This regression was introduced by llvm#196094, which added a special lowering path for reductions on a single array element, such as `a(2)`. The problem is that Flang also treated an array section like `a(2:96)` as if it were a single element. Because of this, the section was sent to a code path that only supports scalar elements. That path produced an array type that the reduction initialization code could not handle, so Flang reached a `TODO` and aborted with a “not yet implemented” error. **Fix** The fix is to use the special element path only when the expression has rank 0, which means it represents one single value. Array sections have rank greater than 0, so they should continue through the existing boxed-array path. Fixes : [209462](llvm#209462) --------- Co-authored-by: Jay Satish Kumar Patel <kumarpat@pe31.hpc.amslabs.hpecorp.net> (cherry picked from commit 6c560cd)
) This was previously not required, but the patch to introduce a new size-based vector layout unintentionally added this new requirement. We almost certainly not want to promise this guarantee going forward, but we should actually land this change explicitly and consider the transition story, not do it as a fallout of another refactoring. Fixes llvm#210732 (cherry picked from commit 17ac8fd)
We need to checkout the upload-release-artifact composite action before using it. (cherry picked from commit 8ad500f)
Several sanitizer tests hang indefinitely on NetBSD: ``` MemorySanitizer-Unit :: ./Msan-x86_64-Test MemorySanitizer-Unit :: ./Msan-x86_64-with-call-Test MemorySanitizer-X86_64 :: zero_alloc.cpp ThreadSanitizer-x86_64 :: signal_cond.cpp libFuzzer-x86_64-default-NetBSD :: reload.test ``` All of them loop and don't time out, so they need to be terminated manually for `ninja check-all` to complete. To avoid this, this patch skips the affected tests or subtests. Unfortunately, the Msan unit tests still hang on exit in `__cxa_finalize` even if all subtests are skipped with `llvm-lit -gtest_filter=-*`. Tested on `x86_64-pc-netbsd11.0`, `x86_64-pc-freebsd15.1`, and `x86_64-pc-linux-gnu`. (cherry picked from commit 782f113)
When fix-its are emitted into a .dia, we previously stored the fix-it text in a blob of arbitrary size, but the size of the text was stored in a separate 16 bit field. For really large fix-its, the size won't fit it those 16 bits, and the compiler crashes. Switch to a variable length encoding of the fit-it size. This is similar to this issue: llvm@e26aea5 We also remove a hard coded check in the clang library used to load .dia files that failed for fix-its whose size doesn't fit in 16 bits. Generated with codex Co-authored-by: Nuri Amari <nuriamari@fb.com> (cherry picked from commit bb123b2)
Revert llvm#196094 and its follow-up llvm#209701. The expression override mechanism does not preserve reduction-object identity across all data environments, leading to incorrect lowering for procedure-local and nested private arrays. Restore the pre-llvm#196094 lowering. Keep coverage showing that array-element constructs compile through the boxed-array reduction path. This was in response to this comment: llvm#196094 (comment) Fixing exactly the bug in the comment wasn't hard but AI code review found a large number of follow on bugs so I think the design needs a rethink, and definitely shouldn't be included in the LLVM release. Assisted-by: Codex
Task and taskloop array-element reductions can introduce both a reduction block argument and an implicit firstprivate block argument for the base array. Sequential symbol binding can then select the wrong argument for references in the construct body. Reject these cases until lowering can distinguish the reduction element from other uses of the base array. Keep supported array-element reduction coverage in the existing test and move the unsupported task forms to focused TODO tests. Assisted-by: Codex
…eadsInfo (llvm#212706) Add `ReadFrameZeroStackMemory`, which expedites the innermost frame's stack memory so a variables view on a stop is served from lldb's memory cache. When frame 0's `$fp` looks usable, two windows are expedited: * `[$fp + 2*ptr_size, $fp + 2*ptr_size + k_expedite_stack_arg_size)` for stack-passed parameters, starting above the saved `{fp, lr}` pair the backchain already covers. * `[$fp - below, $fp)`, `below = min($fp - $sp, k_expedite_stack_window - k_expedite_stack_arg_size)`, for locals and spilled register arguments. A small frame gets all of `[$sp, $fp)`; a large one keeps the part nearest `$fp`, so the cost stays bounded. If `$fp` fails validation (frameless leaf, or `$fp` used as a scratch GPR), a single `[$sp, $sp + k_expedite_stack_window)` window is expedited instead. Each window is a separate chunk, because lldb's L1 cache only serves reads fully contained in one expedited chunk. Only the thread that stopped gets these windows, so the stop reply does not grow with thread count. `GetJSONThreadsInfo` now builds the `"memory"` array from both sources and emits it whenever either produced an entry. Add `JSONGenerator::Array::empty` for that check. (cherry picked from commit b631e0c)
Hexagon implements KCFI operand-bundle lowering in the back end HexagonTargetLowering::EmitKCFICheck emits a KCFI_CHECK pseudo, which HexagonAsmPrinter::LowerKCFI_CHECK expands into a type-hash check and a trap - like PS_crash. Hexagon was never added to the list in addKCFIPass() of targets whose back end lowers the bundles, so Clang kept running the middle-end KCFIPass for it. Add Hexagon to the addKCFIPass() early-return so the "kcfi" bundles reach the back end, which then emits the trapping load that actually blocks the call. (cherry picked from commit 23a601d)
…ation (gcc 7.5.0) (llvm#211331) GCC 7.5.0 fails to compile this code. Use explicit upcasts from std::unique_ptr<Derived> to std::unique_ptr<Base> in deserializeSummary and deserializeAnalysisResult. This resolves a compilation error where llvm::Expected<std::unique_ptr<Base>> could not be constructed from unique_ptr of derived summary/result types.
lldb.SBValue.format should map to GetFormat instead of GetName (cherry picked from commit 91ba38d)
…llvm#216730) `visitSelectInst` folds: select(mask, masked.load(ptr, mask, PT), FV) into: masked.load(ptr, mask, FV) The replacement load was previously created at the select, effectively moving the memory access past any intervening instructions. If one of them writes the loaded memory, the replacement load reads the updated value instead of the original one. This was also observed downstream in [ispc/ispc#3891](ispc/ispc#3891). The fold was added in `eb8589987267`. The issue is labelled `regression:22`, so it affects LLVM 22.1 as well as current trunk. Create the replacement load at the original load's position and require `FV` to be available there. Otherwise, leave the select unchanged. Requiring `FV` to be available at the original load means the fold no longer fires when `FV` is computed between the load and the select. No existing `llvm/test/Transforms` checks change as a result of this restriction. Tests cover an intervening aliasing store and the case where `FV` is unavailable at the original load. They also guard against carrying over call-site attributes such as `range` and `noundef` when those attributes no longer apply. Fixes llvm#215453 (cherry picked from commit fec2cba)
…lvm#216318) `MemoryCache::Read` fetches a whole L2 cache line for any read that fits in one, so reading a few bytes caches the line around them. `ReadRanges` probed only L1, and re-fetched ranges that line already held. Callers hit this whenever they read an array's header and then batch the elements that follow it in the same line, as `AppleObjCRuntimeV2::SharedCacheImageHeaders` and `ClassDescriptorV2::method_list_t` both do. llvm#201166 uses MemoryCache in `Process::ReadRangesFromMemory`, but I didn't see why is L1 used only. Add `FindL2CacheEntry`, a lookup that never reads from the inferior, and consult it after L1. When it serves every range in a batch, `ReadRanges` returns without calling `Process::DoReadMemoryRanges`, so no packet is sent. As in the L1 lookup a range spanning two lines is a miss, and a partially read line is used only up to what it holds. Over the region `TestObjCMethodsNSError.test_runtime_types_efficient_memreads` brackets, `MultiMemRead` drops from 190 packets to 107 and the ranges they carry from 7004 to 6411, with the `m`/`x` count unchanged at 856. That test now also requires no read range to be contained in one an earlier packet already read, which counted 593 ranges before this change and none after. `TestReadMemoryRangesUsesL2Cache` covers the lookup directly. (cherry picked from commit 797a057)
Only alloca or poison is allowed as arguments for lifetime intrinsics. Before replacing, check if the operand can be replaced with a variable and skip replacement if it is not valid. Fixes a verifier crash in the added test case. PR: llvm#216991 (cherry picked from commit 13034ef)
…lvm#208263) This commit is a change to `wasm-ld`'s behavior when the `--cooperative-threading` flag is passed to the linker. The change here is to by default work as if `--export-table` was passed as well. This is required conventionally on this target because the table is where function pointers are read from in the component model `thread.new-indirect` intrinsic. If the table is not exported then there's no way to turn the core module into a component so it's effectively required. This behavior only applies to when the table isn't otherwise imported, for example in shared libraries. The other motivation behind this change is that it'll avoid the need to manually specify `-Wl,--export-table` when compiling for the `wasm32-wasip3` target. This additionally avoids the need for the Clang driver to figure out if flags like `--import-table` were otherwise passed. Basically it seemed best to put this in `wasm-ld` itself to avoid as little juggling of pieces as necessary. cc WebAssembly/wasi-libc#808
…llvm#206831) With `--gc-sections` (the default), `wasm-ld` garbage-collects functions that are only reachable through `__wasm_get_tls_base` / `__wasm_set_tls_base` in the cooperative-threading (libcall thread-context) configuration. This produces a linked module that is invalid or behaves incorrectly: the relocation inside `__wasm_set_tls_base` is left dangling / mis-resolved, so callers trap at runtime (e.g. `validation error: ... values remaining on stack at end of block`, or a call to an unrelated function). In cooperative-threading mode (`--cooperative-threading`, added in llvm#200855), per-task thread context is accessed through libcalls rather than wasm globals. `wasm-ld` synthesizes `__wasm_init_tls` / `__wasm_init_memory`, which invoke `__wasm_get_tls_base` and `__wasm_set_tls_base` via **raw `call` instructions that carry no relocations**. To keep those accessors in the output, the linker marks them live with `Symbol::markLive()`. ## Error and Repro ```bash Error: failed to compile: wasm[0]::function[16]::__wasm_set_tls_base Caused by: 0: WebAssembly translation error 1: Invalid input WebAssembly code at offset 778: type mismatch: values remaining on stack at end of block ``` import was dropped and __wasm_set_tls_base was rewritten from ```wat (func $__wasm_set_tls_base (param i32) local.get 0 call $__wasm_component_model_builtin_context_set_1) ;; correct ``` to ```wat (func $__wasm_set_tls_base (param i32) local.get 0 call $__wasm_component_model_builtin_context_get_0) ;; wrong: get_0 is () -> i32 ``` Minimal linker-only repro (no runtime needed) is: ```bash wasm-ld --cooperative-threading tls.o libc.a # context-set-1 dropped, set_tls_base calls get_0 wasm-ld --cooperative-threading --no-gc-sections tls.o libc.a # correct ``` ## Root cause `Symbol::markLive()` sets the live flag (and the chunk's live bit) but does not push the defining chunk onto the mark queue. The mark phase only follows relocations of chunks that were enqueued via `MarkLive::enqueue()`. As a result the accessors' own relocations are never traversed. This is the same situation already handled for constructors reached through the relocation-less `__wasm_call_ctors`, which `MarkLive::run()` enqueues explicitly. ## Fix In `MarkLive::run()`, enqueue the defining chunks of `__wasm_get_tls_base` and `__wasm_set_tls_base` before `mark()`, so their relocations are followed. ```cpp for (Symbol *sym : {static_cast<Symbol *>(ctx.sym.getTLSBase), static_cast<Symbol *>(ctx.sym.setTLSBase)}) if (sym) if (InputChunk *c = sym->getChunk()) enqueue(c); ``` The symbols are only set in the libcall-thread-context configuration and are null otherwise, so the loop is a no-op for all other builds. ## Testing Adds `lld/test/wasm/cooperative-threading-gc.s`, which links with `--cooperative-threading --gc-sections` and checks (via `obj2yaml`) that the import called by `__wasm_set_tls_base` survives GC. Without this change the test drops the import and rewrites `__wasm_set_tls_base` to call an unrelated function; with it the import is retained and the call is correct. ```sh ninja check-lld-wasm ``` ## Note Human-in-the-loop with claude opus 4.8. I iterated with this patch and got to a working component running with a wasi-sdk fork.
This commit fixes a few issues that have surfaced in `wasm-ld`'s handling of `--cooperative-threading` with `-shared`. Two primary issues fixed are: * The `__wasm_init_memory` function was not valid as it referenced nonexistent locals. This was fixed by adjusting how locals are declared to make this a bit more flexible. * Combining data segments for PIC without extended-const is generalized to only operate on active data segments and is now orthogonal to threading. With coop threads there's a mixture of passive/active segments (TLS is passive, other data is active) and the active segments still need combining while TLS stays passive. The latter fix ended up touching a few more areas. The first is that `.tdata` sections are now sorted just before `.bss`, the end section, rather than first. This is done to ensure that active segments when combined can indeed start at a relative address of 0 (as required without extended-const). This change resulted in a number of adjustments for tests as the data is now sorted differently. Additionally relocations in TLS segments needed adjusting since the previous implementation implicitly only worked if `.tdata` is first.
This commit updates how `wasm-ld` initializes the `__init_tls_base` global during module instantiation. Previously this global was left entirely unmodified meaning that it was always 0. This change updates the `__wasm_init_memory` function to set this global dynamically in PIC mode based on the TLS address calculation, or in non-PIC mode the generation of `__wasm_init_memory` correctly sets it to the desired TLS address. cc WebAssembly/wasi-libc#819
…#215548) The fold here for (abs (sub x y)) -> (abdu x y) was proven in Alive, assuming that both operands had a sign bit of zero. However, the code was checking if x had a sign bit of zero and y had a sign bit of 1 Fixes llvm#214942 Original Alive proof from llvm#186659 : https://alive2.llvm.org/ce/z/HfPF5q A variant that's explicitly (abs (sub x y)): https://alive2.llvm.org/ce/z/QEgDaa And changing the range to 32770 or higher there will break the transformation (cherry picked from commit 93030c3)
a118910 added B.W to v8-M Baseline, relaxing t2B, tCBZ and tCBNZ from Requires<[IsThumb2]> to Requires<[IsThumb, HasV8MBaseline]>, and enabled tail calls for it. It missed tTAILJMPd, which expands to t2B but still required IsThumb2, so emitting a tail call for a Thumb1 MachO target failed: > LLVM ERROR: Attempting to emit tTAILJMPd instruction but the Feature_IsThumb2 predicate(s) are not met (cherry picked from commit 0ef7e0c)
Repro:
```llvm
target triple = "s390x-linux-gnu"
define <2 x half> @fabs_v2f16(<2 x half> %arg) "target-cpu"="z16" {
%bits = bitcast <2 x half> %arg to <2 x i16>
%is_neg = icmp slt <2 x i16> %bits, zeroinitializer
%neg = fneg <2 x half> %arg
%res = select <2 x i1> %is_neg, <2 x half> %neg, <2 x half> %arg
ret <2 x half> %res
}
```
```console
$ llc fp-half-vector-abs.ll
llc: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:7343: SDValue llvm::SelectionDAG::getNode(unsigned int, const SDLoc &, EVT, SDValue, const SDNodeFlags): Assertion `N1.getValueType().bitsGT(VT) && "Invalid truncate node, src < dst!"' failed.
```
Previously this code would generate:
i16 = bitcast f16
i32 = truncate i16
Which would immediately assert due to the invalid truncate, but even
with that fixed it would assert later due to the illegal i16. Instead,
use the same lowering as `LowerOperationWrapper` for the bitcast.
(cherry picked from commit 1c51891)
…or operand scalarization (llvm#216136) PowerPC registers v1i128 as a legal type when P8Altivec is available. When lowering <4 x fp128> comparisons, the type legalizer hits a v1i1 only assert. Generalize the assert to accept any single-element vector result type. (cherry picked from commit 9f4703c)
…de (llvm#215929) When extended-const is enabled, non-TLS global relocations are handled via extended constant expressions. However, TLS GOT entries still require runtime relocation code in `__wasm_apply_global_tls_relocs` because TLS global addresses depend on `__tls_base`. Allow `GlobalSection::generateRelocationCode` to be called when `TLS` is true even if `ctx.arg.extendedConst` is set. (cherry picked from commit 82ea231)
(cherry picked from commit 159dcbf)
…dependently (llvm#217404) We were assuming that both conversions were for the same integer signedness Fixes llvm#217355 (cherry picked from commit fc70e3d)
…#216665) MIPS branch/jump instructions (B, BEQ, JALR64Pseudo, PseudoReturn64, etc.) have a delay slot. The actual encoded size is 8 bytes (instr + NOP). This fixes "out of range PC16 fixup" errors on large functions. This issue was exposed in llvm 23 by commit pr llvm#191460 which changed MipsBranchExpansion to use MBB::iterator instead of instr_iterator, making the MBB size calculation more accurate and revealing the pre-existing bug. Thanks for the pr llvm#187703 `AllowOverEstimate` to help find instr which actual size mismatch expected size . Fix llvm#112010. (cherry picked from commit a97f512)
alexcrichton
added a commit
to alexcrichton/rust
that referenced
this pull request
Aug 21, 2026
This pulls in rust-lang/llvm-project#199 which updates the revision of LLVM 23 to the latest copy of the release branch, just past the rc3 release.
alexcrichton
added a commit
to alexcrichton/rust
that referenced
this pull request
Aug 21, 2026
This pulls in rust-lang/llvm-project#199 which updates the revision of LLVM 23 to the latest copy of the release branch, just past the rc3 release.
Kobzol
pushed a commit
to Kobzol/rust
that referenced
this pull request
Aug 21, 2026
This pulls in rust-lang/llvm-project#199 which updates the revision of LLVM 23 to the latest copy of the release branch, just past the rc3 release.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR is the result of a
git merge origin/release/23.xwhich updates this branch to the latest version of the upstream release/23.x branch.For rationale of this, this notably includes llvm#217096 which lays some groundwork for the upcoming wasip3 target.