Auto merge of #30301 - michaelwoerister:mir-to-metadata2, r=nikomatsakis
This PR makes `Mir` `RustcEncodable` and `RustcDecodable` and stores it in crate metadata for inlinable items. Some other things in here: - `mir::visit::Visitor` is extended to also visit `Literals`, `Spans` and `DefIds`. - It also adds `mir::visit::MutVisitor` which allows to mutate the visited `Mir` structure in place. - Some numbers on how big MIR is in metadata (total metadata size in bytes): | | w/ MIR | w/o MIR | Rel. Size | |----------------|-----------:|------------:|:---------:| | libcore | 17,695,473 | 14,263,377 | 124% | | liblibc | 411,440 | 404,382 | 102% | | libcollections | 4,537,975 | 3,526,933 | 129% | | libserialize | 2,574,769 | 2,060,798 | 125% | | libsyntax | 15,262,894 | 12,075,574 | 126% | | librustc | 16,984,537 | 13,692,168 | 124% | So, adding MIR to metadata makes it about 25% bigger. It could be worse, considering that it still uses the inefficient RBML encoding. Still, the question is whether we should put MIR emission behind a `-Z` flag.
This commit is contained in:
commit
7ce713961c
20 changed files with 567 additions and 63 deletions
|
@ -242,7 +242,7 @@ pub fn lookup_const_fn_by_id<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum ConstVal {
|
||||
Float(f64),
|
||||
Int(i64),
|
||||
|
|
|
@ -28,6 +28,7 @@ use middle::def;
|
|||
use middle::lang_items;
|
||||
use middle::ty::{self, Ty};
|
||||
use middle::def_id::{DefId, DefIndex};
|
||||
use mir::repr::Mir;
|
||||
use session::Session;
|
||||
use session::search_paths::PathKind;
|
||||
use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||
|
@ -100,6 +101,7 @@ pub enum InlinedItem {
|
|||
}
|
||||
|
||||
/// A borrowed version of `hir::InlinedItem`.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum InlinedItemRef<'a> {
|
||||
Item(&'a hir::Item),
|
||||
TraitItem(DefId, &'a hir::TraitItem),
|
||||
|
@ -216,6 +218,8 @@ pub trait CrateStore<'tcx> : Any {
|
|||
// misc. metadata
|
||||
fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId)
|
||||
-> FoundAst<'tcx>;
|
||||
fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
|
||||
-> Option<Mir<'tcx>>;
|
||||
// This is basically a 1-based range of ints, which is a little
|
||||
// silly - I may fix that.
|
||||
fn crates(&self) -> Vec<ast::CrateNum>;
|
||||
|
@ -235,6 +239,7 @@ pub trait CrateStore<'tcx> : Any {
|
|||
item_symbols: &RefCell<NodeMap<String>>,
|
||||
link_meta: &LinkMeta,
|
||||
reachable: &NodeSet,
|
||||
mir_map: &NodeMap<Mir<'tcx>>,
|
||||
krate: &hir::Crate) -> Vec<u8>;
|
||||
fn metadata_encoding_version(&self) -> &[u8];
|
||||
}
|
||||
|
@ -383,6 +388,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
|||
// misc. metadata
|
||||
fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId)
|
||||
-> FoundAst<'tcx> { unimplemented!() }
|
||||
fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
|
||||
-> Option<Mir<'tcx>> { unimplemented!() }
|
||||
|
||||
// This is basically a 1-based range of ints, which is a little
|
||||
// silly - I may fix that.
|
||||
fn crates(&self) -> Vec<ast::CrateNum> { vec![] }
|
||||
|
@ -404,6 +412,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
|||
item_symbols: &RefCell<NodeMap<String>>,
|
||||
link_meta: &LinkMeta,
|
||||
reachable: &NodeSet,
|
||||
mir_map: &NodeMap<Mir<'tcx>>,
|
||||
krate: &hir::Crate) -> Vec<u8> { vec![] }
|
||||
fn metadata_encoding_version(&self) -> &[u8] { unimplemented!() }
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
//! This module contains TypeVariants and its major components
|
||||
|
||||
use middle::cstore;
|
||||
use middle::def_id::DefId;
|
||||
use middle::region;
|
||||
use middle::subst::{self, Substs};
|
||||
|
@ -26,6 +27,8 @@ use syntax::abi;
|
|||
use syntax::ast::{self, Name};
|
||||
use syntax::parse::token::special_idents;
|
||||
|
||||
use serialize::{Decodable, Decoder};
|
||||
|
||||
use rustc_front::hir;
|
||||
|
||||
use self::FnOutput::*;
|
||||
|
@ -233,7 +236,7 @@ pub enum TypeVariants<'tcx> {
|
|||
/// closure C wind up influencing the decisions we ought to make for
|
||||
/// closure C (which would then require fixed point iteration to
|
||||
/// handle). Plus it fixes an ICE. :P
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct ClosureSubsts<'tcx> {
|
||||
/// Lifetime and type parameters from the enclosing function.
|
||||
/// These are separated out because trans wants to pass them around
|
||||
|
@ -246,6 +249,23 @@ pub struct ClosureSubsts<'tcx> {
|
|||
pub upvar_tys: Vec<Ty<'tcx>>
|
||||
}
|
||||
|
||||
impl<'tcx> Decodable for &'tcx ClosureSubsts<'tcx> {
|
||||
fn decode<S: Decoder>(s: &mut S) -> Result<&'tcx ClosureSubsts<'tcx>, S::Error> {
|
||||
let closure_substs = try! { Decodable::decode(s) };
|
||||
let dummy_def_id: DefId = unsafe { mem::zeroed() };
|
||||
|
||||
cstore::tls::with_decoding_context(s, |dcx, _| {
|
||||
// Intern the value
|
||||
let ty = dcx.tcx().mk_closure_from_closure_substs(dummy_def_id,
|
||||
Box::new(closure_substs));
|
||||
match ty.sty {
|
||||
TyClosure(_, ref closure_substs) => Ok(&**closure_substs),
|
||||
_ => unreachable!()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct TraitTy<'tcx> {
|
||||
pub principal: ty::PolyTraitRef<'tcx>,
|
||||
|
@ -434,7 +454,7 @@ pub struct ClosureTy<'tcx> {
|
|||
pub sig: PolyFnSig<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum FnOutput<'tcx> {
|
||||
FnConverging(Ty<'tcx>),
|
||||
FnDiverging
|
||||
|
@ -632,7 +652,7 @@ pub struct DebruijnIndex {
|
|||
///
|
||||
/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
|
||||
/// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Copy)]
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)]
|
||||
pub enum Region {
|
||||
// Region bound in a type or fn declaration which will be
|
||||
// substituted 'early' -- that is, at the same time when type
|
||||
|
@ -701,7 +721,7 @@ pub struct RegionVid {
|
|||
pub index: u32
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct SkolemizedRegionVid {
|
||||
pub index: u32
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use middle::def_id::DefId;
|
|||
use middle::subst::Substs;
|
||||
use middle::ty::{AdtDef, ClosureSubsts, FnOutput, Region, Ty};
|
||||
use rustc_back::slice;
|
||||
use rustc_data_structures::tuple_slice::TupleSlice;
|
||||
use rustc_front::hir::InlineAsm;
|
||||
use syntax::ast::Name;
|
||||
use syntax::codemap::Span;
|
||||
|
@ -20,6 +21,7 @@ use std::fmt::{Debug, Formatter, Error};
|
|||
use std::u32;
|
||||
|
||||
/// Lowered representation of a single function.
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct Mir<'tcx> {
|
||||
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
|
||||
/// that indexes into this vector.
|
||||
|
@ -70,13 +72,13 @@ impl<'tcx> Mir<'tcx> {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// Mutability and borrow kinds
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum Mutability {
|
||||
Mut,
|
||||
Not,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum BorrowKind {
|
||||
/// Data must be immutable and is aliasable.
|
||||
Shared,
|
||||
|
@ -127,6 +129,7 @@ pub enum BorrowKind {
|
|||
|
||||
// A "variable" is a binding declared by the user as part of the fn
|
||||
// decl, a let, etc.
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct VarDecl<'tcx> {
|
||||
pub mutability: Mutability,
|
||||
pub name: Name,
|
||||
|
@ -135,6 +138,7 @@ pub struct VarDecl<'tcx> {
|
|||
|
||||
// A "temp" is a temporary that we place on the stack. They are
|
||||
// anonymous, always mutable, and have only a type.
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct TempDecl<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
}
|
||||
|
@ -150,6 +154,7 @@ pub struct TempDecl<'tcx> {
|
|||
//
|
||||
// there is only one argument, of type `(i32, u32)`, but two bindings
|
||||
// (`x` and `y`).
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct ArgDecl<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
}
|
||||
|
@ -161,7 +166,7 @@ pub struct ArgDecl<'tcx> {
|
|||
/// list of the `Mir`.
|
||||
///
|
||||
/// (We use a `u32` internally just to save memory.)
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub struct BasicBlock(u32);
|
||||
|
||||
impl BasicBlock {
|
||||
|
@ -185,12 +190,13 @@ impl Debug for BasicBlock {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// BasicBlock and Terminator
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct BasicBlockData<'tcx> {
|
||||
pub statements: Vec<Statement<'tcx>>,
|
||||
pub terminator: Terminator<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub enum Terminator<'tcx> {
|
||||
/// block should have one successor in the graph; we jump there
|
||||
Goto {
|
||||
|
@ -206,7 +212,7 @@ pub enum Terminator<'tcx> {
|
|||
/// jump to branch 0 if this lvalue evaluates to true
|
||||
If {
|
||||
cond: Operand<'tcx>,
|
||||
targets: [BasicBlock; 2],
|
||||
targets: (BasicBlock, BasicBlock),
|
||||
},
|
||||
|
||||
/// lvalue evaluates to some enum; jump depending on the branch
|
||||
|
@ -254,7 +260,7 @@ pub enum Terminator<'tcx> {
|
|||
/// unwinding.
|
||||
Call {
|
||||
data: CallData<'tcx>,
|
||||
targets: [BasicBlock; 2],
|
||||
targets: (BasicBlock, BasicBlock),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -264,12 +270,12 @@ impl<'tcx> Terminator<'tcx> {
|
|||
match *self {
|
||||
Goto { target: ref b } => slice::ref_slice(b),
|
||||
Panic { target: ref b } => slice::ref_slice(b),
|
||||
If { cond: _, targets: ref b } => b,
|
||||
If { cond: _, targets: ref b } => b.as_slice(),
|
||||
Switch { targets: ref b, .. } => b,
|
||||
SwitchInt { targets: ref b, .. } => b,
|
||||
Diverge => &[],
|
||||
Return => &[],
|
||||
Call { data: _, targets: ref b } => b,
|
||||
Call { data: _, targets: ref b } => b.as_slice(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,17 +284,17 @@ impl<'tcx> Terminator<'tcx> {
|
|||
match *self {
|
||||
Goto { target: ref mut b } => slice::mut_ref_slice(b),
|
||||
Panic { target: ref mut b } => slice::mut_ref_slice(b),
|
||||
If { cond: _, targets: ref mut b } => b,
|
||||
If { cond: _, targets: ref mut b } => b.as_mut_slice(),
|
||||
Switch { targets: ref mut b, .. } => b,
|
||||
SwitchInt { targets: ref mut b, .. } => b,
|
||||
Diverge => &mut [],
|
||||
Return => &mut [],
|
||||
Call { data: _, targets: ref mut b } => b,
|
||||
Call { data: _, targets: ref mut b } => b.as_mut_slice(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct CallData<'tcx> {
|
||||
/// where the return value is written to
|
||||
pub destination: Lvalue<'tcx>,
|
||||
|
@ -345,18 +351,19 @@ impl<'tcx> Debug for Terminator<'tcx> {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// Statements
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct Statement<'tcx> {
|
||||
pub span: Span,
|
||||
pub kind: StatementKind<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum StatementKind<'tcx> {
|
||||
Assign(Lvalue<'tcx>, Rvalue<'tcx>),
|
||||
Drop(DropKind, Lvalue<'tcx>),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum DropKind {
|
||||
Free, // free a partially constructed box, should go away eventually
|
||||
Deep
|
||||
|
@ -377,7 +384,7 @@ impl<'tcx> Debug for Statement<'tcx> {
|
|||
|
||||
/// A path to a value; something that can be evaluated without
|
||||
/// changing or disturbing program state.
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
|
||||
pub enum Lvalue<'tcx> {
|
||||
/// local variable declared by the user
|
||||
Var(u32),
|
||||
|
@ -403,13 +410,13 @@ pub enum Lvalue<'tcx> {
|
|||
/// or `*B` or `B[index]`. Note that it is parameterized because it is
|
||||
/// shared between `Constant` and `Lvalue`. See the aliases
|
||||
/// `LvalueProjection` etc below.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||
pub struct Projection<'tcx, B, V> {
|
||||
pub base: B,
|
||||
pub elem: ProjectionElem<'tcx, V>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||
pub enum ProjectionElem<'tcx, V> {
|
||||
Deref,
|
||||
Field(Field),
|
||||
|
@ -447,7 +454,7 @@ pub type LvalueElem<'tcx> =
|
|||
ProjectionElem<'tcx,Operand<'tcx>>;
|
||||
|
||||
/// Index into the list of fields found in a `VariantDef`
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct Field(u32);
|
||||
|
||||
impl Field {
|
||||
|
@ -523,7 +530,7 @@ impl<'tcx> Debug for Lvalue<'tcx> {
|
|||
// lvalue). They are intentionally limited to prevent rvalues from
|
||||
// being nested in one another.
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
|
||||
pub enum Operand<'tcx> {
|
||||
Consume(Lvalue<'tcx>),
|
||||
Constant(Constant<'tcx>),
|
||||
|
@ -542,7 +549,7 @@ impl<'tcx> Debug for Operand<'tcx> {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// Rvalues
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
pub enum Rvalue<'tcx> {
|
||||
// x (either a move or copy, depending on type of x)
|
||||
Use(Operand<'tcx>),
|
||||
|
@ -583,10 +590,10 @@ pub enum Rvalue<'tcx> {
|
|||
from_end: usize,
|
||||
},
|
||||
|
||||
InlineAsm(&'tcx InlineAsm),
|
||||
InlineAsm(InlineAsm),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum CastKind {
|
||||
Misc,
|
||||
|
||||
|
@ -604,7 +611,7 @@ pub enum CastKind {
|
|||
Unsize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum AggregateKind<'tcx> {
|
||||
Vec,
|
||||
Tuple,
|
||||
|
@ -612,7 +619,7 @@ pub enum AggregateKind<'tcx> {
|
|||
Closure(DefId, &'tcx ClosureSubsts<'tcx>),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum BinOp {
|
||||
/// The `+` operator (addition)
|
||||
Add,
|
||||
|
@ -648,7 +655,7 @@ pub enum BinOp {
|
|||
Gt,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum UnOp {
|
||||
/// The `!` operator for logical inversion
|
||||
Not,
|
||||
|
@ -684,14 +691,14 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
|||
// this does not necessarily mean that they are "==" in Rust -- in
|
||||
// particular one must be wary of `NaN`!
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||
pub struct Constant<'tcx> {
|
||||
pub span: Span,
|
||||
pub ty: Ty<'tcx>,
|
||||
pub literal: Literal<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||
pub enum Literal<'tcx> {
|
||||
Item {
|
||||
def_id: DefId,
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use middle::def_id::DefId;
|
||||
use middle::ty::Region;
|
||||
use mir::repr::*;
|
||||
use rustc_data_structures::tuple_slice::TupleSlice;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
pub trait Visitor<'tcx> {
|
||||
// Override these, and call `self.super_xxx` to revert back to the
|
||||
|
@ -55,6 +58,18 @@ pub trait Visitor<'tcx> {
|
|||
self.super_constant(constant);
|
||||
}
|
||||
|
||||
fn visit_literal(&mut self, literal: &Literal<'tcx>) {
|
||||
self.super_literal(literal);
|
||||
}
|
||||
|
||||
fn visit_def_id(&mut self, def_id: DefId) {
|
||||
self.super_def_id(def_id);
|
||||
}
|
||||
|
||||
fn visit_span(&mut self, span: Span) {
|
||||
self.super_span(span);
|
||||
}
|
||||
|
||||
// The `super_xxx` methods comprise the default behavior and are
|
||||
// not meant to be overidden.
|
||||
|
||||
|
@ -73,6 +88,8 @@ pub trait Visitor<'tcx> {
|
|||
}
|
||||
|
||||
fn super_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) {
|
||||
self.visit_span(statement.span);
|
||||
|
||||
match statement.kind {
|
||||
StatementKind::Assign(ref lvalue, ref rvalue) => {
|
||||
self.visit_assign(block, lvalue, rvalue);
|
||||
|
@ -97,7 +114,7 @@ pub trait Visitor<'tcx> {
|
|||
|
||||
Terminator::If { ref cond, ref targets } => {
|
||||
self.visit_operand(cond);
|
||||
for &target in &targets[..] {
|
||||
for &target in targets.as_slice() {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +143,7 @@ pub trait Visitor<'tcx> {
|
|||
for arg in &data.args {
|
||||
self.visit_operand(arg);
|
||||
}
|
||||
for &target in &targets[..] {
|
||||
for &target in targets.as_slice() {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +234,26 @@ pub trait Visitor<'tcx> {
|
|||
fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) {
|
||||
}
|
||||
|
||||
fn super_constant(&mut self, _constant: &Constant<'tcx>) {
|
||||
fn super_constant(&mut self, constant: &Constant<'tcx>) {
|
||||
self.visit_span(constant.span);
|
||||
self.visit_literal(&constant.literal);
|
||||
}
|
||||
|
||||
fn super_literal(&mut self, literal: &Literal<'tcx>) {
|
||||
match *literal {
|
||||
Literal::Item { def_id, .. } => {
|
||||
self.visit_def_id(def_id);
|
||||
},
|
||||
Literal::Value { .. } => {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn super_def_id(&mut self, _def_id: DefId) {
|
||||
}
|
||||
|
||||
fn super_span(&mut self, _span: Span) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,3 +280,277 @@ pub enum LvalueContext {
|
|||
// Consumed as part of an operand
|
||||
Consume,
|
||||
}
|
||||
|
||||
pub trait MutVisitor<'tcx> {
|
||||
// Override these, and call `self.super_xxx` to revert back to the
|
||||
// default behavior.
|
||||
|
||||
fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
|
||||
self.super_mir(mir);
|
||||
}
|
||||
|
||||
fn visit_basic_block_data(&mut self,
|
||||
block: BasicBlock,
|
||||
data: &mut BasicBlockData<'tcx>) {
|
||||
self.super_basic_block_data(block, data);
|
||||
}
|
||||
|
||||
fn visit_statement(&mut self,
|
||||
block: BasicBlock,
|
||||
statement: &mut Statement<'tcx>) {
|
||||
self.super_statement(block, statement);
|
||||
}
|
||||
|
||||
fn visit_assign(&mut self,
|
||||
block: BasicBlock,
|
||||
lvalue: &mut Lvalue<'tcx>,
|
||||
rvalue: &mut Rvalue<'tcx>) {
|
||||
self.super_assign(block, lvalue, rvalue);
|
||||
}
|
||||
|
||||
fn visit_terminator(&mut self,
|
||||
block: BasicBlock,
|
||||
terminator: &mut Terminator<'tcx>) {
|
||||
self.super_terminator(block, terminator);
|
||||
}
|
||||
|
||||
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
|
||||
self.super_rvalue(rvalue);
|
||||
}
|
||||
|
||||
fn visit_operand(&mut self, operand: &mut Operand<'tcx>) {
|
||||
self.super_operand(operand);
|
||||
}
|
||||
|
||||
fn visit_lvalue(&mut self,
|
||||
lvalue: &mut Lvalue<'tcx>,
|
||||
context: LvalueContext) {
|
||||
self.super_lvalue(lvalue, context);
|
||||
}
|
||||
|
||||
fn visit_branch(&mut self, source: BasicBlock, target: BasicBlock) {
|
||||
self.super_branch(source, target);
|
||||
}
|
||||
|
||||
fn visit_constant(&mut self, constant: &mut Constant<'tcx>) {
|
||||
self.super_constant(constant);
|
||||
}
|
||||
|
||||
fn visit_literal(&mut self, literal: &mut Literal<'tcx>) {
|
||||
self.super_literal(literal);
|
||||
}
|
||||
|
||||
fn visit_def_id(&mut self, def_id: &mut DefId) {
|
||||
self.super_def_id(def_id);
|
||||
}
|
||||
|
||||
fn visit_span(&mut self, span: &mut Span) {
|
||||
self.super_span(span);
|
||||
}
|
||||
|
||||
// The `super_xxx` methods comprise the default behavior and are
|
||||
// not meant to be overidden.
|
||||
|
||||
fn super_mir(&mut self, mir: &mut Mir<'tcx>) {
|
||||
for block in mir.all_basic_blocks() {
|
||||
let data = mir.basic_block_data_mut(block);
|
||||
self.visit_basic_block_data(block, data);
|
||||
}
|
||||
}
|
||||
|
||||
fn super_basic_block_data(&mut self,
|
||||
block: BasicBlock,
|
||||
data: &mut BasicBlockData<'tcx>) {
|
||||
for statement in &mut data.statements {
|
||||
self.visit_statement(block, statement);
|
||||
}
|
||||
self.visit_terminator(block, &mut data.terminator);
|
||||
}
|
||||
|
||||
fn super_statement(&mut self,
|
||||
block: BasicBlock,
|
||||
statement: &mut Statement<'tcx>) {
|
||||
self.visit_span(&mut statement.span);
|
||||
|
||||
match statement.kind {
|
||||
StatementKind::Assign(ref mut lvalue, ref mut rvalue) => {
|
||||
self.visit_assign(block, lvalue, rvalue);
|
||||
}
|
||||
StatementKind::Drop(_, ref mut lvalue) => {
|
||||
self.visit_lvalue(lvalue, LvalueContext::Drop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn super_assign(&mut self,
|
||||
_block: BasicBlock,
|
||||
lvalue: &mut Lvalue<'tcx>,
|
||||
rvalue: &mut Rvalue<'tcx>) {
|
||||
self.visit_lvalue(lvalue, LvalueContext::Store);
|
||||
self.visit_rvalue(rvalue);
|
||||
}
|
||||
|
||||
fn super_terminator(&mut self,
|
||||
block: BasicBlock,
|
||||
terminator: &mut Terminator<'tcx>) {
|
||||
match *terminator {
|
||||
Terminator::Goto { target } |
|
||||
Terminator::Panic { target } => {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
|
||||
Terminator::If { ref mut cond, ref mut targets } => {
|
||||
self.visit_operand(cond);
|
||||
for &target in targets.as_slice() {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
}
|
||||
|
||||
Terminator::Switch { ref mut discr, adt_def: _, ref targets } => {
|
||||
self.visit_lvalue(discr, LvalueContext::Inspect);
|
||||
for &target in targets {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
}
|
||||
|
||||
Terminator::SwitchInt { ref mut discr, switch_ty: _, values: _, ref targets } => {
|
||||
self.visit_lvalue(discr, LvalueContext::Inspect);
|
||||
for &target in targets {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
}
|
||||
|
||||
Terminator::Diverge |
|
||||
Terminator::Return => {
|
||||
}
|
||||
|
||||
Terminator::Call { ref mut data, ref mut targets } => {
|
||||
self.visit_lvalue(&mut data.destination, LvalueContext::Store);
|
||||
self.visit_operand(&mut data.func);
|
||||
for arg in &mut data.args {
|
||||
self.visit_operand(arg);
|
||||
}
|
||||
for &target in targets.as_slice() {
|
||||
self.visit_branch(block, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn super_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
|
||||
match *rvalue {
|
||||
Rvalue::Use(ref mut operand) => {
|
||||
self.visit_operand(operand);
|
||||
}
|
||||
|
||||
Rvalue::Repeat(ref mut value, ref mut len) => {
|
||||
self.visit_operand(value);
|
||||
self.visit_constant(len);
|
||||
}
|
||||
|
||||
Rvalue::Ref(r, bk, ref mut path) => {
|
||||
self.visit_lvalue(path, LvalueContext::Borrow {
|
||||
region: r,
|
||||
kind: bk
|
||||
});
|
||||
}
|
||||
|
||||
Rvalue::Len(ref mut path) => {
|
||||
self.visit_lvalue(path, LvalueContext::Inspect);
|
||||
}
|
||||
|
||||
Rvalue::Cast(_, ref mut operand, _) => {
|
||||
self.visit_operand(operand);
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(_, ref mut lhs, ref mut rhs) => {
|
||||
self.visit_operand(lhs);
|
||||
self.visit_operand(rhs);
|
||||
}
|
||||
|
||||
Rvalue::UnaryOp(_, ref mut op) => {
|
||||
self.visit_operand(op);
|
||||
}
|
||||
|
||||
Rvalue::Box(_) => {
|
||||
}
|
||||
|
||||
Rvalue::Aggregate(ref mut kind, ref mut operands) => {
|
||||
match *kind {
|
||||
AggregateKind::Closure(ref mut def_id, _) => {
|
||||
self.visit_def_id(def_id);
|
||||
}
|
||||
_ => { /* nothing to do */ }
|
||||
}
|
||||
|
||||
for operand in &mut operands[..] {
|
||||
self.visit_operand(operand);
|
||||
}
|
||||
}
|
||||
|
||||
Rvalue::Slice { ref mut input, from_start, from_end } => {
|
||||
self.visit_lvalue(input, LvalueContext::Slice {
|
||||
from_start: from_start,
|
||||
from_end: from_end,
|
||||
});
|
||||
}
|
||||
|
||||
Rvalue::InlineAsm(_) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn super_operand(&mut self, operand: &mut Operand<'tcx>) {
|
||||
match *operand {
|
||||
Operand::Consume(ref mut lvalue) => {
|
||||
self.visit_lvalue(lvalue, LvalueContext::Consume);
|
||||
}
|
||||
Operand::Constant(ref mut constant) => {
|
||||
self.visit_constant(constant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn super_lvalue(&mut self,
|
||||
lvalue: &mut Lvalue<'tcx>,
|
||||
_context: LvalueContext) {
|
||||
match *lvalue {
|
||||
Lvalue::Var(_) |
|
||||
Lvalue::Temp(_) |
|
||||
Lvalue::Arg(_) |
|
||||
Lvalue::ReturnPointer => {
|
||||
}
|
||||
Lvalue::Static(ref mut def_id) => {
|
||||
self.visit_def_id(def_id);
|
||||
}
|
||||
Lvalue::Projection(ref mut proj) => {
|
||||
self.visit_lvalue(&mut proj.base, LvalueContext::Projection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) {
|
||||
}
|
||||
|
||||
fn super_constant(&mut self, constant: &mut Constant<'tcx>) {
|
||||
self.visit_span(&mut constant.span);
|
||||
self.visit_literal(&mut constant.literal);
|
||||
}
|
||||
|
||||
fn super_literal(&mut self, literal: &mut Literal<'tcx>) {
|
||||
match *literal {
|
||||
Literal::Item { ref mut def_id, .. } => {
|
||||
self.visit_def_id(def_id);
|
||||
},
|
||||
Literal::Value { .. } => {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn super_def_id(&mut self, _def_id: &mut DefId) {
|
||||
}
|
||||
|
||||
fn super_span(&mut self, _span: &mut Span) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ pub mod snapshot_vec;
|
|||
pub mod transitive_relation;
|
||||
pub mod unify;
|
||||
pub mod fnv;
|
||||
pub mod tuple_slice;
|
||||
|
||||
// See comments in src/librustc/lib.rs
|
||||
#[doc(hidden)]
|
||||
|
|
60
src/librustc_data_structures/tuple_slice.rs
Normal file
60
src/librustc_data_structures/tuple_slice.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::slice;
|
||||
|
||||
/// Allows to view uniform tuples as slices
|
||||
pub trait TupleSlice<T> {
|
||||
fn as_slice(&self) -> &[T];
|
||||
fn as_mut_slice(&mut self) -> &mut [T];
|
||||
}
|
||||
|
||||
macro_rules! impl_tuple_slice {
|
||||
($tuple_type:ty, $size:expr) => {
|
||||
impl<T> TupleSlice<T> for $tuple_type {
|
||||
fn as_slice(&self) -> &[T] {
|
||||
unsafe {
|
||||
let ptr = &self.0 as *const T;
|
||||
slice::from_raw_parts(ptr, $size)
|
||||
}
|
||||
}
|
||||
|
||||
fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
unsafe {
|
||||
let ptr = &mut self.0 as *mut T;
|
||||
slice::from_raw_parts_mut(ptr, $size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_tuple_slice!((T,T), 2);
|
||||
impl_tuple_slice!((T,T,T), 3);
|
||||
impl_tuple_slice!((T,T,T,T), 4);
|
||||
impl_tuple_slice!((T,T,T,T,T), 5);
|
||||
impl_tuple_slice!((T,T,T,T,T,T), 6);
|
||||
impl_tuple_slice!((T,T,T,T,T,T,T), 7);
|
||||
impl_tuple_slice!((T,T,T,T,T,T,T,T), 8);
|
||||
|
||||
#[test]
|
||||
fn test_sliced_tuples() {
|
||||
let t2 = (100i32, 101i32);
|
||||
assert_eq!(t2.as_slice(), &[100i32, 101i32]);
|
||||
|
||||
let t3 = (102i32, 103i32, 104i32);
|
||||
assert_eq!(t3.as_slice(), &[102i32, 103i32, 104i32]);
|
||||
|
||||
let t4 = (105i32, 106i32, 107i32, 108i32);
|
||||
assert_eq!(t4.as_slice(), &[105i32, 106i32, 107i32, 108i32]);
|
||||
|
||||
let t5 = (109i32, 110i32, 111i32, 112i32, 113i32);
|
||||
assert_eq!(t5.as_slice(), &[109i32, 110i32, 111i32, 112i32, 113i32]);
|
||||
}
|
|
@ -120,7 +120,8 @@ enum_from_u32! {
|
|||
|
||||
tag_tree = 0x51,
|
||||
|
||||
// GAP 0x52
|
||||
tag_mir = 0x52,
|
||||
|
||||
tag_table = 0x53,
|
||||
// GAP 0x54, 0x55
|
||||
tag_table_def = 0x56,
|
||||
|
|
|
@ -22,6 +22,7 @@ use middle::ty::{self, Ty};
|
|||
use middle::def_id::{DefId, DefIndex};
|
||||
|
||||
use rustc::front::map as hir_map;
|
||||
use rustc::mir::repr::Mir;
|
||||
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
@ -421,6 +422,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
|||
decoder::maybe_get_item_ast(&*cdata, tcx, def.index, decode_inlined_item)
|
||||
}
|
||||
|
||||
fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
|
||||
-> Option<Mir<'tcx>> {
|
||||
let cdata = self.get_crate_data(def.krate);
|
||||
decoder::maybe_get_item_mir(&*cdata, tcx, def.index)
|
||||
}
|
||||
|
||||
fn crates(&self) -> Vec<ast::CrateNum>
|
||||
{
|
||||
let mut result = vec![];
|
||||
|
@ -473,6 +480,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
|||
item_symbols: &RefCell<NodeMap<String>>,
|
||||
link_meta: &LinkMeta,
|
||||
reachable: &NodeSet,
|
||||
mir_map: &NodeMap<Mir<'tcx>>,
|
||||
krate: &hir::Crate) -> Vec<u8>
|
||||
{
|
||||
let encode_inlined_item: encoder::EncodeInlinedItem =
|
||||
|
@ -486,7 +494,8 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
|||
link_meta: link_meta,
|
||||
cstore: self,
|
||||
encode_inlined_item: encode_inlined_item,
|
||||
reachable: reachable
|
||||
reachable: reachable,
|
||||
mir_map: mir_map,
|
||||
};
|
||||
encoder::encode_metadata(encode_params, krate)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ use cstore::{self, crate_metadata};
|
|||
use common::*;
|
||||
use encoder::def_to_u64;
|
||||
use index;
|
||||
use tls_context;
|
||||
use tydecode::TyDecoder;
|
||||
|
||||
use rustc::back::svh::Svh;
|
||||
|
@ -26,7 +27,7 @@ use rustc::util::nodemap::FnvHashMap;
|
|||
use rustc_front::hir;
|
||||
|
||||
use middle::cstore::{LOCAL_CRATE, FoundAst, InlinedItem, LinkagePreference};
|
||||
use middle::cstore::{DefLike, DlDef, DlField, DlImpl};
|
||||
use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls};
|
||||
use middle::def;
|
||||
use middle::def_id::{DefId, DefIndex};
|
||||
use middle::lang_items;
|
||||
|
@ -34,6 +35,9 @@ use middle::subst;
|
|||
use middle::ty::{ImplContainer, TraitContainer};
|
||||
use middle::ty::{self, RegionEscape, Ty};
|
||||
|
||||
use rustc::mir;
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
|
@ -48,7 +52,7 @@ use syntax::parse::token::{IdentInterner, special_idents};
|
|||
use syntax::parse::token;
|
||||
use syntax::ast;
|
||||
use syntax::abi;
|
||||
use syntax::codemap;
|
||||
use syntax::codemap::{self, Span};
|
||||
use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
|
||||
|
@ -783,6 +787,56 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: DefIndex,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn maybe_get_item_mir<'tcx>(cdata: Cmd,
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
id: DefIndex)
|
||||
-> Option<mir::repr::Mir<'tcx>> {
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
|
||||
return reader::maybe_get_doc(item_doc, tag_mir as usize).map(|mir_doc| {
|
||||
let dcx = tls_context::DecodingContext {
|
||||
crate_metadata: cdata,
|
||||
tcx: tcx,
|
||||
};
|
||||
let mut decoder = reader::Decoder::new(mir_doc);
|
||||
|
||||
let mut mir = tls::enter_decoding_context(&dcx, &mut decoder, |_, decoder| {
|
||||
Decodable::decode(decoder).unwrap()
|
||||
});
|
||||
|
||||
let mut def_id_and_span_translator = MirDefIdAndSpanTranslator {
|
||||
crate_metadata: cdata,
|
||||
codemap: tcx.sess.codemap(),
|
||||
last_filemap_index_hint: Cell::new(0),
|
||||
};
|
||||
|
||||
def_id_and_span_translator.visit_mir(&mut mir);
|
||||
|
||||
mir
|
||||
});
|
||||
|
||||
struct MirDefIdAndSpanTranslator<'cdata, 'codemap> {
|
||||
crate_metadata: Cmd<'cdata>,
|
||||
codemap: &'codemap codemap::CodeMap,
|
||||
last_filemap_index_hint: Cell<usize>
|
||||
}
|
||||
|
||||
impl<'v, 'cdata, 'codemap> mir::visit::MutVisitor<'v>
|
||||
for MirDefIdAndSpanTranslator<'cdata, 'codemap>
|
||||
{
|
||||
fn visit_def_id(&mut self, def_id: &mut DefId) {
|
||||
*def_id = translate_def_id(self.crate_metadata, *def_id);
|
||||
}
|
||||
|
||||
fn visit_span(&mut self, span: &mut Span) {
|
||||
*span = translate_span(self.crate_metadata,
|
||||
self.codemap,
|
||||
&self.last_filemap_index_hint,
|
||||
*span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
|
||||
fn get_mutability(ch: u8) -> hir::Mutability {
|
||||
match ch as char {
|
||||
|
|
|
@ -30,6 +30,7 @@ use middle::ty::{self, Ty};
|
|||
use rustc::back::svh::Svh;
|
||||
use rustc::front::map::{LinkedPath, PathElem, PathElems};
|
||||
use rustc::front::map as ast_map;
|
||||
use rustc::mir::repr::Mir;
|
||||
use rustc::session::config;
|
||||
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||
|
||||
|
@ -64,6 +65,7 @@ pub struct EncodeParams<'a, 'tcx: 'a> {
|
|||
pub cstore: &'a cstore::CStore,
|
||||
pub encode_inlined_item: EncodeInlinedItem<'a>,
|
||||
pub reachable: &'a NodeSet,
|
||||
pub mir_map: &'a NodeMap<Mir<'tcx>>,
|
||||
}
|
||||
|
||||
pub struct EncodeContext<'a, 'tcx: 'a> {
|
||||
|
@ -76,6 +78,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
|
|||
pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
|
||||
pub type_abbrevs: tyencode::abbrev_map<'tcx>,
|
||||
pub reachable: &'a NodeSet,
|
||||
pub mir_map: &'a NodeMap<Mir<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EncodeContext<'a,'tcx> {
|
||||
|
@ -840,7 +843,24 @@ fn encode_inlined_item(ecx: &EncodeContext,
|
|||
ii: InlinedItemRef) {
|
||||
let mut eii = ecx.encode_inlined_item.borrow_mut();
|
||||
let eii: &mut EncodeInlinedItem = &mut *eii;
|
||||
eii(ecx, rbml_w, ii)
|
||||
eii(ecx, rbml_w, ii);
|
||||
|
||||
encode_mir(ecx, rbml_w, ii);
|
||||
}
|
||||
|
||||
fn encode_mir(ecx: &EncodeContext, rbml_w: &mut Encoder, ii: InlinedItemRef) {
|
||||
let id = match ii {
|
||||
InlinedItemRef::Item(item) => item.id,
|
||||
InlinedItemRef::TraitItem(_, trait_item) => trait_item.id,
|
||||
InlinedItemRef::ImplItem(_, impl_item) => impl_item.id,
|
||||
InlinedItemRef::Foreign(foreign_item) => foreign_item.id
|
||||
};
|
||||
|
||||
if let Some(mir) = ecx.mir_map.get(&id) {
|
||||
rbml_w.start_tag(tag_mir as usize);
|
||||
Encodable::encode(mir, rbml_w).unwrap();
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
}
|
||||
|
||||
const FN_FAMILY: char = 'f';
|
||||
|
@ -1884,6 +1904,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
|
|||
encode_inlined_item,
|
||||
link_meta,
|
||||
reachable,
|
||||
mir_map,
|
||||
..
|
||||
} = parms;
|
||||
let ecx = EncodeContext {
|
||||
|
@ -1896,6 +1917,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
|
|||
encode_inlined_item: RefCell::new(encode_inlined_item),
|
||||
type_abbrevs: RefCell::new(FnvHashMap()),
|
||||
reachable: reachable,
|
||||
mir_map: mir_map,
|
||||
};
|
||||
|
||||
let mut wr = Cursor::new(Vec::new());
|
||||
|
|
|
@ -69,7 +69,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
this.cfg.terminate(block,
|
||||
Terminator::If {
|
||||
cond: Operand::Consume(lt),
|
||||
targets: [success, failure],
|
||||
targets: (success, failure),
|
||||
});
|
||||
this.panic(failure);
|
||||
success.and(slice.index(idx))
|
||||
|
|
|
@ -40,7 +40,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
this.in_scope(extent, block, |this| this.as_rvalue(block, value))
|
||||
}
|
||||
ExprKind::InlineAsm { asm } => {
|
||||
block.and(Rvalue::InlineAsm(asm))
|
||||
block.and(Rvalue::InlineAsm(asm.clone()))
|
||||
}
|
||||
ExprKind::Repeat { value, count } => {
|
||||
let value_operand = unpack!(block = this.as_operand(block, value));
|
||||
|
|
|
@ -53,7 +53,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
let mut else_block = this.cfg.start_new_block();
|
||||
this.cfg.terminate(block, Terminator::If {
|
||||
cond: operand,
|
||||
targets: [then_block, else_block]
|
||||
targets: (then_block, else_block)
|
||||
});
|
||||
|
||||
unpack!(then_block = this.into(destination, then_block, then_expr));
|
||||
|
@ -84,15 +84,15 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
|
||||
let lhs = unpack!(block = this.as_operand(block, lhs));
|
||||
let blocks = match op {
|
||||
LogicalOp::And => [else_block, false_block],
|
||||
LogicalOp::Or => [true_block, else_block],
|
||||
LogicalOp::And => (else_block, false_block),
|
||||
LogicalOp::Or => (true_block, else_block),
|
||||
};
|
||||
this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });
|
||||
|
||||
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
|
||||
this.cfg.terminate(else_block, Terminator::If {
|
||||
cond: rhs,
|
||||
targets: [true_block, false_block]
|
||||
targets: (true_block, false_block)
|
||||
});
|
||||
|
||||
this.cfg.push_assign_constant(
|
||||
|
@ -149,7 +149,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
this.cfg.terminate(loop_block_end,
|
||||
Terminator::If {
|
||||
cond: cond,
|
||||
targets: [body_block, exit_block]
|
||||
targets: (body_block, exit_block)
|
||||
});
|
||||
} else {
|
||||
body_block = loop_block;
|
||||
|
@ -225,7 +225,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
func: fun,
|
||||
args: args,
|
||||
},
|
||||
targets: [success, panic],
|
||||
targets: (success, panic),
|
||||
});
|
||||
success.unit()
|
||||
}
|
||||
|
|
|
@ -555,7 +555,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
let cond = unpack!(block = self.as_operand(block, guard));
|
||||
let otherwise = self.cfg.start_new_block();
|
||||
self.cfg.terminate(block, Terminator::If { cond: cond,
|
||||
targets: [arm_block, otherwise]});
|
||||
targets: (arm_block, otherwise)});
|
||||
Some(otherwise)
|
||||
} else {
|
||||
self.cfg.terminate(block, Terminator::Goto { target: arm_block });
|
||||
|
|
|
@ -232,7 +232,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
self.cfg.start_new_block()];
|
||||
self.cfg.terminate(block, Terminator::If {
|
||||
cond: Operand::Consume(result),
|
||||
targets: [target_blocks[0], target_blocks[1]]
|
||||
targets: (target_blocks[0], target_blocks[1])
|
||||
});
|
||||
|
||||
target_blocks
|
||||
|
@ -252,7 +252,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
let bool_ty = self.hir.bool_ty();
|
||||
let eq_result = self.temp(bool_ty);
|
||||
let func = self.item_ref_operand(span, item_ref);
|
||||
let call_blocks = [self.cfg.start_new_block(), self.diverge_cleanup()];
|
||||
let call_blocks = (self.cfg.start_new_block(), self.diverge_cleanup());
|
||||
self.cfg.terminate(block,
|
||||
Terminator::Call {
|
||||
data: CallData {
|
||||
|
@ -264,10 +264,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
});
|
||||
|
||||
// check the result
|
||||
self.cfg.terminate(call_blocks[0],
|
||||
self.cfg.terminate(call_blocks.0,
|
||||
Terminator::If {
|
||||
cond: Operand::Consume(eq_result),
|
||||
targets: [target_blocks[0], target_blocks[1]],
|
||||
targets: (target_blocks[0], target_blocks[1]),
|
||||
});
|
||||
|
||||
target_blocks
|
||||
|
|
|
@ -96,9 +96,9 @@ impl SimplifyCfg {
|
|||
mem::swap(&mut terminator, &mut mir.basic_block_data_mut(bb).terminator);
|
||||
|
||||
mir.basic_block_data_mut(bb).terminator = match terminator {
|
||||
Terminator::If { ref targets, .. } if targets[0] == targets[1] => {
|
||||
Terminator::If { ref targets, .. } if targets.0 == targets.1 => {
|
||||
changed = true;
|
||||
Terminator::Goto { target: targets[0] }
|
||||
Terminator::Goto { target: targets.0 }
|
||||
}
|
||||
Terminator::If { ref targets, cond: Operand::Constant(Constant {
|
||||
literal: Literal::Value {
|
||||
|
@ -106,8 +106,11 @@ impl SimplifyCfg {
|
|||
}, ..
|
||||
}) } => {
|
||||
changed = true;
|
||||
let target_idx = if cond { 0 } else { 1 };
|
||||
Terminator::Goto { target: targets[target_idx] }
|
||||
if cond {
|
||||
Terminator::Goto { target: targets.0 }
|
||||
} else {
|
||||
Terminator::Goto { target: targets.1 }
|
||||
}
|
||||
}
|
||||
Terminator::SwitchInt { ref targets, .. } if targets.len() == 1 => {
|
||||
Terminator::Goto { target: targets[0] }
|
||||
|
|
|
@ -2760,7 +2760,11 @@ fn register_method(ccx: &CrateContext,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn write_metadata(cx: &SharedCrateContext, krate: &hir::Crate, reachable: &NodeSet) -> Vec<u8> {
|
||||
pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>,
|
||||
krate: &hir::Crate,
|
||||
reachable: &NodeSet,
|
||||
mir_map: &MirMap<'tcx>)
|
||||
-> Vec<u8> {
|
||||
use flate;
|
||||
|
||||
let any_library = cx.sess()
|
||||
|
@ -2773,9 +2777,13 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &hir::Crate, reachable: &N
|
|||
}
|
||||
|
||||
let cstore = &cx.tcx().sess.cstore;
|
||||
let metadata = cstore.encode_metadata(
|
||||
cx.tcx(), cx.export_map(), cx.item_symbols(), cx.link_meta(), reachable,
|
||||
krate);
|
||||
let metadata = cstore.encode_metadata(cx.tcx(),
|
||||
cx.export_map(),
|
||||
cx.item_symbols(),
|
||||
cx.link_meta(),
|
||||
reachable,
|
||||
mir_map,
|
||||
krate);
|
||||
let mut compressed = cstore.metadata_encoding_version().to_vec();
|
||||
compressed.extend_from_slice(&flate::deflate_bytes(&metadata));
|
||||
|
||||
|
@ -3045,7 +3053,7 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
|
||||
|
||||
// Translate the metadata.
|
||||
let metadata = write_metadata(&shared_ccx, krate, &reachable_symbol_ids);
|
||||
let metadata = write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map);
|
||||
|
||||
if shared_ccx.sess().trans_stats() {
|
||||
let stats = shared_ccx.stats();
|
||||
|
|
|
@ -39,7 +39,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
mir::Terminator::If { ref cond, targets: [true_bb, false_bb] } => {
|
||||
mir::Terminator::If { ref cond, targets: (true_bb, false_bb) } => {
|
||||
let cond = self.trans_operand(bcx, cond);
|
||||
let lltrue = self.llblock(true_bb);
|
||||
let llfalse = self.llblock(false_bb);
|
||||
|
|
|
@ -120,7 +120,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
bcx
|
||||
}
|
||||
|
||||
mir::Rvalue::InlineAsm(inline_asm) => {
|
||||
mir::Rvalue::InlineAsm(ref inline_asm) => {
|
||||
asm::trans_inline_asm(bcx, inline_asm)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue