-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Make inline assembly volatile if it has no outputs. Fixes #46026 #46030
Conversation
🤔 Is it possible to write a test for this? |
r? @nrc |
Added a test. r? @eddyb |
If LLVM has this option then presumably it's useful for someone at some point? In the sense of "you probably want this" but perhaps not always? For those users that may wish to turn this off, would they have any recourse? |
You always want this behavior. |
@Zoxc as the reviewer of a PR it's sort of my job to understand why we would want such a change, what the change itself is doing, and if possible there's an alternative route to achieving the final goal. To understand this change there is no description on this PR, no comments indicating what the change is doing on the PR itself, an issue opened by yourself which advocates a different solution, a reference to another PR fixing a similar bug, and only internal comments which say what's happening rather than why. I am not personally intimately familiar with either inline assembly or volatile inline assembly. When I ask a question like "For those users that may wish to turn this off, would they have any recourse?" I'm actually genuinely curious as to what's going on here and why this is being proposed. An answer like "You always want this behavior." basically doesn't help me at all and is very curt and seems to assume that I should obviously understand that this is the only possible change we could do. I'd ask again, then, why doesn't LLVM do this already? Is there a use case for nonvolatile assembly with no outputs? I sort of realize that you don't seem to believe so, but have you investigated LLVM's source code for this? Test cases? Other users? Are there others we could ask? I've found that 99% of the time if there's an option or a flag in LLVM it's there for good reason. We have been bitten many times in the past for not exposing or otherwise defaulting various options. I'd like to be sure that we should do this before approving so, and at this point I without doing what seems to be all of the investigation myself I don't have a lot to go on to make a decision on this PR. |
Inline assembly expressions are pure by default, which means they can be removed if they are unused. You can tell LLVM that it has side effects by marking it "volatile"; for example disabling interrupts or changing some FPU flag. You can also say that the assembly changes memory by using the "memory" clobber. If either "volatile" or "memory" are present, LLVM can never remove the inline assembly expression. If an inline assembly expression has no outputs and is pure, it can never be used and LLVM is free to remove it entirely. This is what happened in compiler-builtins. Such inline assembly expressions are useless and are pretty much guaranteed to be user errors, hence I created #46026. Just adding "volatile" in these cases as suggested by @parched seemed like the better option. It avoids breaking crates and we want "volatile" (and "memory") to eventually be default anyway. We should probably add both "volatile" and "memory" if neither "volatile" or "memory" are present and the inline assembly has no output. Adding both is more conservative, although I suspect "memory" is a stronger constraint than "volatile". If we do this we can write |
Unless they are produced by some kind of macro or code generator, then LLVM removing them is exactly the desired outcome. |
What counts as "output" for the purposes of this code? Is it the
However, it is far from obvious to me that silently adding the side-effects flag is the right option. I'd favor giving the user an error, for several reasons:
To avoid breaking user code, it could be a deny-by-default lint (dependent crates would still compile thanks to --cap-lints, the crate itself is easily fixed). |
Hi @Zoxc, it seems the majority here prefer to emit a deny-by-fault lint instead of silently make the asm |
See this line from the GCC docs:
Matching the GCC/Clang behavior here is probably a good idea. |
I was working under the assumption that Clang differs from GCC here, but apparently it doesn't. Not matching C compilers is unfortunate, but the arguments in favor of an error still stand. Since it's not a silent mismatch, I don't see it causing a lot of trouble (i.e., if someone ports inline asm without outputs from C, they'll get a deny-by-default lint rather than miscompilation). |
What I want is for all inline assembly to be volatile by default. If you want purity you have to explicitly opt-in by marking the assembly |
I can see the appeal of defaulting to volatile. Is that plan written down anywhere else? Does it have buy-in from others? |
@rkruppe There is this thing: https://internals.rust-lang.org/t/inline-assembly-syntax/239 |
Okay, interesting. However, that's a far bigger and more radical proposal than just making volatile the default. It's also quite old, and has received relatively little discussion compared to its size and radicalness (surely explained by the smaller size of the Rust community in 2014). In any case, it doesn't seem like any bigger changes to inline asm are sure to happen soon, so this doesn't really change my position re: this narrower patch. Specifically,
|
I am opposed to changing the current Regardless, I feel that such a change is outside the scope of this issue. I see only two options here:
I don't have any particular preference for either of these options. |
The test needs to be ignored on asm.js. |
Hi @Zoxc, seems like you need to update a test as per #46030 (comment). Could you do that so the PR can be merged? |
@bors r=nikomatsakis |
📌 Commit a29d854 has been approved by |
Make inline assembly volatile if it has no outputs. Fixes rust-lang#46026
⌛ Testing commit a29d854 with merge 1696b8ebf319e7c4258e6bd47154a0b14bfb8d15... |
💔 Test failed - status-appveyor |
💥 Test timed out |
@bors clean retry r- |
No description provided.