Skip to content

Bump LLVM to v21#59950

Draft
giordano wants to merge 10 commits intomasterfrom
mg/llvm-21
Draft

Bump LLVM to v21#59950
giordano wants to merge 10 commits intomasterfrom
mg/llvm-21

Conversation

@giordano
Copy link
Copy Markdown
Member

@giordano giordano commented Oct 24, 2025

I won't be able to work on this besides for rebasing the PR and other small edits, I'm opening this PR to keep the ball rolling, but everyone is more than welcome to take it over.

This needs #59946 to start with.

@giordano giordano added building Build system, or building Julia or its dependencies external dependencies Involves LLVM, OpenBLAS, or other linked libraries stdlib Julia's standard library JLLs compiler:llvm For issues that relate to LLVM labels Oct 24, 2025
@giordano
Copy link
Copy Markdown
Member Author

Oh, cool, with the changes in #59946 temporarily incorporated here, for the platforms where compilation is successful (macos and freebsd) tests are already passing, that's encouraging.

@yuyichao
Copy link
Copy Markdown
Contributor

The compile error on linux seems to be a Werror for uninitialized variable in LLVM. It could easily be a false positive since it's in the part of the code where LLVM does it's trick with memory layout of objects...

@giordano
Copy link
Copy Markdown
Member Author

I think

[buildroot]/usr/include/llvm/ADT/DenseMap.h: In function 'bool removeAddrspaces(llvm::Module&, AddrspaceRemapFunction)':
[buildroot]/usr/include/llvm/ADT/DenseMap.h:1207:18: error: '*((void*)(& VMap)+72).llvm::SmallDenseMap<std::pair<llvm::Metadata*, long unsigned int>, long unsigned int>::LargeRep::Buckets' may be used uninitialized in this function [-Werror=maybe-uninitialized]
 1207 |     return Small ? getInlineBuckets() : getLargeRep()->Buckets;
      |            ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[buildroot]/usr/include/llvm/ADT/DenseMap.h:1216:18: error: '*((void*)(& VMap)+72).llvm::SmallDenseMap<std::pair<llvm::Metadata*, long unsigned int>, long unsigned int>::LargeRep::NumBuckets' may be used uninitialized in this function [-Werror=maybe-uninitialized]
 1216 |     return Small ? InlineBuckets : getLargeRep()->NumBuckets;
      |            ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

was fixed by llvm/llvm-project#177168, so we'll have to backport that PR to our fork (we want to build a newer patch version with other patches anyway)

@giordano
Copy link
Copy Markdown
Member Author

Windows build fails with

JIT session error: could not register eh-frame: __register_frame function not found
Internal error: Lookup failed: Failed to materialize symbols: { (JuliaOJIT, { japi1_top-level scope_0#0, jlplt_ijl_toplevel_eval_in_2_got, ccall_ijl_toplevel_eval_in_1 }) }
[8908] signal 22: SIGABRT
in expression starting at boot.jl:283
crt_sig_handler at C:/workdir/src\signals-win.c:101
raise at C:\Windows\System32\msvcrt.dll (unknown line)
abort at C:\Windows\System32\msvcrt.dll (unknown line)
operator() at C:/workdir/src\jitlayers.cpp:2048 [inlined]
CallImpl<JuliaOJIT::publishCIs(llvm::ArrayRef<_jl_code_instance_t*>, bool)::<lambda(llvm::Expected<llvm::DenseMap<llvm::orc::SymbolStringPtr, llvm::orc::ExecutorSymbolDef> >)> > at C:/workdir/usr/include/llvm/ADT\FunctionExtras.h:222
_ZN4llvm3orc23AsynchronousSymbolQuery12handleFailedENS_5ErrorE at C:\workdir\usr\bin\libLLVM-21jl.dll (unknown line)
_ZN4llvm3orc16ExecutionSession15OL_notifyFailedERNS0_29MaterializationResponsibilityE at C:\workdir\usr\bin\libLLVM-21jl.dll (unknown line)
_ZN4llvm3orc21LinkGraphLinkingLayer10JITLinkCtx12notifyFailedENS_5ErrorE at C:\workdir\usr\bin\libLLVM-21jl.dll (unknown line)
_ZN4llvm6detail18UniqueFunctionBaseIvJNS_8ExpectedINS_7jitlink20JITLinkMemoryManager14FinalizedAllocEEEEE8CallImplIZNS3_13JITLinkerBase10linkPhase3ESt10unique_ptrIS9_St14default_deleteIS9_EENS2_INS_8DenseMapINS_3orc15SymbolStringPtrENSF_17ExecutorSymbolDefENS_12DenseMapInfoISG_vEENS0_12DenseMapPairISG_SH_EEEEEEE3$_0EEvPvRS6_ at C:\workdir\usr\bin\libLLVM-21jl.dll (unknown line)
operator() at C:/workdir/usr/include/llvm/ADT\FunctionExtras.h:389 [inlined]

I'll need help for that one.

@giordano
Copy link
Copy Markdown
Member Author

giordano commented Mar 16, 2026

32-bit Windows somehow builds successfully, but then there's an interesting test failure

Error in testset ccall:
Test Failed at C:\buildkite-agent\builds\win2k22-amdci6-4\julialang\julia-master\julia-722c9d9693\share\julia\test\ccall.jl:669
  Expression: x == a + b * 1
   Evaluated: -78957614000159160166582917303 == 168812324694683145004459105838176403456

julia/test/ccall.jl

Lines 664 to 669 in 3360c8c

a = Int128(0x7f00123456789abc)<<64 + typemax(UInt64)
b = Int64(1)
x = ccall((:test_128, libccalltest), Int128, (Int128, Int64), a, b)
@test x == a + b*1

is that an ABI problem with Int128 on 32-bit systems?

@gbaraldi
Copy link
Copy Markdown
Member

@xal-0 JIT session error: could not register eh-frame: __register_frame function not found
Any clue?

@giordano
Copy link
Copy Markdown
Member Author

After Sam's fix to the 64-bit Windows build, its tests are successful 🥳 Ok, I guess now it's time to start a new rebuild of LLVM in Yggdrasil

@giordano
Copy link
Copy Markdown
Member Author

/cache/build/tester-amdci4-10/julialang/julia-master/src/clangsa/GCChecker.cpp:1053:73: error: no matching function for call to 'clang::ento::SValBuilder::conjureSymbolVal(const clang::Expr*, const clang::LocationContext*, clang::QualType&, unsigned int)'
 1053 |         Call.getOriginExpr(), C.getLocationContext(), QT, C.blockCount());
      |       

https://buildkite.com/julialang/julia-master/builds/55880#019d1a76-6b59-47af-badc-653ea1406ce2/L1440

@giordano
Copy link
Copy Markdown
Member Author

giordano commented Mar 23, 2026

We're still getting

[buildroot]/usr/include/llvm/ADT/DenseMap.h:1207:18: error: '*((void*)(& VMap)+72).llvm::SmallDenseMap<std::pair<llvm::Metadata*, long unsigned int>, long unsigned int>::LargeRep::Buckets' may be used uninitialized in this function [-Werror=maybe-uninitialized]
 1207 |     return Small ? getInlineBuckets() : getLargeRep()->Buckets;
      |            ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~

despite backporting llvm/llvm-project#177168, which puzzles me quite a bit. But also, I can't reproduce the warning/error with GCC 15. Edit: I can't reproduce the error with -Werror even with GCC 9 inside BinaryBuilder, so I have no clue where this error is coming from here.

@giordano
Copy link
Copy Markdown
Member Author

I'm temporarily (?) disabling the maybe uninitialized warning for the sake of moving forward because I don't know what to do with it (I can't even reproduce it with gcc from 9 to 15). All 64-bit platforms are looking good, both 32-bit platforms are sad about ccalls involving Int128 (incorrect result on windows, segfault in Linux). Analyzegc needs adapting to new clang API

LLVM 21 replaced the `Stmt*` parameter in `SValBuilder::conjureSymbolVal`
with `ConstCFGElementRef` (llvm/llvm-project#128251). Update all four
call sites in GCChecker.cpp to use `C.getCFGElementRef()` instead of
passing `Expr*` pointers directly.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@giordano
Copy link
Copy Markdown
Member Author

giordano commented Mar 24, 2026

My pattern-matching-powered fix to the analyzegc build failure seems to have worked in the sense that now there are actual errors reported by the analysis:

/cache/build/builder-amdci5-2/julialang/julia-master/src/gc-stock.c:1566:12: error: Dereference of a fixed address [core.FixedAddressDereference]
 1566 |     return *(uintptr_t*)real_addr;
      |            ^
[...]
/cache/build/builder-amdci5-2/julialang/julia-master/src/gc-stock.c:1566:12: error: Dereference of a fixed address [core.FixedAddressDereference]
 1566 |     return *(uintptr_t*)real_addr;
      |            ^
[...]
/cache/build/builder-amdci5-2/julialang/julia-master/usr/include/llvm/ADT/ilist_node_base.h:55:49: error: Access to field 'Parent' results in a dereference of a fixed address [core.FixedAddressDereference]
   55 |   inline ParentTy *getNodeBaseParent() { return Parent; }
      |                                                 ^
[...]
/cache/build/builder-amdci5-2/julialang/julia-master/src/aotcompile.cpp:344:20: error: Passing non-rooted value as argument to function that may GC [julia.GCChecker]
  344 |             list = jl_idset_put_key(list, val, &idx);
      |                    ^                ~~~~

I'll let someone else have fun fixing them 🙃

Edit: my friendly assistant proposed the following patch

diff --git a/src/Makefile b/src/Makefile
index 2f12ff8d80..11c5df6634 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -642,6 +642,8 @@ SA_EXCEPTIONS-jloptions.c                   := -Xanalyzer -analyzer-config -Xana
  # clang doesn't understand that e->vars has the same value in save_env (NULL) and restore_env (assumed non-NULL)
 SA_EXCEPTIONS-subtype.c                     := -Xanalyzer -analyzer-config -Xanalyzer silence-checkers="core.uninitialized.Assign;core.UndefinedBinaryOperatorResult"
 SA_EXCEPTIONS-codegen.c                     := -Xanalyzer -analyzer-config -Xanalyzer silence-checkers="core"
+SA_EXCEPTIONS-gc-stock.c                    := -Xanalyzer -analyzer-config -Xanalyzer silence-checkers="core.FixedAddressDereference"
+SA_EXCEPTIONS-aotcompile.cpp                := -Xanalyzer -analyzer-config -Xanalyzer silence-checkers="core.FixedAddressDereference"
  # these need to be annotated (and possibly fixed)
 SKIP_GC_CHECK := codegen.cpp rtutils.c
 
diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp
index 1fbfd459fc..96220989fa 100644
--- a/src/aotcompile.cpp
+++ b/src/aotcompile.cpp
@@ -341,7 +341,10 @@ public:
         jl_value_t *rval = jl_idset_get(list, keyset, val);
         if (rval == NULL) {
             ssize_t idx;
+            JL_GC_PROMISE_ROOTED(list);
             list = jl_idset_put_key(list, val, &idx);
+            JL_GC_PROMISE_ROOTED(list);
+            JL_GC_PROMISE_ROOTED(keyset);
             keyset = jl_idset_put_idx(list, keyset, idx);
         }
     }

but I can't really judge it, so I'm not even trying to push these changes.

LLVM 21 (llvm/llvm-project#138092) aligns i128 to 16 bytes when
passing on the x86-32 stack. However, GCC does not support __int128
on 32-bit x86 at all, so C libraries use struct { int64_t, int64_t }
which only has 4-byte stack alignment. This mismatch caused segfaults
on Linux and incorrect results on Windows for ccalls involving Int128.

Fix by using [4 x i32] instead of i128 as the byval type for large
integer arguments, which naturally has 4-byte alignment matching the
C ABI. Also fix abi_win32.cpp to pass large primitive types like Int128
by reference (byval) instead of directly, avoiding the same alignment
issue.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@giordano
Copy link
Copy Markdown
Member Author

All tests green, yay! Now only analyzegc is unhappy.

giordano and others added 2 commits March 31, 2026 10:18
Add JL_GC_PROMISE_ROOTED annotations in egal_set::insert() for val,
list, and keyset. These class members are rooted by the caller via
JL_GC_PUSH3, but the GC checker cannot track rooting through class
member indirection. The post-put_key annotation on list is needed
because the returned pointer is a new value assigned to the already-
pushed member address.

Suppress optin.core.FixedAddressDereference false positives in
llvm-alloc-opt.cpp (LLVM ilist_node_base.h internals) and gc-stock.c
(gc_read_stack bounds-checked address) — this checker is new in
LLVM 21.

Co-authored-by: Claude <noreply@anthropic.com>
@giordano
Copy link
Copy Markdown
Member Author

giordano commented Apr 4, 2026

@nanosoldier runtests()

@giordano
Copy link
Copy Markdown
Member Author

giordano commented Apr 7, 2026

@maleadt What's up with nanosoldier?

@maleadt
Copy link
Copy Markdown
Member

maleadt commented Apr 8, 2026

Down until further notice.

@giordano giordano added the needs pkgeval Tests for all registered packages should be run with this change label Apr 8, 2026
@maleadt
Copy link
Copy Markdown
Member

maleadt commented Apr 9, 2026

@nanosoldier runtests()

@nanosoldier
Copy link
Copy Markdown
Collaborator

The package evaluation job you requested has completed - possible new issues were detected.
The full report is available.

Report summary

❗ Packages that crashed

5 packages crashed only on the current version.

  • The process was aborted: 1 packages
  • An internal error was encountered: 1 packages
  • A segmentation fault happened: 3 packages

458 packages crashed on the previous version too.

✖ Packages that failed

83 packages failed only on the current version.

  • Package fails to precompile: 60 packages
  • Package has test failures: 2 packages
  • Package tests unexpectedly errored: 2 packages
  • Tests became inactive: 1 packages
  • Test duration exceeded the time limit: 17 packages
  • Test log exceeded the size limit: 1 packages

3904 packages failed on the previous version too.

✔ Packages that passed tests

7 packages passed tests only on the current version.

  • Other: 7 packages

5797 packages passed tests on the previous version too.

➖ Packages that were skipped altogether

1409 packages were skipped on the previous version too.

@giordano
Copy link
Copy Markdown
Member Author

Of the 83 failing packages, I think

Package fails to precompile: 60 packages

are just packages depending on LLVM.jl which doesn't support LLVM 21 yet?

@giordano
Copy link
Copy Markdown
Member Author

@nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Copy Markdown
Collaborator

Your job failed. Consult the server logs for more details.

@giordano giordano added the needs nanosoldier run This PR should have benchmarks run on it label Apr 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

building Build system, or building Julia or its dependencies compiler:llvm For issues that relate to LLVM external dependencies Involves LLVM, OpenBLAS, or other linked libraries JLLs needs nanosoldier run This PR should have benchmarks run on it needs pkgeval Tests for all registered packages should be run with this change stdlib Julia's standard library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants