Skip to content

Commit

Permalink
Auto merge of #41917 - arielb1:mir-array, r=nagisa
Browse files Browse the repository at this point in the history
Translate array drop glue using MIR

I was a bit lazy here and used a usize-based index instead of a pointer iteration. Do you think this is important @eddyb?

r? @eddyb
  • Loading branch information
bors committed May 28, 2017
2 parents 41e74a2 + ee982d4 commit 924898f
Show file tree
Hide file tree
Showing 37 changed files with 999 additions and 454 deletions.
10 changes: 8 additions & 2 deletions src/librustc/ich/impls_mir.rs
Expand Up @@ -315,7 +315,8 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Rvalue<'tcx>
mir::Rvalue::Discriminant(ref lvalue) => {
lvalue.hash_stable(hcx, hasher);
}
mir::Rvalue::Box(ty) => {
mir::Rvalue::NullaryOp(op, ty) => {
op.hash_stable(hcx, hasher);
ty.hash_stable(hcx, hasher);
}
mir::Rvalue::Aggregate(ref kind, ref operands) => {
Expand Down Expand Up @@ -374,14 +375,19 @@ impl_stable_hash_for!(enum mir::BinOp {
Le,
Ne,
Ge,
Gt
Gt,
Offset
});

impl_stable_hash_for!(enum mir::UnOp {
Not,
Neg
});

impl_stable_hash_for!(enum mir::NullOp {
Box,
SizeOf
});

impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal });

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/lib.rs
Expand Up @@ -47,7 +47,7 @@
#![cfg_attr(stage0, feature(staged_api))]
#![cfg_attr(stage0, feature(loop_break_value))]

#![recursion_limit="128"]
#![recursion_limit="192"]

extern crate arena;
extern crate core;
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/middle/cstore.rs
Expand Up @@ -245,7 +245,6 @@ pub trait CrateStore {

// flags
fn is_const_fn(&self, did: DefId) -> bool;
fn is_default_impl(&self, impl_did: DefId) -> bool;
fn is_dllimport_foreign_item(&self, def: DefId) -> bool;
fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool;

Expand Down Expand Up @@ -364,7 +363,6 @@ impl CrateStore for DummyCrateStore {

// flags
fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") }
fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false }
fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false }

Expand Down
20 changes: 14 additions & 6 deletions src/librustc/mir/mod.rs
Expand Up @@ -1046,6 +1046,7 @@ pub enum Rvalue<'tcx> {
BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
CheckedBinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),

NullaryOp(NullOp, Ty<'tcx>),
UnaryOp(UnOp, Operand<'tcx>),

/// Read the discriminant of an ADT.
Expand All @@ -1054,9 +1055,6 @@ pub enum Rvalue<'tcx> {
/// be defined to return, say, a 0) if ADT is not an enum.
Discriminant(Lvalue<'tcx>),

/// Creates an *uninitialized* Box
Box(Ty<'tcx>),

/// Create an aggregate value, like a tuple or struct. This is
/// only needed because we want to distinguish `dest = Foo { x:
/// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
Expand Down Expand Up @@ -1132,6 +1130,8 @@ pub enum BinOp {
Ge,
/// The `>` operator (greater than)
Gt,
/// The `ptr.offset` operator
Offset,
}

impl BinOp {
Expand All @@ -1144,6 +1144,14 @@ impl BinOp {
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum NullOp {
/// Return the size of a value of that type
SizeOf,
/// Create a new uninitialized box for a value of that type
Box,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum UnOp {
/// The `!` operator for logical inversion
Expand All @@ -1167,7 +1175,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
}
UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval),
Box(ref t) => write!(fmt, "Box({:?})", t),
NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
Ref(_, borrow_kind, ref lv) => {
let kind_str = match borrow_kind {
BorrowKind::Shared => "",
Expand Down Expand Up @@ -1601,7 +1609,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
Box(ty) => Box(ty.fold_with(folder)),
NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
Aggregate(ref kind, ref fields) => {
let kind = box match **kind {
AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
Expand Down Expand Up @@ -1629,7 +1637,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
rhs.visit_with(visitor) || lhs.visit_with(visitor),
UnaryOp(_, ref val) => val.visit_with(visitor),
Discriminant(ref lval) => lval.visit_with(visitor),
Box(ty) => ty.visit_with(visitor),
NullaryOp(_, ty) => ty.visit_with(visitor),
Aggregate(ref kind, ref fields) => {
(match **kind {
AggregateKind::Array(ty) => ty.visit_with(visitor),
Expand Down
13 changes: 7 additions & 6 deletions src/librustc/mir/tcx.rs
Expand Up @@ -166,7 +166,8 @@ impl<'tcx> Rvalue<'tcx> {
let ty = op.ty(tcx, lhs_ty, rhs_ty);
tcx.intern_tup(&[ty, tcx.types.bool], false)
}
Rvalue::UnaryOp(_, ref operand) => {
Rvalue::UnaryOp(UnOp::Not, ref operand) |
Rvalue::UnaryOp(UnOp::Neg, ref operand) => {
operand.ty(mir, tcx)
}
Rvalue::Discriminant(ref lval) => {
Expand All @@ -179,9 +180,8 @@ impl<'tcx> Rvalue<'tcx> {
bug!("Rvalue::Discriminant on Lvalue of type {:?}", ty);
}
}
Rvalue::Box(t) => {
tcx.mk_box(t)
}
Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t),
Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize,
Rvalue::Aggregate(ref ak, ref ops) => {
match **ak {
AggregateKind::Array(ty) => {
Expand Down Expand Up @@ -227,7 +227,7 @@ impl<'tcx> BinOp {
assert_eq!(lhs_ty, rhs_ty);
lhs_ty
}
&BinOp::Shl | &BinOp::Shr => {
&BinOp::Shl | &BinOp::Shr | &BinOp::Offset => {
lhs_ty // lhs_ty can be != rhs_ty
}
&BinOp::Eq | &BinOp::Lt | &BinOp::Le |
Expand Down Expand Up @@ -270,7 +270,8 @@ impl BinOp {
BinOp::Lt => hir::BinOp_::BiLt,
BinOp::Gt => hir::BinOp_::BiGt,
BinOp::Le => hir::BinOp_::BiLe,
BinOp::Ge => hir::BinOp_::BiGe
BinOp::Ge => hir::BinOp_::BiGe,
BinOp::Offset => unreachable!()
}
}
}
2 changes: 1 addition & 1 deletion src/librustc/mir/visit.rs
Expand Up @@ -509,7 +509,7 @@ macro_rules! make_mir_visitor {
self.visit_lvalue(lvalue, LvalueContext::Inspect, location);
}

Rvalue::Box(ref $($mutability)* ty) => {
Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
self.visit_ty(ty);
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/item_path.rs
Expand Up @@ -218,15 +218,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

// Always use types for non-local impls, where types are always
// available, and filename/line-number is mostly uninteresting.
let use_types = !impl_def_id.is_local() || {
let use_types = !self.is_default_impl(impl_def_id) && (!impl_def_id.is_local() || {
// Otherwise, use filename/line-number if forced.
let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
!force_no_types && {
// Otherwise, use types if we can query them without inducing a cycle.
ty::queries::impl_trait_ref::try_get(self, DUMMY_SP, impl_def_id).is_ok() &&
ty::queries::type_of::try_get(self, DUMMY_SP, impl_def_id).is_ok()
}
};
});

if !use_types {
return self.push_impl_path_fallback(buffer, impl_def_id);
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/ty/maps.rs
Expand Up @@ -774,6 +774,9 @@ define_maps! { <'tcx>
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
[] is_foreign_item: IsForeignItem(DefId) -> bool,

/// True if this is a default impl (aka impl Foo for ..)
[] is_default_impl: ItemSignature(DefId) -> bool,

/// Get a map with the variance of every item; use `item_variance`
/// instead.
[] crate_variances: crate_variances(CrateNum) -> Rc<ty::CrateVariancesMap>,
Expand Down
9 changes: 9 additions & 0 deletions src/librustc/ty/util.rs
Expand Up @@ -600,6 +600,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
})
}

pub fn const_usize(&self, val: u16) -> ConstInt {
match self.sess.target.uint_type {
ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(val as u16)),
ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(val as u32)),
ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(val as u64)),
_ => bug!(),
}
}
}

pub struct TypeIdHasher<'a, 'gcx: 'a+'tcx, 'tcx: 'a, W> {
Expand Down
13 changes: 6 additions & 7 deletions src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
Expand Up @@ -22,7 +22,7 @@ use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::indexed_set::IdxSetBuf;
use rustc_data_structures::indexed_vec::Idx;
use rustc_mir::util::patch::MirPatch;
use rustc_mir::util::elaborate_drops::{DropFlagState, elaborate_drop};
use rustc_mir::util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
use rustc_mir::util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
use syntax::ast;
use syntax_pos::Span;
Expand Down Expand Up @@ -399,14 +399,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
ctxt: self
},
terminator.source_info,
data.is_cleanup,
location,
path,
target,
if data.is_cleanup {
None
Unwind::InCleanup
} else {
Some(Option::unwrap_or(unwind, resume_block))
Unwind::To(Option::unwrap_or(unwind, resume_block))
},
bb)
}
Expand Down Expand Up @@ -455,6 +454,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
let bb = loc.block;
let data = &self.mir[bb];
let terminator = data.terminator();
assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported");

let assign = Statement {
kind: StatementKind::Assign(location.clone(), Rvalue::Use(value.clone())),
Expand All @@ -477,7 +477,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
kind: TerminatorKind::Goto { target: target },
..*terminator
}),
is_cleanup: data.is_cleanup,
is_cleanup: false,
});

match self.move_data().rev_lookup.find(location) {
Expand All @@ -491,11 +491,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
ctxt: self
},
terminator.source_info,
data.is_cleanup,
location,
path,
target,
Some(unwind),
Unwind::To(unwind),
bb);
on_all_children_bits(self.tcx, self.mir, self.move_data(), path, |child| {
self.set_drop_flag(Location { block: target, statement_index: 0 },
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_borrowck/borrowck/mir/gather_moves.rs
Expand Up @@ -438,7 +438,8 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
Rvalue::Ref(..) |
Rvalue::Discriminant(..) |
Rvalue::Len(..) |
Rvalue::Box(..) => {
Rvalue::NullaryOp(NullOp::SizeOf, _) |
Rvalue::NullaryOp(NullOp::Box, _) => {
// This returns an rvalue with uninitialized contents. We can't
// move out of it here because it is an rvalue - assignments always
// completely initialize their lvalue.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_borrowck/borrowck/mir/mod.rs
Expand Up @@ -59,7 +59,7 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
attributes: &[ast::Attribute]) {
let tcx = bcx.tcx;
let def_id = tcx.hir.local_def_id(id);
debug!("borrowck_mir({}) UNIMPLEMENTED", tcx.item_path_str(def_id));
debug!("borrowck_mir({:?}) UNIMPLEMENTED", def_id);

// It is safe for us to borrow `mir_validated()`: `optimized_mir`
// steals it, but it forces the `borrowck` query.
Expand Down
7 changes: 7 additions & 0 deletions src/librustc_data_structures/indexed_vec.rs
Expand Up @@ -212,6 +212,13 @@ impl<I: Idx, T> IndexMut<I> for IndexVec<I, T> {
}
}

impl<I: Idx, T> Default for IndexVec<I, T> {
#[inline]
fn default() -> Self {
Self::new()
}
}

impl<I: Idx, T> Extend<T> for IndexVec<I, T> {
#[inline]
fn extend<J: IntoIterator<Item = T>>(&mut self, iter: J) {
Expand Down
10 changes: 3 additions & 7 deletions src/librustc_metadata/cstore_impl.rs
Expand Up @@ -106,6 +106,7 @@ provide! { <'tcx> tcx, def_id, cdata
closure_type => { cdata.closure_ty(def_id.index, tcx) }
inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
is_foreign_item => { cdata.is_foreign_item(def_id.index) }
is_default_impl => { cdata.is_default_impl(def_id.index) }
describe_def => { cdata.get_def(def_id.index) }
def_span => { cdata.get_span(def_id.index, &tcx.sess) }
stability => { cdata.get_stability(def_id.index) }
Expand Down Expand Up @@ -176,11 +177,6 @@ impl CrateStore for cstore::CStore {
self.get_crate_data(did.krate).is_const_fn(did.index)
}

fn is_default_impl(&self, impl_did: DefId) -> bool {
self.dep_graph.read(DepNode::MetaData(impl_did));
self.get_crate_data(impl_did.krate).is_default_impl(impl_did.index)
}

fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool
{
self.do_is_statically_included_foreign_item(def_id)
Expand Down Expand Up @@ -403,7 +399,7 @@ impl CrateStore for cstore::CStore {
}

self.dep_graph.read(DepNode::MetaData(def_id));
debug!("item_body({}): inlining item", tcx.item_path_str(def_id));
debug!("item_body({:?}): inlining item", def_id);

self.get_crate_data(def_id.krate).item_body(tcx, def_id.index)
}
Expand Down Expand Up @@ -515,4 +511,4 @@ impl CrateStore for cstore::CStore {
drop(visible_parent_map);
self.visible_parent_map.borrow()
}
}
}
3 changes: 2 additions & 1 deletion src/librustc_mir/build/expr/as_rvalue.rs
Expand Up @@ -97,7 +97,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let value = this.hir.mirror(value);
let result = this.temp(expr.ty, expr_span);
// to start, malloc some memory of suitable type (thus far, uninitialized):
this.cfg.push_assign(block, source_info, &result, Rvalue::Box(value.ty));
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
this.cfg.push_assign(block, source_info, &result, box_);
this.in_scope(value_extents, block, |this| {
// schedule a shallow free of that memory, lest we unwind:
this.schedule_box_free(expr_span, value_extents, &result, value.ty);
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_mir/shim.rs
Expand Up @@ -198,11 +198,10 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
elaborate_drops::elaborate_drop(
&mut elaborator,
source_info,
false,
&dropee,
(),
return_block,
Some(resume_block),
elaborate_drops::Unwind::To(resume_block),
START_BLOCK
);
elaborator.patch
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/transform/erase_regions.rs
Expand Up @@ -53,7 +53,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
Rvalue::CheckedBinaryOp(..) |
Rvalue::UnaryOp(..) |
Rvalue::Discriminant(..) |
Rvalue::Box(..) |
Rvalue::NullaryOp(..) |
Rvalue::Aggregate(..) => {
// These variants don't contain regions.
}
Expand Down

0 comments on commit 924898f

Please sign in to comment.