-
-
Notifications
You must be signed in to change notification settings - Fork 12.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vim bottle is miscompiled because Xcode 16 has codegen bugs #195325
Comments
I wonder if it's related to Apple's new libiconv implementation. See https://savannah.gnu.org/bugs/?65686 and discussion at #194691. Does it still happen if you link against https://formulae.brew.sh/formula/libiconv#default instead? |
It's not iconv. This is a code miscompilation issue, which I verified by using a debugger/disassembler. The code in question does not call iconv code and displays different results depending on whether one uses I actually have a dedicated repository that one can use to reproduce this bug and it does not rely on iconv and is a pretty simple one-file test (it uses extracted Vim code to make it easier to inspect): https://github.com/ychin/xcode16-clang-codegen-bug Speaking of iconv, Apple has fixed iconv around macOS 14.2 to be conformant to how GNU iconv works. It was only broken around macOS 14.0 - 14.1. I was going to file an issue about that, but it's another topic of discussion. |
From further testing, seems like system Vim ( |
Doesn't seem that way, since gnulib rejects all Apple libiconv implementations starting macOS 14. The |
A bit late for that, since we just upgraded our macOS 14 machines to Xcode 16. If the issue is more widespread we could maybe discuss rolling it back. CC @Homebrew/maintainers |
Are you able to reproduce the issue with |
I tried llvm@17/18/19 and could not reproduce the issue. This seems to only exist in Xcode 16 clang. I did file a bug with Apple using their Feedback Assistant but as usual I haven't heard back regarding the bug. My test repo also has CI set up but right now it's only testing Xcode 15 vs Xcode 16 and now the open source LLVM compilers (but not that hard to add them). Edit: I added CI tests to my repo to test open source LLVM as well, as can be seen here: https://github.com/ychin/xcode16-clang-codegen-bug/actions/runs/11486836312
To be fair I don't know how widespread this bug is, but at least from my linked thread in the issue it does seem to affect OpenJDK as well. In that case, the miscompiled code causes a runtime exception so it's causing build step to fail it seems. For now they are just saying "don't use Xcode 16". |
Yes, we've seen that as well. We are, in fact, not using Xcode 16 to build OpenJDK: homebrew-core/Formula/o/openjdk.rb Lines 41 to 53 in 3b86f97
But the OpenJDK bug seems separate from the one affecting Vim. |
The problem doesn't seem to have been wide spread. OpenJDK has a ton of for loops but the problem for some reason only happened with a very specific one and it wouldn't miscompile if you touched it slightly so was extremely difficult to narrow down into a test case to report to Apple beyond "compile this massive project". Your reproducer repo is helpful for narrowing it down - it's the smallest we've managed so far. I'll have a look and see if I can push Apple on it more. Xcode 15 unfortunately does not run on macOS 15 and fixing Xcode 16 is important before Xcode's support for macOS 14 is dropped in a few months. Some packages are now requiring Xcode 16 to even build. |
Right. In the case I see with Vim, it seems to be a bug related to inline functions, whereas in JDK it's some weird issue with the loop. It's hard to tell if the underlying cause is the same though unless we can narrow down to what optimizer pass is causing the issue specifically. But I think this is why I'm raising an issue here. Maybe it's not "wide spread" per se, but so far two projects have already run into it. In JDK's case the miscompilation breaks the program in an obvious way that throws an exception which is good. In Vim's case, it's an infrequently used feature that only got caught by a test in CI. But it's hard to tell what other programs are affected. I do understand the fact that Xcode 16 is what Apple uses for everything and mandatory for targeting new macOS features so it may not easy or even possible to switch away. |
@ychin Thanks for the reproducer. I've verified this still occurs with the update in Xcode 16.2 beta |
As an extra data point, I wasn't able to reproduce with the open sourced parts of Swift Clang: https://github.com/swiftlang/llvm-project/commits/swift-6.0-RELEASE. So seems limited to a bad optimiser pass that Apple have implemented internally for Xcode Clang only. Thanks to your test case, I also narrowed down the bad pass to:
So it can be worked around I think with |
Oh interesting, thanks for looking into this. I was not aware of this LLVM trick (optimization passes bisect) before. That seems very useful for future. I can confirm this flag fixes this particularly issue. I'll update the Apple bug with this information. You can see that this flag would fix the issue: https://github.com/ychin/xcode16-clang-codegen-bug/actions/runs/11488583311/job/31975597614 Let me try to build Vim with this and see if tests pass, how it affects the program, etc. |
The optimisation eliminates a condition (unsurprisingly from the name) seemingly by attempting to collapse into a previous condition so sounds about right that it's the cause:
19: ; preds = %16, %13
%20 = phi i64 [ 1, %13 ], [ %17, %16 ]
%21 = getelementptr inbounds i8, ptr %3, i64 %20
%22 = load i8, ptr %21, align 1, !tbaa !6
%23 = and i8 %22, -64
%24 = icmp eq i8 %23, -128
br i1 %24, label %16, label %27
25: ; preds = %6, %16
%26 = icmp slt i8 %4, 0
br i1 %26, label %28, label %51
27: ; preds = %19
br i1 false, label %46, label %51 LLVM |
I ran Vim tests with this command line flag (only for Apple clang 16) and they all pass now (https://github.com/ychin/vim/actions/runs/11489113066), so the flag is working. I also did different testing and benchmarking and it does not appear to affect performance in any significant / concrete ways. I would recommend modifying Vim / MacVim / Neovim formulas to use this flag when building using Xcode 16 until they have this bug fixed. As I mentioned I don't know if other projects other than JDK is affected but this would at least make sure Vim is not buggy. |
I tested OpenJDK and basic bootstrapping passes now (#195392) whereas before I agree it makes sense to apply to Vim in the meantime. I'm not sure if all the information here has been forwarded but we've at least forwarded your bug report FB number to our Apple contacts so hopefully it'll be something that can get fixed prior to macOS 14 support ending in Xcode. |
Apple has also been provided the repo for the reproducer and the flag. |
This can result in build failures (e.g. OpenJDK) and silently miscompile some formulae (e.g. Vim). See Homebrew/homebrew-core#195325.
This can result in build failures (e.g. OpenJDK) and silently miscompile some formulae (e.g. Vim). See Homebrew/homebrew-core#195325.
Probably safer to do it globally. Adding it to superenv at Homebrew/brew#18620. |
@carlocab disagree that introducing a new flag across all of Homebrew is a good solution. It seems to heavy-handed to me, adding the flag to all formulas without actually testing. |
I've opened a PR for vim, passing the right |
@ychin This is fixed in Xcode 16.2 beta 3 (clang-1600.0.26.6). |
Thanks for the update and follow-up! I tried locally and can confirm that the compiler issue seems to be fixed. |
brew gist-logs <formula>
link ORbrew config
ANDbrew doctor
outputVerification
brew doctor
output saysYour system is ready to brew.
and am still able to reproduce my issue.brew update
and am still able to reproduce my issue.brew doctor
and that did not fix my problem.What were you trying to do (and why)?
The current bottled Vim seems to have behavior bugs because the compiler is miscompiling it. From what we can tell Xcode 16 seems to have a fair amount of codegen bugs leading to this.
This issue was discovered in vim/vim#15764, when we attempted to upgrade Vim's CI to use macos-15 runners. It failed one of the tests, and after investigation it appears to be an inherent Xcode 16 clang bug that has not yet been fixed in Xcode.
Note that Vim doesn't seem to be the only affected software. From browsing around it appears JDK is also facing issues with Xcode 16 clang generating wrong results (https://bugs.openjdk.org/browse/JDK-8340341).
I tried to look around but I couldn't find other reports in Homebrew. I'm guessing this is either an niche bug affecting only few software, or the bug is so subtle that it is not easy to detect. Are all bottles in Homebrew built with Xcode 16?
Edit: Note that this affects Neovim as well. One caveat is that Vim bottles seem to be broken in both macOS 14/15 but Neovim bottles seem to be broken only in macOS 15. Using
otool -l
and looking underLC_BUILD_VERSION
, it does seem that Vim is built with Xcode 16 for both macOS 14/15, and Neovim is only using Xcode 16 to build bottles for macOS 15, so that matches the observed behaviors.What happened (include all command output)?
The cursor landed on the
<82>
part, which is not the expected behavior. This doesn't happen when Vim is built in Xcode 15 or when building in Xcode 16 using-O1
/-O0
.What did you expect to happen?
The cursor should land on the
<e2>
part, which is where the invalid UTF-8 sequence starts. This is how it works on macOS 14.Step-by-step reproduction instructions (by running
brew
commands)The text was updated successfully, but these errors were encountered: