-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Rollup of 7 pull requests #95944
Rollup of 7 pull requests #95944
Conversation
Co-authored-by: Amanieu d'Antras <amanieu@gmail.com>
We may sometimes emit an `invoke` instead of a `call` for inline assembly during the MIR -> LLVM IR lowering. But we failed to update the IR builder's current basic block before writing the results to the outputs. This would result in invalid IR because the basic block would end in a `store` instruction, which isn't a valid terminator.
Specifically, make it clear that it is immediately UB to pass ill-formed UTF-8 into the function. The previous wording left space to interpret that the UB only occurred when calling another function, which "assumes that `&str`s are valid UTF-8." This does not change whether str being UTF-8 is a safety or a validity invariant. (As per previous discussion, it is a safety invariant, not a validity invariant.) It just makes it clear that valid UTF-8 is a precondition of str::from_utf8_unchecked, and that emitting an Abstract Machine fault (e.g. UB or a sanitizer error) on invalid UTF-8 is a valid thing to do. If user code wants to create an unsafe `&str` pointing to ill-formed UTF-8, it must be done via transmutes. Also, just, don't.
Bootstrap already allows selecting these in `PathSet::has`, which allows any string that matches the end of a full path. I found these by adding `assert!(path.exists())` in `StepDescription::paths`. I think ideally we wouldn't have any aliases that aren't paths, but I've held off on enforcing that here since it may be controversial, I'll open a separate PR.
These paths (`_cranelift` and `_gcc`) are somewhat misleading, since they actually tell bootstrap to build *all* codegen backends. But this seems like a useful improvement in the meantime.
…wiser [`let_chains`] Forbid `let` inside parentheses Parenthesizes are mostly a no-op in let chains, in other words, they are mostly ignored. ```rust let opt = Some(Some(1i32)); if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { println!("`b` is declared inside but used outside"); } ``` As seen above, such behavior can lead to confusion. A proper fix or nested encapsulation would probably require research, time and a modified MIR graph so in this PR I simply denied any `let` inside parentheses. Non-let stuff are still allowed. ```rust fn main() { let fun = || true; if let true = (true && fun()) && (true) { println!("Allowed"); } } ``` It is worth noting that `let ...` is not an expression and the RFC did not mention this specific situation. cc `@matthewjasper`
Replace RwLock by a futex based one on Linux This replaces the pthread-based RwLock on Linux by a futex based one. This implementation is similar to [the algorithm](https://gist.github.com/kprotty/3042436aa55620d8ebcddf2bf25668bc) suggested by `@kprotty,` but modified to prefer writers and spin before sleeping. It uses two futexes: One for the readers to wait on, and one for the writers to wait on. The readers futex contains the state of the RwLock: The number of readers, a bit indicating whether writers are waiting, and a bit indicating whether readers are waiting. The writers futex is used as a simple condition variable and its contents are meaningless; it just needs to be changed on every notification. Using two futexes rather than one has the obvious advantage of allowing a separate queue for readers and writers, but it also means we avoid the problem a single-futex RwLock would have of making it hard for a writer to go to sleep while the number of readers is rapidly changing up and down, as the writers futex is only changed when we actually want to wake up a writer. It always prefers writers, as we decided [here](rust-lang#93740 (comment)). To be able to prefer writers, it relies on futex_wake to return the number of awoken threads to be able to handle write-unlocking while both the readers-waiting and writers-waiting bits are set. Instead of waking both and letting them race, it first wakes writers and only continues to wake the readers too if futex_wake reported there were no writers to wake up. r? `@Amanieu`
…compile, r=Amanieu Fix miscompilation of inline assembly with outputs in cases where we emit an invoke instead of call instruction. We ran into this bug where rustc would segfault while trying to compile certain uses of inline assembly. Here is a simple repro that demonstrates the issue: ```rust #![feature(asm_unwind)] fn main() { let _x = String::from("string here just cause we need something with a non-trivial drop"); let foo: u64; unsafe { std::arch::asm!( "mov {}, 1", out(reg) foo, options(may_unwind) ); } println!("{}", foo); } ``` ([playground link](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=7d6641e83370d2536a07234aca2498ff)) But crucially `feature(asm_unwind)` is not actually needed and this can be triggered on stable as a result of the way async functions/generators are handled in the compiler. e.g.: ```rust extern crate futures; // 0.3.21 async fn bar() { let foo: u64; unsafe { std::arch::asm!( "mov {}, 1", out(reg) foo, ); } println!("{}", foo); } fn main() { futures::executor::block_on(bar()); } ``` ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1c7781c34dd4a3e80ae4bd936a0c82fc)) An example of the incorrect LLVM generated: ```llvm bb1: ; preds = %start %1 = invoke i64 asm sideeffect alignstack inteldialect unwind "mov ${0:q}, 1", "=&r,~{dirflag},~{fpsr},~{flags},~{memory}"() to label %bb2 unwind label %cleanup, !srcloc !9 store i64 %1, i64* %foo, align 8 bb2: [...snip...] ``` The store should not be placed after the asm invoke but rather should be in the normal control flow basic block (`bb2` in this case). [Here](https://gist.github.com/luqmana/be1af5b64d2cda5a533e3e23a7830b44) is a writeup of the investigation that lead to finding this.
Fix formatting error in pin.rs docs Not sure if there's more formatting issues I missed; I kinda lost interest reading midway through.
Clarify str::from_utf8_unchecked's invariants Specifically, make it clear that it is immediately UB to pass ill-formed UTF-8 into the function. The previous wording left space to interpret that the UB only occurred when calling another function, which "assumes that `&str`s are valid UTF-8." This does not change whether str being UTF-8 is a safety or a validity invariant. (As per previous discussion, it is a safety invariant, not a validity invariant.) It just makes it clear that valid UTF-8 is a precondition of str::from_utf8_unchecked, and that emitting an Abstract Machine fault (e.g. UB or a sanitizer error) on invalid UTF-8 is a valid thing to do. If user code wants to create an unsafe `&str` pointing to ill-formed UTF-8, it must be done via transmutes. Also, just, don't. Zulip discussion: https://rust-lang.zulipchat.com/#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/str.3A.3Afrom_utf8_unchecked.20Safety.20requirement
…Mark-Simulacrum Remove duplicate aliases for `check codegen_{cranelift,gcc}` and fix `build codegen_gcc` * Remove duplicate aliases Bootstrap already allows selecting these in `PathSet::has`, which allows any string that matches the end of a full path. I found these by adding `assert!(path.exists())` in `StepDescription::paths`. I think ideally we wouldn't have any aliases that aren't paths, but I've held off on enforcing that here since it may be controversial, I'll open a separate PR. * Add `build compiler/rustc_codegen_gcc` as an alias for `CodegenBackend` These paths (`_cranelift` and `_gcc`) are somewhat misleading, since they actually tell bootstrap to build *all* codegen backends. But this seems like a useful improvement in the meantime. cc ```@bjorn3``` ```@antoyo```
CI: do not compile libcore twice when performing LLVM PGO I forgot the delete the first compilation when modifying this file in a previous PR. r? ```@lqd```
@bors r+ rollup=never p=5 |
📌 Commit 070e8ed has been approved by |
⌛ Testing commit 070e8ed with merge 63035ff192faa6fe3a292b460684a38f7b19697b... |
💔 Test failed - checks-actions |
@bors retry |
⌛ Testing commit 070e8ed with merge c16b9f29894ea19e7d04d63188c6cb1afae6bf7f... |
💔 Test failed - checks-actions |
@bors retry |
The job Click to see the possible cause of the failure (guessed by this bot)
|
☀️ Test successful - checks-actions |
The job Click to see the possible cause of the failure (guessed by this bot)
|
Finished benchmarking commit (de392c7): comparison url. Summary:
If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. @rustbot label: -perf-regression Footnotes |
Successful merges:
let_chains
] Forbidlet
inside parentheses #95008 ([let_chains
] Forbidlet
inside parentheses)check codegen_{cranelift,gcc}
and fixbuild codegen_gcc
#95901 (Remove duplicate aliases forcheck codegen_{cranelift,gcc}
and fixbuild codegen_gcc
)Failed merges:
r? @ghost
@rustbot modify labels: rollup
Create a similar rollup