Skip to content

Commit

Permalink
Auto merge of #118492 - cuviper:beta-next, r=cuviper
Browse files Browse the repository at this point in the history
[beta] backports

- Build pre-coroutine-transform coroutine body #117686
- Fix coroutine validation for mixed panic strategy #118422
- ConstProp: Remove const when rvalue check fails. #118426
- Dispose llvm::TargetMachines prior to llvm::Context being disposed #118464

r? ghost
  • Loading branch information
bors committed Dec 1, 2023
2 parents bd45872 + 6c45608 commit 1a06ac5
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 29 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use std::ffi::{CStr, CString};
use std::fs::File;
use std::io;
use std::iter;
use std::mem::ManuallyDrop;
use std::path::Path;
use std::slice;
use std::sync::Arc;
Expand Down Expand Up @@ -734,7 +735,7 @@ pub unsafe fn optimize_thin_module(
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _;
let mut module = ModuleCodegen {
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
name: thin_module.name().to_string(),
kind: ModuleKind::Regular,
};
Expand Down
21 changes: 16 additions & 5 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ use rustc_span::symbol::Symbol;
use std::any::Any;
use std::ffi::CStr;
use std::io::Write;
use std::mem::ManuallyDrop;

mod back {
pub mod archive;
Expand Down Expand Up @@ -408,8 +409,9 @@ pub struct ModuleLlvm {
llcx: &'static mut llvm::Context,
llmod_raw: *const llvm::Module,

// independent from llcx and llmod_raw, resources get disposed by drop impl
tm: OwnedTargetMachine,
// This field is `ManuallyDrop` because it is important that the `TargetMachine`
// is disposed prior to the `Context` being disposed otherwise UAFs can occur.
tm: ManuallyDrop<OwnedTargetMachine>,
}

unsafe impl Send for ModuleLlvm {}
Expand All @@ -420,15 +422,23 @@ impl ModuleLlvm {
unsafe {
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
ModuleLlvm {
llmod_raw,
llcx,
tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)),
}
}
}

fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
unsafe {
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
ModuleLlvm {
llmod_raw,
llcx,
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
}
}
}

Expand All @@ -449,7 +459,7 @@ impl ModuleLlvm {
}
};

Ok(ModuleLlvm { llmod_raw, llcx, tm })
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
}
}

Expand All @@ -461,6 +471,7 @@ impl ModuleLlvm {
impl Drop for ModuleLlvm {
fn drop(&mut self) {
unsafe {
ManuallyDrop::drop(&mut self.tm);
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
}
}
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_mir_build/src/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,17 +656,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
let args = args.as_coroutine();
let yield_ty = args.yield_ty();
let return_ty = args.return_ty();
let self_ty = Ty::new_adt(
tcx,
tcx.adt_def(tcx.lang_items().pin_type().unwrap()),
tcx.mk_args(&[Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty).into()]),
);
let coroutine_state = Ty::new_adt(
tcx,
tcx.adt_def(tcx.lang_items().coroutine_state().unwrap()),
tcx.mk_args(&[yield_ty.into(), return_ty.into()]),
);
(vec![self_ty, args.resume_ty()], coroutine_state, Some(yield_ty))
(vec![coroutine_ty, args.resume_ty()], return_ty, Some(yield_ty))
}
dk => bug!("{:?} is not a body: {:?}", def_id, dk),
};
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_mir_transform/src/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {

// FIXME we need to revisit this for #67176
if rvalue.has_param() {
trace!("skipping, has param");
return None;
}
if !rvalue
Expand Down Expand Up @@ -708,7 +709,11 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
self.super_assign(place, rvalue, location);

let Some(()) = self.check_rvalue(rvalue) else { return };
let Some(()) = self.check_rvalue(rvalue) else {
trace!("rvalue check failed, removing const");
Self::remove_const(&mut self.ecx, place.local);
return;
};

match self.ecx.machine.can_const_prop[place.local] {
// Do nothing if the place is indirect.
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_mir_transform/src/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1153,18 +1153,9 @@ fn create_coroutine_drop_shim<'tcx>(
simplify::remove_dead_blocks(&mut body);

// Update the body's def to become the drop glue.
// This needs to be updated before the AbortUnwindingCalls pass.
let coroutine_instance = body.source.instance;
let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None);
let drop_instance = InstanceDef::DropGlue(drop_in_place, Some(coroutine_ty));
body.source.instance = drop_instance;

pm::run_passes_no_validate(
tcx,
&mut body,
&[&abort_unwinding_calls::AbortUnwindingCalls],
None,
);

// Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible
// filename.
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_mir_transform/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
debug!("make_shim({:?}) = {:?}", instance, body);

// Run empty passes to mark phase change and perform validation.
pm::run_passes(
tcx,
&mut body,
&[],
&[
&abort_unwinding_calls::AbortUnwindingCalls,
&add_call_guards::CriticalCallEdges,
],
Some(MirPhase::Runtime(RuntimePhase::Optimized)),
);

Expand Down
26 changes: 26 additions & 0 deletions tests/mir-opt/const_prop/overwrite_with_const_with_params.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// unit-test: ConstProp
// compile-flags: -O

// Regression test for https://github.com/rust-lang/rust/issues/118328

#![allow(unused_assignments)]

struct SizeOfConst<T>(std::marker::PhantomData<T>);
impl<T> SizeOfConst<T> {
const SIZE: usize = std::mem::size_of::<T>();
}

// EMIT_MIR overwrite_with_const_with_params.size_of.ConstProp.diff
fn size_of<T>() -> usize {
// CHECK-LABEL: fn size_of(
// CHECK: _1 = const 0_usize;
// CHECK-NEXT: _1 = const _;
// CHECK-NEXT: _0 = _1;
let mut a = 0;
a = SizeOfConst::<T>::SIZE;
a
}

fn main() {
assert_eq!(size_of::<u32>(), std::mem::size_of::<u32>());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
- // MIR for `size_of` before ConstProp
+ // MIR for `size_of` after ConstProp

fn size_of() -> usize {
let mut _0: usize;
let mut _1: usize;
scope 1 {
debug a => _1;
}

bb0: {
StorageLive(_1);
_1 = const 0_usize;
_1 = const _;
_0 = _1;
StorageDead(_1);
return;
}
}

21 changes: 21 additions & 0 deletions tests/ui/const_prop/overwrite_with_const_with_params.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// compile-flags: -O
// run-pass

// Regression test for https://github.com/rust-lang/rust/issues/118328

#![allow(unused_assignments)]

struct SizeOfConst<T>(std::marker::PhantomData<T>);
impl<T> SizeOfConst<T> {
const SIZE: usize = std::mem::size_of::<T>();
}

fn size_of<T>() -> usize {
let mut a = 0;
a = SizeOfConst::<T>::SIZE;
a
}

fn main() {
assert_eq!(size_of::<u32>(), std::mem::size_of::<u32>());
}
11 changes: 11 additions & 0 deletions tests/ui/coroutine/auxiliary/unwind-aux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// compile-flags: -Cpanic=unwind --crate-type=lib
// no-prefer-dynamic
// edition:2021

#![feature(coroutines)]
pub fn run<T>(a: T) {
let _ = move || {
drop(a);
yield;
};
}
13 changes: 13 additions & 0 deletions tests/ui/coroutine/unwind-abort-mix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Ensure that coroutine drop glue is valid when mixing different panic
// strategies. Regression test for #116953.
//
// no-prefer-dynamic
// build-pass
// aux-build:unwind-aux.rs
// compile-flags: -Cpanic=abort
// needs-unwind
extern crate unwind_aux;

pub fn main() {
unwind_aux::run(String::new());
}
8 changes: 8 additions & 0 deletions tests/ui/mir/build-async-error-body-correctly.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// edition: 2021

async fn asyncfn() {
let binding = match true {};
//~^ ERROR non-exhaustive patterns: type `bool` is non-empty
}

fn main() {}
17 changes: 17 additions & 0 deletions tests/ui/mir/build-async-error-body-correctly.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0004]: non-exhaustive patterns: type `bool` is non-empty
--> $DIR/build-async-error-body-correctly.rs:4:25
|
LL | let binding = match true {};
| ^^^^
|
= note: the matched value is of type `bool`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ let binding = match true {
LL + _ => todo!(),
LL ~ };
|

error: aborting due to previous error

For more information about this error, try `rustc --explain E0004`.

0 comments on commit 1a06ac5

Please sign in to comment.