Skip to content

[Place 2.0] Convert Place's projection to a boxed slice #63420

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

Merged
merged 11 commits into from
Sep 13, 2019
308 changes: 91 additions & 217 deletions src/librustc/mir/mod.rs

Large diffs are not rendered by default.

15 changes: 5 additions & 10 deletions src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,21 +121,16 @@ BraceStructTypeFoldableImpl! {
impl<'tcx> Place<'tcx> {
pub fn ty_from<D>(
base: &PlaceBase<'tcx>,
projection: &Option<Box<Projection<'tcx>>>,
projection: &[PlaceElem<'tcx>],
local_decls: &D,
tcx: TyCtxt<'tcx>
) -> PlaceTy<'tcx>
where D: HasLocalDecls<'tcx>
{
Place::iterate_over(base, projection, |place_base, place_projections| {
let mut place_ty = place_base.ty(local_decls);

for proj in place_projections {
place_ty = place_ty.projection_ty(tcx, &proj.elem);
}

place_ty
})
projection.iter().fold(
base.ty(local_decls),
|place_ty, elem| place_ty.projection_ty(tcx, elem)
)
}

pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
Expand Down
72 changes: 39 additions & 33 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,18 @@ macro_rules! make_mir_visitor {
}

fn visit_place_base(&mut self,
place_base: & $($mutability)? PlaceBase<'tcx>,
base: & $($mutability)? PlaceBase<'tcx>,
context: PlaceContext,
location: Location) {
self.super_place_base(place_base, context, location);
self.super_place_base(base, context, location);
}

fn visit_projection(&mut self,
place_base: & $($mutability)? PlaceBase<'tcx>,
place: & $($mutability)? Projection<'tcx>,
base: & $($mutability)? PlaceBase<'tcx>,
projection: & $($mutability)? [PlaceElem<'tcx>],
context: PlaceContext,
location: Location) {
self.super_projection(place_base, place, context, location);
self.super_projection(base, projection, context, location);
}

fn visit_constant(&mut self,
Expand Down Expand Up @@ -344,7 +344,9 @@ macro_rules! make_mir_visitor {

self.visit_source_info(source_info);
match kind {
StatementKind::Assign(place, rvalue) => {
StatementKind::Assign(
box(ref $($mutability)? place, ref $($mutability)? rvalue)
) => {
self.visit_assign(place, rvalue, location);
}
StatementKind::FakeRead(_, place) => {
Expand Down Expand Up @@ -391,7 +393,10 @@ macro_rules! make_mir_visitor {
StatementKind::Retag(kind, place) => {
self.visit_retag(kind, place, location);
}
StatementKind::AscribeUserType(place, variance, user_ty) => {
StatementKind::AscribeUserType(
box(ref $($mutability)? place, ref $($mutability)? user_ty),
variance
) => {
self.visit_ascribe_user_ty(place, variance, user_ty, location);
}
StatementKind::Nop => {}
Expand Down Expand Up @@ -685,7 +690,7 @@ macro_rules! make_mir_visitor {
location: Location) {
let mut context = context;

if place.projection.is_some() {
if !place.projection.is_empty() {
context = if context.is_mutating_use() {
PlaceContext::MutatingUse(MutatingUseContext::Projection)
} else {
Expand All @@ -695,9 +700,10 @@ macro_rules! make_mir_visitor {

self.visit_place_base(& $($mutability)? place.base, context, location);

if let Some(box proj) = & $($mutability)? place.projection {
self.visit_projection(& $($mutability)? place.base, proj, context, location);
}
self.visit_projection(& $($mutability)? place.base,
& $($mutability)? place.projection,
context,
location);
}

fn super_place_base(&mut self,
Expand All @@ -715,31 +721,31 @@ macro_rules! make_mir_visitor {
}

fn super_projection(&mut self,
place_base: & $($mutability)? PlaceBase<'tcx>,
proj: & $($mutability)? Projection<'tcx>,
base: & $($mutability)? PlaceBase<'tcx>,
projection: & $($mutability)? [PlaceElem<'tcx>],
context: PlaceContext,
location: Location) {
if let Some(box proj_base) = & $($mutability)? proj.base {
self.visit_projection(place_base, proj_base, context, location);
}
if let [proj_base @ .., elem] = projection {
self.visit_projection(base, proj_base, context, location);

match & $($mutability)? proj.elem {
ProjectionElem::Field(_field, ty) => {
self.visit_ty(ty, TyContext::Location(location));
}
ProjectionElem::Index(local) => {
self.visit_local(
local,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
location
);
}
ProjectionElem::Deref |
ProjectionElem::Subslice { from: _, to: _ } |
ProjectionElem::ConstantIndex { offset: _,
min_length: _,
from_end: _ } |
ProjectionElem::Downcast(_, _) => {
match elem {
ProjectionElem::Field(_field, ty) => {
self.visit_ty(ty, TyContext::Location(location));
}
ProjectionElem::Index(local) => {
self.visit_local(
local,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
location
);
}
ProjectionElem::Deref |
ProjectionElem::Subslice { from: _, to: _ } |
ProjectionElem::ConstantIndex { offset: _,
min_length: _,
from_end: _ } |
ProjectionElem::Downcast(_, _) => {
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_codegen_ssa/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![feature(box_syntax)]
#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(slice_patterns)]
#![feature(stmt_expr_attributes)]
#![feature(try_blocks)]
#![feature(in_band_lifetimes)]
Expand Down
23 changes: 10 additions & 13 deletions src/librustc_codegen_ssa/mir/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
) {
let cx = self.fx.cx;

if let Some(proj) = place_ref.projection {
if let [proj_base @ .., elem] = place_ref.projection {
// Allow uses of projections that are ZSTs or from scalar fields.
let is_consume = match context {
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
Expand All @@ -114,12 +114,12 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
};
if is_consume {
let base_ty =
mir::Place::ty_from(place_ref.base, &proj.base, self.fx.mir, cx.tcx());
mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir, cx.tcx());
let base_ty = self.fx.monomorphize(&base_ty);

// ZSTs don't require any actual memory access.
let elem_ty = base_ty
.projection_ty(cx.tcx(), &proj.elem)
.projection_ty(cx.tcx(), elem)
.ty;
let elem_ty = self.fx.monomorphize(&elem_ty);
let span = if let mir::PlaceBase::Local(index) = place_ref.base {
Expand All @@ -131,7 +131,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
return;
}

if let mir::ProjectionElem::Field(..) = proj.elem {
if let mir::ProjectionElem::Field(..) = elem {
let layout = cx.spanned_layout_of(base_ty.ty, span);
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
// Recurse with the same context, instead of `Projection`,
Expand All @@ -140,7 +140,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
self.process_place(
&mir::PlaceRef {
base: place_ref.base,
projection: &proj.base,
projection: proj_base,
},
context,
location,
Expand All @@ -151,11 +151,11 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
}

// A deref projection only reads the pointer, never needs the place.
if let mir::ProjectionElem::Deref = proj.elem {
if let mir::ProjectionElem::Deref = elem {
self.process_place(
&mir::PlaceRef {
base: place_ref.base,
projection: &proj.base,
projection: proj_base,
},
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
location
Expand All @@ -168,7 +168,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
// visit_place API
let mut context = context;

if place_ref.projection.is_some() {
if !place_ref.projection.is_empty() {
context = if context.is_mutating_use() {
PlaceContext::MutatingUse(MutatingUseContext::Projection)
} else {
Expand All @@ -177,10 +177,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
}

self.visit_place_base(place_ref.base, context, location);

if let Some(box proj) = place_ref.projection {
self.visit_projection(place_ref.base, proj, context, location);
}
self.visit_projection(place_ref.base, place_ref.projection, context, location);
}

}
Expand All @@ -196,7 +193,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>

if let mir::Place {
base: mir::PlaceBase::Local(index),
projection: None,
projection: box [],
} = *place {
self.assign(index, location);
let decl_span = self.fx.mir.local_decls[index].source_info.span;
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_codegen_ssa/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

PassMode::Direct(_) | PassMode::Pair(..) => {
let op =
self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE.as_ref());
self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref());
if let Ref(llval, _, align) = op.val {
bx.load(llval, align)
} else {
Expand Down Expand Up @@ -612,7 +612,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
ty,
def_id: _,
}),
projection: None,
projection: box [],
}
) |
mir::Operand::Move(
Expand All @@ -622,7 +622,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
ty,
def_id: _,
}),
projection: None,
projection: box [],
}
) => {
let param_env = ty::ParamEnv::reveal_all();
Expand Down Expand Up @@ -1105,7 +1105,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
let dest = if let mir::Place {
base: mir::PlaceBase::Local(index),
projection: None,
projection: box [],
} = *dest {
match self.locals[index] {
LocalRef::Place(dest) => dest,
Expand Down Expand Up @@ -1166,7 +1166,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) {
if let mir::Place {
base: mir::PlaceBase::Local(index),
projection: None,
projection: box [],
} = *dst {
match self.locals[index] {
LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
Expand Down
68 changes: 33 additions & 35 deletions src/librustc_codegen_ssa/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,47 +384,45 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) -> Option<OperandRef<'tcx, Bx::Value>> {
debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);

place_ref.iterate(|place_base, place_projection| {
if let mir::PlaceBase::Local(index) = place_base {
match self.locals[*index] {
LocalRef::Operand(Some(mut o)) => {
// Moves out of scalar and scalar pair fields are trivial.
for proj in place_projection {
match proj.elem {
mir::ProjectionElem::Field(ref f, _) => {
o = o.extract_field(bx, f.index());
}
mir::ProjectionElem::Index(_) |
mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
o = OperandRef::new_zst(bx, elem);
} else {
return None;
}
if let mir::PlaceBase::Local(index) = place_ref.base {
match self.locals[*index] {
LocalRef::Operand(Some(mut o)) => {
// Moves out of scalar and scalar pair fields are trivial.
for elem in place_ref.projection.iter() {
match elem {
mir::ProjectionElem::Field(ref f, _) => {
o = o.extract_field(bx, f.index());
}
mir::ProjectionElem::Index(_) |
mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
o = OperandRef::new_zst(bx, elem);
} else {
return None;
}
_ => return None,
}
_ => return None,
}

Some(o)
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place_ref);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
None
}

Some(o)
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place_ref);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
None
}
} else {
None
}
})
} else {
None
}
}

pub fn codegen_consume(
Expand Down
Loading