Skip to content
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

[SR-3642] SILGen crash when compiling with whole module optimization #46227

Closed
tkrajacic opened this issue Jan 15, 2017 · 31 comments
Closed

[SR-3642] SILGen crash when compiling with whole module optimization #46227

tkrajacic opened this issue Jan 15, 2017 · 31 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software SILGen Area → compiler: The SIL generation stage

Comments

@tkrajacic
Copy link

Previous ID SR-3642
Radar None
Original Reporter @tkrajacic
Type Bug
Status Closed
Resolution Done

Attachment: Download

Environment

DEVELOPMENT-SNAPSHOT-2017-01-13-a

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, CompilerCrash, SILGen
Assignee @belkadan
Priority Medium

md5: cc82d7d59039c4669b13f27cc3043b82

Issue Description:

Update: I finally figured it out!

The crash is happening when you put functions in private extensions of Cocoa classes in two separate files and then turn on whole module optimization. When they have the same parameter names, you crash the compiler.

This will trigger the crash! Put in `FileA.swift` and `FileB.swift` or use the uploaded sample project.

private extension NSMenuItem {
    convenience init(action: Selector?) { self.init() }
}

When I turn on WMO in my project, the compiler crashes:

Assertion failed: (F->empty() && "already emitted function?!"), function preEmitFunction, file /Users/buildnode/jenkins/workspace/oss-swift-package-osx/swift/lib/SILGen/SILGen.cpp, line 591.
0  swift                    0x00000001100fb838 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1  swift                    0x00000001100faa16 llvm::sys::RunSignalHandlers() + 86
2  swift                    0x00000001100fbed9 SignalHandler(int) + 361
3  libsystem_platform.dylib 0x00007fffd10e8bba _sigtramp + 26
4  libsystem_platform.dylib 000000000000000000 _sigtramp + 787575904
5  libsystem_c.dylib        0x00007fffd0f6f420 abort + 129
6  libsystem_c.dylib        0x00007fffd0f36893 basename_r + 0
7  swift                    0x000000010d34da6d void swift::Lowering::SILGenModule::preEmitFunction<swift::ConstructorDecl>(swift::SILDeclRef, swift::ConstructorDecl*, swift::SILFunction*, swift::SILLocation) + 685
8  swift                    0x000000010d3520ea swift::Lowering::SILGenModule::emitConstructor(swift::ConstructorDecl*)::$_2::operator()(swift::SILFunction*) const + 122
9  swift                    0x000000010d349b78 swift::Lowering::SILGenModule::emitConstructor(swift::ConstructorDecl*) + 1096
10 swift                    0x000000010d3faf9b SILGenExtension::visitConstructorDecl(swift::ConstructorDecl*) + 43
11 swift                    0x000000010d3f9edb SILGenExtension::emitExtension(swift::ExtensionDecl*) + 59
12 swift                    0x000000010d3f9e95 swift::Lowering::SILGenModule::visitExtensionDecl(swift::ExtensionDecl*) + 21
13 swift                    0x000000010d34e63b swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*, unsigned int) + 747
14 swift                    0x000000010d34f6f5 swift::SILModule::constructSIL(swift::ModuleDecl*, swift::SILOptions&, swift::FileUnit*, llvm::Optional<unsigned int>, bool, bool) + 1029
15 swift                    0x000000010d34fb46 swift::performSILGeneration(swift::ModuleDecl*, swift::SILOptions&, bool, bool) + 38
16 swift                    0x000000010d1885cc swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 12188
17 swift                    0x000000010d140e91 main + 3025
18 libdyld.dylib            0x00007fffd0edb255 start + 1

Is there any way to find out what is actually causing the problem?
The log in Xcode tells me which file this happens in , but I can actually completely remove all methods and properties from the mentioned class, and this still happens! (So I guess this isn't really the file where it happens after all)

@tkrajacic
Copy link
Author

I have seen SR-1795 but I don't think I am doing any overloading like this.

@belkadan
Copy link
Contributor

This doesn't happen at all in non-WMO optimized builds? Very strange.

The part of the crash log below the stack trace might have information about what function is causing the problem, but if not, we'd probably need to see your project to be any help.

@tkrajacic
Copy link
Author

Yes, it doesn't even happen in Single File Optimization (-O) builds. Only WMO.

Sadly there is no line after the stack trace except for the "Program arguments:..." line, and that only points to said file that is clearly not the culprit.
I found out however that it is always the first file of the target it tries to compile.

The project consists of some frameworks, which build before, and when the main app starts building, the first file always crashes the compiler. I have been starting to remove those files from the target, and it just keeps crashing on the next. Does this tell something?

I can't share the project with you unfortunately as it consist of quite a few other private frameworks.

@tkrajacic
Copy link
Author

With my severely limited knowledge of the toolchain - is it correct that the problem is that there are two functions that seem to emit the same mangled name in SIL even if they should be unique?

Does the error mean, that both are functions `(A) -> Void` of some name where A might be different for both functions, but they return the same SIL name anyway?

Just trying to figure out if starting to rename any functions in my project would help or not.

@tkrajacic
Copy link
Author

Still happens on the latest `swift-3.1-DEVELOPMENT-SNAPSHOT-2017-01-22-a.xctoolchain`

(I am checking every snapshot because I finally want to enable this again and I saw some SILGen related commits lately 😉 )

@belkadan
Copy link
Contributor

That's the general problem, yes, but given that you're only seeing it in WMO mode I doubt that it's actually two functions you have in your project. I would expect you'd get linker errors for anything you wrote explicitly.

@tkrajacic
Copy link
Author

Without any code changes this now compiles as of Xcode 8.3 beta!

I cleaned out twice to make sure because I couldn't believe it.
So the fix must be between `swift-3.1-DEVELOPMENT-SNAPSHOT-2017-01-22-a.xctoolchain` and whatever is inside Xcode 8.3 beta.

Any ideas what fixed it?

@tkrajacic
Copy link
Author

As of Xcode 8.3 beta.

See comment

@belkadan
Copy link
Contributor

IIRC 8.3b1 doesn't have assertions on, so it might just be falling back to some reasonable-ish behavior. I don't think we should treat this as fixed just yet…but at the same time I'm not sure what we can do to help without more information.

@tkrajacic
Copy link
Author

I'd be happy to help and experiment, but I cannot send you my project unfortunately.
(Does being restrictive (e.g. `private` and `final`) with types help? Does the mangled name include scope somehow?)

So if I understand correctly, there is nothing wrong with the resulting binary if it compiles, just that SILGen made some assumptions that it shouldn't have made explicitly, but it was luckily right? Or will I experience undefined behavior in my app when I use `-Owholemodule` now?

@belkadan
Copy link
Contributor

It really might be undefined behavior. Consider the case where there really were two different functions; it probably just picked one and went on. That wouldn't be correct.

@tkrajacic
Copy link
Author

Ok I'm giving up for today (it's close to midnight here).

One thing that came to my mind is that it could be related to Generic subclasses trying to conform to objc protocols. Those also trap the compiler. E.g.

class MyVC<A>: NSViewController {}
extension MyVC: NSTableViewDelegate {}

Those however give a different message.

I do have some generic classes that implement and conform to NSTextFieldDelegate, NSComboBoxDelegate and such, but those never had a problem so far. If this seems like a possibility to you I can try to weed all of those out of my app tomorrow.

@tkrajacic
Copy link
Author

BTW, I checked and if I remove all code (except for the AppDelegate) of my macOS App, it indeed does compile. So it shouldn't be one of the included other projects in the workspace.

@belkadan
Copy link
Contributor

Curious![]( Thank you for continuing to search and finding the reduced test case, Thomas)

@tkrajacic
Copy link
Author

Time well spent!

Thank YOU guys for doing the hard work of actually fixing things 😉

@tkrajacic
Copy link
Author

BTW, what would I have to do to contribute a test case for such an example to the Swift repo (I do find crashers regularly in my projects)?

I'd love to actually help by providing tests as well, but I am not sure where to start (or if that is even feasible).

@tkrajacic
Copy link
Author

In Xcode 8.3 this doesn't crash the compiler anymore, but sourcekit is in perma-crash mode or so, since syntax highlighting is constantly crashing or so.

This brings me back to a question I asked before somewhere but never got an answer: What version of Swift is used for syntax highlighting. In one of my other bugs it was also the case that the compiler didn't crash anymore but the syntax highlighting still couldn't handle the case and constantly crashed.

@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2017

It's always the same version of Swift as the compiler, unless you're using the for-compiler-testing-only build setting SWIFT_EXEC (or a non-public build setting Xcode people use, which is unlikely). That doesn't mean there are no bugs, though—they clearly go down different code paths since there are many times the compiler crashes and syntax highlighting or code completion does not. As always, we'd need a project to really be sure.


To your earlier question, reduced test cases are very useful. If you want to add them to the compiler test suite, you can follow the instructions to build Swift locally at https://github.com/apple/swift, and then add new tests to the test/ and validation-test/ folders, following the (admittedly skimpy) documentation in docs/Testing.rst. (This shouldn't just be arbitrary code; it should either produce a crash—in which case validation-test/compiler_crashers_2/ is a good place to put the test case—or be something that you don't think is covered by the existing tests.)

Once you've made that change, you can submit a pull request to the main Swift repository with your new test, and one of us will merge it in.

Given your skill at reducing your own issue, another way to contribute would be to look at the open bugs tagged CompilerCrash that have whole projects attached and reduce them, so that whoever gets around to fixing the bug will have an easier time pinpointing the problem.

@tkrajacic
Copy link
Author

Thanks Jordan for taking the time to explain!

The test project attached to this SR is a prime example of SourceKit crashing where the compiler is fine though.

I will have a look at the docs and also at reducing other people's examples.

@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2017

Oops, I forgot there was still a project attached! Can you attach a crash log, too, so that we know what SourceKit was trying to do? (Check Console.app.)

@tkrajacic
Copy link
Author

Added a crashlog from Console.app which I believe is related to this now.

@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2017

Ah, that's still a compiler crash, though, not a SourceKit crash.

@tkrajacic
Copy link
Author

Where would I find the sourcekit log?

Mhmm usually I find SourceKit crashes with

ls ~/Library/Logs/DiagnosticReports | grep SourceKitService | wc -l

but this shows 0 at the moment (which is usually in the low hundreds)

@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2017

They should also be under "User Reports", with the process name "SourceKitService".

@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2017

Hm, that's where I'd expect them to be. @akyrtzi, any insights?

@tkrajacic
Copy link
Author

Seems they have changed location. Because switching between the two files in the project definitely kills source coloring every time but there is no crash report in that directory

@akyrtzi
Copy link
Member

akyrtzi commented Apr 3, 2017

AFAIK crashlogs should still go to that directory.
I cannot reproduce any sourcekitd crash with the attached project and Xcode 8.3, do I need to do something specific ? I tried various things.

@tkrajacic
Copy link
Author

Mhm, and syntax highlighting works flawlessly for you?

I suspected that it might not be a SourceKit crash but maybe something else related to syntax highlighting. I just always assumed they were the same thing in this context.

@tkrajacic
Copy link
Author

Anyway, I don't want to keep you from doing far more important work just because my syntax highlighting doesn't work.
Your time is far too precious for that
(BTW I have submitted a new crasher in the meantime ... wink wink 😛 )

@tkrajacic
Copy link
Author

Since the compiler doesn't crash anymore I guess you can close this issue?

@tkrajacic
Copy link
Author

Tested again in Xcode 10 and this is definitely fixed

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added the crash Bug: A crash, i.e., an abnormal termination of software label Dec 12, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software SILGen Area → compiler: The SIL generation stage
Projects
None yet
Development

No branches or pull requests

4 participants