-
Notifications
You must be signed in to change notification settings - Fork 340
X86: force enable the mandatory tailcall on Win64 #6281
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
Conversation
Enable the guaranteed tailcall on Windows x86_64 when we encounter a Swift function call. This function will not conform to the Windows prologue requirements which will implicitly break the unwinder and the debugger, but is required to enable the proper Concurrency behaviour for non-trivial programs. This requires associated changes in the Swift repository to update the test expectations.
CC: @TNorthover |
Particularly if Swift is going to need changes anyway (but as a matter of principle too), shouldn't we gate this on I suppose since this is only in Swift's fork for a specific release it's not critical though. |
I'm not sure that is correct though. You can have |
BTW, the swift changes that are needed in the tests: swiftlang/swift#63660 All the points where we attach |
Why should a If it's ultimately down to debugability rather than actual code breaking, that's what debug info is for. Symbolizers might want to use unwind tables too, but I don't view them as a consumer with a stake in the issue. Edit: also bear in mind this whole thing is gated by the guaranteed tail call optimisation that messes with the ABI. You don't end up here by accident. You have to select a guaranteed tail callingconv, or use |
Yes, Windows does proper asynchronous exceptions, and those occur whether you like it or not. That is part of the reason that the prologues are so restrictive. They support asynchronous exceptions, and recovery from exceptions in prologue setup.
Oh, this won't be code breaking per se, but if you have code that is reliant on stack walking or symbolicating, that will break as the unwinder and symbolication paths will not be able to handle the frame. I should reword things to make that more clear.
I think that |
So how does Swift escape these consequences? I had assumed that as long as you didn't do weird things with
This is still sounding like the whole purpose of
That's why I tried to emphasize the target option. Just grepped more and it's |
Oh hang on, I've finally taken the time to look at LangRef and see that My revised question is why doesn't this diff break that guarantee? The function can no longer take part in the platform's asynchronous exception routing. It's not just about debugability. |
It doesn't? My understanding is it does break that. That is why I conditionalised it on swiftasynccc rather than nounwind. |
Ah, okay. So, that is definitely good to know. I was worried that we might end up here in a different language mode as well. However, given that we would want to upstream this, I still think that preventing another language from accidentally breaking the ABI contract is preferable and restricting the "incorrect" codegen to just Swift's async calls is "safer". |
Fair enough. I'm certainly persuaded that this solution is a reasonable option now. LGTM. |
I decided to look in a bit more detail the stack layout requirements for Windows X64. The requirements are: RDX, RCX, R8, R9 are spilt first to home the argument registers (this gives us the contiguous arguments, windows uses 4 regparm not 6 like SysV), and the stack pointer cannot be adjusted in the prologue. The current TCO flow is adjust rsp, spill, adjust rsp. We need it to be spill, adjust rsp. This means that if we want to keep synchronous unwinding working, we need to alter the epilogue to shuffle the data into the spill slots by means of reloading them and not popping the CSRs. WDYT @TNorthover? |
@swift-ci please test |
Please test with following PRs: @swift-ci please test |
Going to go ahead and merge this for now; we can iteratively try to improve this for debugging. |
Can we pull this into 5.9? |
I might need a bit of help to get that to happen but seems feasible. Fundamentally, there isn't much that should block that. I can try to take a pass at it tomorrow. I think that I did run into some tests on the Swift side that needed a bit of investigation. |
5.9 branched a few weeks ago, so hopefully it's not too tricky. Of course, I could ask about 5.8 as well :) |
Hahah, I'd be impressed if we find a way to bring this into 5.8! |
Enable the guaranteed tailcall on Windows x86_64 when we encounter a Swift function call. This function will not conform to the Windows prologue requirements which will implicitly break the unwinder and the debugger, but is required to enable the proper Concurrency behaviour for non-trivial programs. This requires associated changes in the Swift repository to update the test expectations.