diff options
| author | Matthias Krüger <476013+matthiaskrgr@users.noreply.github.com> | 2025-07-11 07:35:22 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-11 07:35:22 +0200 |
| commit | e43481e362431442f2a6e39c3c2d3001ff0cf917 (patch) | |
| tree | 452b5d72a52f99ca49dd1dadc58ba57850d8a8ff /compiler/rustc_codegen_ssa/src | |
| parent | dbd2f303953e66db33f15bb78e2fbf23ca557b13 (diff) | |
| parent | f5fc8727dbbf8c9e93bb0822b2e5bfa77dbd0208 (diff) | |
| download | rust-e43481e362431442f2a6e39c3c2d3001ff0cf917.tar.gz rust-e43481e362431442f2a6e39c3c2d3001ff0cf917.zip | |
Rollup merge of #143718 - scottmcm:ub-transmute-is-ub, r=WaffleLapkin
Make UB transmutes really UB in LLVM Ralf suggested in <https://github.com/rust-lang/rust/pull/143410#discussion_r2184928123> that UB transmutes shouldn't be trapping, which happened for the one path *that* PR was changing, but there's another path as well, so *this* PR changes that other path to match. r? codegen
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/traits/builder.rs | 10 |
2 files changed, 14 insertions, 10 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index cbbb0196890..bf3b1e73b94 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -207,9 +207,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { { // These cases are all UB to actually hit, so don't emit code for them. // (The size mismatches are reachable via `transmute_unchecked`.) - // We can't use unreachable because that's a terminator, and we - // need something that can be in the middle of a basic block. - bx.assume(bx.cx().const_bool(false)) + bx.unreachable_nonterminator(); } else { // Since in this path we have a place anyway, we can store or copy to it, // making sure we use the destination place's alignment even if the @@ -236,14 +234,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { || operand.layout.is_uninhabited() || cast.is_uninhabited() { - if !operand.layout.is_uninhabited() { - // Since this is known statically and the input could have existed - // without already having hit UB, might as well trap for it. - bx.abort(); - } + bx.unreachable_nonterminator(); - // Because this transmute is UB, return something easy to generate, - // since it's fine that later uses of the value are probably UB. + // We still need to return a value of the appropriate type, but + // it's already UB so do the easiest thing available. return OperandValue::poison(bx, cast); } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 9d367748c2a..0f1358ee508 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -136,6 +136,16 @@ pub trait BuilderMethods<'a, 'tcx>: ) -> Self::Value; fn unreachable(&mut self); + /// Like [`Self::unreachable`], but for use in the middle of a basic block. + fn unreachable_nonterminator(&mut self) { + // This is the preferred LLVM incantation for this per + // https://llvm.org/docs/Frontend/PerformanceTips.html#other-things-to-consider + // Other backends may override if they have a better way. + let const_true = self.cx().const_bool(true); + let poison_ptr = self.const_poison(self.cx().type_ptr()); + self.store(const_true, poison_ptr, Align::ONE); + } + fn add(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn fadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn fadd_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; |
