use rustc::hir;
use rustc::hir::def_id::DefId;
-use rustc::infer;
use rustc::mir::*;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::VariantIdx;
};
use crate::util::elaborate_drops::{self, DropElaborator, DropStyle, DropFlagMode};
use crate::util::patch::MirPatch;
+use crate::util::expand_aggregate;
pub fn provide(providers: &mut Providers<'_>) {
providers.mir_shims = make_shim;
// Check if this is a generator, if so, return the drop glue for it
if let Some(&ty::TyS { sty: ty::Generator(gen_def_id, substs, _), .. }) = ty {
- let mir = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap();
- return mir.subst(tcx, substs.substs);
+ let body = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap();
+ return body.subst(tcx, substs.substs);
}
let substs = if let Some(ty) = ty {
block(&mut blocks, TerminatorKind::Goto { target: return_block });
block(&mut blocks, TerminatorKind::Return);
- let mut mir = Body::new(
+ let mut body = Body::new(
blocks,
IndexVec::from_elem_n(
SourceScopeData { span: span, parent_scope: None }, 1
let dropee_ptr = Place::Base(PlaceBase::Local(Local::new(1+0)));
if tcx.sess.opts.debugging_opts.mir_emit_retag {
// Function arguments should be retagged, and we make this one raw.
- mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
+ body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
source_info,
kind: StatementKind::Retag(RetagKind::Raw, dropee_ptr.clone()),
});
let patch = {
let param_env = tcx.param_env(def_id).with_reveal_all();
let mut elaborator = DropShimElaborator {
- mir: &mir,
- patch: MirPatch::new(&mir),
+ body: &body,
+ patch: MirPatch::new(&body),
tcx,
param_env
};
);
elaborator.patch
};
- patch.apply(&mut mir);
+ patch.apply(&mut body);
}
- mir
+ body
}
pub struct DropShimElaborator<'a, 'tcx: 'a> {
- pub mir: &'a Body<'tcx>,
+ pub body: &'a Body<'tcx>,
pub patch: MirPatch<'tcx>,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
type Path = ();
fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
- fn mir(&self) -> &'a Body<'tcx> { self.mir }
+ fn body(&self) -> &'a Body<'tcx> { self.body }
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env }
block(&mut blocks, vec![], TerminatorKind::Resume, true);
}
- let mut mir = Body::new(
+ let mut body = Body::new(
blocks,
IndexVec::from_elem_n(
SourceScopeData { span: span, parent_scope: None }, 1
vec![],
);
if let Abi::RustCall = sig.abi {
- mir.spread_arg = Some(Local::new(sig.inputs().len()));
+ body.spread_arg = Some(Local::new(sig.inputs().len()));
}
- mir
+ body
}
-pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
- ctor_id: hir::HirId,
- fields: &[hir::StructField],
- span: Span)
- -> Body<'tcx>
-{
- let tcx = infcx.tcx;
- let gcx = tcx.global_tcx();
- let def_id = tcx.hir().local_def_id_from_hir_id(ctor_id);
- let param_env = gcx.param_env(def_id);
+pub fn build_adt_ctor<'gcx>(tcx: TyCtxt<'_, 'gcx, 'gcx>, ctor_id: DefId) -> &'gcx Body<'gcx> {
+ debug_assert!(tcx.is_constructor(ctor_id));
+
+ let span = tcx.hir().span_if_local(ctor_id)
+ .unwrap_or_else(|| bug!("no span for ctor {:?}", ctor_id));
+
+ let param_env = tcx.param_env(ctor_id);
// Normalize the sig.
- let sig = gcx.fn_sig(def_id)
+ let sig = tcx.fn_sig(ctor_id)
.no_bound_vars()
.expect("LBR in ADT constructor signature");
- let sig = gcx.normalize_erasing_regions(param_env, sig);
+ let sig = tcx.normalize_erasing_regions(param_env, sig);
let (adt_def, substs) = match sig.output().sty {
ty::Adt(adt_def, substs) => (adt_def, substs),
_ => bug!("unexpected type for ADT ctor {:?}", sig.output())
};
- debug!("build_ctor: def_id={:?} sig={:?} fields={:?}", def_id, sig, fields);
+ debug!("build_ctor: ctor_id={:?} sig={:?}", ctor_id, sig);
let local_decls = local_decls_for_sig(&sig, span);
scope: OUTERMOST_SOURCE_SCOPE
};
- let variant_no = if adt_def.is_enum() {
- adt_def.variant_index_with_ctor_id(def_id)
+ let variant_index = if adt_def.is_enum() {
+ adt_def.variant_index_with_ctor_id(ctor_id)
} else {
VariantIdx::new(0)
};
- // return = ADT(arg0, arg1, ...); return
+ // Generate the following MIR:
+ //
+ // (return as Variant).field0 = arg0;
+ // (return as Variant).field1 = arg1;
+ //
+ // return;
+ debug!("build_ctor: variant_index={:?}", variant_index);
+
+ let statements = expand_aggregate(
+ Place::RETURN_PLACE,
+ adt_def
+ .variants[variant_index]
+ .fields
+ .iter()
+ .enumerate()
+ .map(|(idx, field_def)| (
+ Operand::Move(Place::Base(PlaceBase::Local(Local::new(idx + 1)))),
+ field_def.ty(tcx, substs),
+ )),
+ AggregateKind::Adt(adt_def, variant_index, substs, None, None),
+ source_info,
+ ).collect();
+
let start_block = BasicBlockData {
- statements: vec![Statement {
- source_info,
- kind: StatementKind::Assign(
- Place::RETURN_PLACE,
- box Rvalue::Aggregate(
- box AggregateKind::Adt(adt_def, variant_no, substs, None, None),
- (1..sig.inputs().len()+1).map(|i| {
- Operand::Move(Place::Base(PlaceBase::Local(Local::new(i))))
- }).collect()
- )
- )
- }],
+ statements,
terminator: Some(Terminator {
source_info,
kind: TerminatorKind::Return,
is_cleanup: false
};
- Body::new(
+ let body = Body::new(
IndexVec::from_elem_n(start_block, 1),
IndexVec::from_elem_n(
SourceScopeData { span: span, parent_scope: None }, 1
vec![],
span,
vec![],
- )
+ );
+
+ crate::util::dump_mir(
+ tcx,
+ None,
+ "mir_map",
+ &0,
+ crate::transform::MirSource::item(ctor_id),
+ &body,
+ |_, _| Ok(()),
+ );
+
+ tcx.arena.alloc(body)
}