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 {
|
pub enum ConstVal {
|
||||||
Float(f64),
|
Float(f64),
|
||||||
Int(i64),
|
Int(i64),
|
||||||
|
|
|
@ -28,6 +28,7 @@ use middle::def;
|
||||||
use middle::lang_items;
|
use middle::lang_items;
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, Ty};
|
||||||
use middle::def_id::{DefId, DefIndex};
|
use middle::def_id::{DefId, DefIndex};
|
||||||
|
use mir::repr::Mir;
|
||||||
use session::Session;
|
use session::Session;
|
||||||
use session::search_paths::PathKind;
|
use session::search_paths::PathKind;
|
||||||
use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||||
|
@ -100,6 +101,7 @@ pub enum InlinedItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A borrowed version of `hir::InlinedItem`.
|
/// A borrowed version of `hir::InlinedItem`.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
pub enum InlinedItemRef<'a> {
|
pub enum InlinedItemRef<'a> {
|
||||||
Item(&'a hir::Item),
|
Item(&'a hir::Item),
|
||||||
TraitItem(DefId, &'a hir::TraitItem),
|
TraitItem(DefId, &'a hir::TraitItem),
|
||||||
|
@ -216,6 +218,8 @@ pub trait CrateStore<'tcx> : Any {
|
||||||
// misc. metadata
|
// misc. metadata
|
||||||
fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId)
|
fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId)
|
||||||
-> FoundAst<'tcx>;
|
-> 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
|
// This is basically a 1-based range of ints, which is a little
|
||||||
// silly - I may fix that.
|
// silly - I may fix that.
|
||||||
fn crates(&self) -> Vec<ast::CrateNum>;
|
fn crates(&self) -> Vec<ast::CrateNum>;
|
||||||
|
@ -235,6 +239,7 @@ pub trait CrateStore<'tcx> : Any {
|
||||||
item_symbols: &RefCell<NodeMap<String>>,
|
item_symbols: &RefCell<NodeMap<String>>,
|
||||||
link_meta: &LinkMeta,
|
link_meta: &LinkMeta,
|
||||||
reachable: &NodeSet,
|
reachable: &NodeSet,
|
||||||
|
mir_map: &NodeMap<Mir<'tcx>>,
|
||||||
krate: &hir::Crate) -> Vec<u8>;
|
krate: &hir::Crate) -> Vec<u8>;
|
||||||
fn metadata_encoding_version(&self) -> &[u8];
|
fn metadata_encoding_version(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
@ -383,6 +388,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
||||||
// misc. metadata
|
// misc. metadata
|
||||||
fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId)
|
fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId)
|
||||||
-> FoundAst<'tcx> { unimplemented!() }
|
-> 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
|
// This is basically a 1-based range of ints, which is a little
|
||||||
// silly - I may fix that.
|
// silly - I may fix that.
|
||||||
fn crates(&self) -> Vec<ast::CrateNum> { vec![] }
|
fn crates(&self) -> Vec<ast::CrateNum> { vec![] }
|
||||||
|
@ -404,6 +412,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
||||||
item_symbols: &RefCell<NodeMap<String>>,
|
item_symbols: &RefCell<NodeMap<String>>,
|
||||||
link_meta: &LinkMeta,
|
link_meta: &LinkMeta,
|
||||||
reachable: &NodeSet,
|
reachable: &NodeSet,
|
||||||
|
mir_map: &NodeMap<Mir<'tcx>>,
|
||||||
krate: &hir::Crate) -> Vec<u8> { vec![] }
|
krate: &hir::Crate) -> Vec<u8> { vec![] }
|
||||||
fn metadata_encoding_version(&self) -> &[u8] { unimplemented!() }
|
fn metadata_encoding_version(&self) -> &[u8] { unimplemented!() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
//! This module contains TypeVariants and its major components
|
//! This module contains TypeVariants and its major components
|
||||||
|
|
||||||
|
use middle::cstore;
|
||||||
use middle::def_id::DefId;
|
use middle::def_id::DefId;
|
||||||
use middle::region;
|
use middle::region;
|
||||||
use middle::subst::{self, Substs};
|
use middle::subst::{self, Substs};
|
||||||
|
@ -26,6 +27,8 @@ use syntax::abi;
|
||||||
use syntax::ast::{self, Name};
|
use syntax::ast::{self, Name};
|
||||||
use syntax::parse::token::special_idents;
|
use syntax::parse::token::special_idents;
|
||||||
|
|
||||||
|
use serialize::{Decodable, Decoder};
|
||||||
|
|
||||||
use rustc_front::hir;
|
use rustc_front::hir;
|
||||||
|
|
||||||
use self::FnOutput::*;
|
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 wind up influencing the decisions we ought to make for
|
||||||
/// closure C (which would then require fixed point iteration to
|
/// closure C (which would then require fixed point iteration to
|
||||||
/// handle). Plus it fixes an ICE. :P
|
/// 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> {
|
pub struct ClosureSubsts<'tcx> {
|
||||||
/// Lifetime and type parameters from the enclosing function.
|
/// Lifetime and type parameters from the enclosing function.
|
||||||
/// These are separated out because trans wants to pass them around
|
/// 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>>
|
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)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct TraitTy<'tcx> {
|
pub struct TraitTy<'tcx> {
|
||||||
pub principal: ty::PolyTraitRef<'tcx>,
|
pub principal: ty::PolyTraitRef<'tcx>,
|
||||||
|
@ -434,7 +454,7 @@ pub struct ClosureTy<'tcx> {
|
||||||
pub sig: PolyFnSig<'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> {
|
pub enum FnOutput<'tcx> {
|
||||||
FnConverging(Ty<'tcx>),
|
FnConverging(Ty<'tcx>),
|
||||||
FnDiverging
|
FnDiverging
|
||||||
|
@ -632,7 +652,7 @@ pub struct DebruijnIndex {
|
||||||
///
|
///
|
||||||
/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
|
/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
|
||||||
/// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/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 {
|
pub enum Region {
|
||||||
// Region bound in a type or fn declaration which will be
|
// Region bound in a type or fn declaration which will be
|
||||||
// substituted 'early' -- that is, at the same time when type
|
// substituted 'early' -- that is, at the same time when type
|
||||||
|
@ -701,7 +721,7 @@ pub struct RegionVid {
|
||||||
pub index: u32
|
pub index: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub struct SkolemizedRegionVid {
|
pub struct SkolemizedRegionVid {
|
||||||
pub index: u32
|
pub index: u32
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use middle::def_id::DefId;
|
||||||
use middle::subst::Substs;
|
use middle::subst::Substs;
|
||||||
use middle::ty::{AdtDef, ClosureSubsts, FnOutput, Region, Ty};
|
use middle::ty::{AdtDef, ClosureSubsts, FnOutput, Region, Ty};
|
||||||
use rustc_back::slice;
|
use rustc_back::slice;
|
||||||
|
use rustc_data_structures::tuple_slice::TupleSlice;
|
||||||
use rustc_front::hir::InlineAsm;
|
use rustc_front::hir::InlineAsm;
|
||||||
use syntax::ast::Name;
|
use syntax::ast::Name;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
|
@ -20,6 +21,7 @@ use std::fmt::{Debug, Formatter, Error};
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
|
||||||
/// Lowered representation of a single function.
|
/// Lowered representation of a single function.
|
||||||
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct Mir<'tcx> {
|
pub struct Mir<'tcx> {
|
||||||
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
|
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
|
||||||
/// that indexes into this vector.
|
/// that indexes into this vector.
|
||||||
|
@ -70,13 +72,13 @@ impl<'tcx> Mir<'tcx> {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Mutability and borrow kinds
|
// Mutability and borrow kinds
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum Mutability {
|
pub enum Mutability {
|
||||||
Mut,
|
Mut,
|
||||||
Not,
|
Not,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum BorrowKind {
|
pub enum BorrowKind {
|
||||||
/// Data must be immutable and is aliasable.
|
/// Data must be immutable and is aliasable.
|
||||||
Shared,
|
Shared,
|
||||||
|
@ -127,6 +129,7 @@ pub enum BorrowKind {
|
||||||
|
|
||||||
// A "variable" is a binding declared by the user as part of the fn
|
// A "variable" is a binding declared by the user as part of the fn
|
||||||
// decl, a let, etc.
|
// decl, a let, etc.
|
||||||
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct VarDecl<'tcx> {
|
pub struct VarDecl<'tcx> {
|
||||||
pub mutability: Mutability,
|
pub mutability: Mutability,
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
|
@ -135,6 +138,7 @@ pub struct VarDecl<'tcx> {
|
||||||
|
|
||||||
// A "temp" is a temporary that we place on the stack. They are
|
// A "temp" is a temporary that we place on the stack. They are
|
||||||
// anonymous, always mutable, and have only a type.
|
// anonymous, always mutable, and have only a type.
|
||||||
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct TempDecl<'tcx> {
|
pub struct TempDecl<'tcx> {
|
||||||
pub ty: Ty<'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
|
// there is only one argument, of type `(i32, u32)`, but two bindings
|
||||||
// (`x` and `y`).
|
// (`x` and `y`).
|
||||||
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct ArgDecl<'tcx> {
|
pub struct ArgDecl<'tcx> {
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
@ -161,7 +166,7 @@ pub struct ArgDecl<'tcx> {
|
||||||
/// list of the `Mir`.
|
/// list of the `Mir`.
|
||||||
///
|
///
|
||||||
/// (We use a `u32` internally just to save memory.)
|
/// (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);
|
pub struct BasicBlock(u32);
|
||||||
|
|
||||||
impl BasicBlock {
|
impl BasicBlock {
|
||||||
|
@ -185,12 +190,13 @@ impl Debug for BasicBlock {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// BasicBlock and Terminator
|
// BasicBlock and Terminator
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub struct BasicBlockData<'tcx> {
|
pub struct BasicBlockData<'tcx> {
|
||||||
pub statements: Vec<Statement<'tcx>>,
|
pub statements: Vec<Statement<'tcx>>,
|
||||||
pub terminator: Terminator<'tcx>,
|
pub terminator: Terminator<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub enum Terminator<'tcx> {
|
pub enum Terminator<'tcx> {
|
||||||
/// block should have one successor in the graph; we jump there
|
/// block should have one successor in the graph; we jump there
|
||||||
Goto {
|
Goto {
|
||||||
|
@ -206,7 +212,7 @@ pub enum Terminator<'tcx> {
|
||||||
/// jump to branch 0 if this lvalue evaluates to true
|
/// jump to branch 0 if this lvalue evaluates to true
|
||||||
If {
|
If {
|
||||||
cond: Operand<'tcx>,
|
cond: Operand<'tcx>,
|
||||||
targets: [BasicBlock; 2],
|
targets: (BasicBlock, BasicBlock),
|
||||||
},
|
},
|
||||||
|
|
||||||
/// lvalue evaluates to some enum; jump depending on the branch
|
/// lvalue evaluates to some enum; jump depending on the branch
|
||||||
|
@ -254,7 +260,7 @@ pub enum Terminator<'tcx> {
|
||||||
/// unwinding.
|
/// unwinding.
|
||||||
Call {
|
Call {
|
||||||
data: CallData<'tcx>,
|
data: CallData<'tcx>,
|
||||||
targets: [BasicBlock; 2],
|
targets: (BasicBlock, BasicBlock),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,12 +270,12 @@ impl<'tcx> Terminator<'tcx> {
|
||||||
match *self {
|
match *self {
|
||||||
Goto { target: ref b } => slice::ref_slice(b),
|
Goto { target: ref b } => slice::ref_slice(b),
|
||||||
Panic { 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,
|
Switch { targets: ref b, .. } => b,
|
||||||
SwitchInt { targets: ref b, .. } => b,
|
SwitchInt { targets: ref b, .. } => b,
|
||||||
Diverge => &[],
|
Diverge => &[],
|
||||||
Return => &[],
|
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 {
|
match *self {
|
||||||
Goto { target: ref mut b } => slice::mut_ref_slice(b),
|
Goto { target: ref mut b } => slice::mut_ref_slice(b),
|
||||||
Panic { 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,
|
Switch { targets: ref mut b, .. } => b,
|
||||||
SwitchInt { targets: ref mut b, .. } => b,
|
SwitchInt { targets: ref mut b, .. } => b,
|
||||||
Diverge => &mut [],
|
Diverge => &mut [],
|
||||||
Return => &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> {
|
pub struct CallData<'tcx> {
|
||||||
/// where the return value is written to
|
/// where the return value is written to
|
||||||
pub destination: Lvalue<'tcx>,
|
pub destination: Lvalue<'tcx>,
|
||||||
|
@ -345,18 +351,19 @@ impl<'tcx> Debug for Terminator<'tcx> {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Statements
|
// Statements
|
||||||
|
|
||||||
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct Statement<'tcx> {
|
pub struct Statement<'tcx> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub kind: StatementKind<'tcx>,
|
pub kind: StatementKind<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub enum StatementKind<'tcx> {
|
pub enum StatementKind<'tcx> {
|
||||||
Assign(Lvalue<'tcx>, Rvalue<'tcx>),
|
Assign(Lvalue<'tcx>, Rvalue<'tcx>),
|
||||||
Drop(DropKind, Lvalue<'tcx>),
|
Drop(DropKind, Lvalue<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum DropKind {
|
pub enum DropKind {
|
||||||
Free, // free a partially constructed box, should go away eventually
|
Free, // free a partially constructed box, should go away eventually
|
||||||
Deep
|
Deep
|
||||||
|
@ -377,7 +384,7 @@ impl<'tcx> Debug for Statement<'tcx> {
|
||||||
|
|
||||||
/// A path to a value; something that can be evaluated without
|
/// A path to a value; something that can be evaluated without
|
||||||
/// changing or disturbing program state.
|
/// changing or disturbing program state.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum Lvalue<'tcx> {
|
pub enum Lvalue<'tcx> {
|
||||||
/// local variable declared by the user
|
/// local variable declared by the user
|
||||||
Var(u32),
|
Var(u32),
|
||||||
|
@ -403,13 +410,13 @@ pub enum Lvalue<'tcx> {
|
||||||
/// or `*B` or `B[index]`. Note that it is parameterized because it is
|
/// or `*B` or `B[index]`. Note that it is parameterized because it is
|
||||||
/// shared between `Constant` and `Lvalue`. See the aliases
|
/// shared between `Constant` and `Lvalue`. See the aliases
|
||||||
/// `LvalueProjection` etc below.
|
/// `LvalueProjection` etc below.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Projection<'tcx, B, V> {
|
pub struct Projection<'tcx, B, V> {
|
||||||
pub base: B,
|
pub base: B,
|
||||||
pub elem: ProjectionElem<'tcx, V>,
|
pub elem: ProjectionElem<'tcx, V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum ProjectionElem<'tcx, V> {
|
pub enum ProjectionElem<'tcx, V> {
|
||||||
Deref,
|
Deref,
|
||||||
Field(Field),
|
Field(Field),
|
||||||
|
@ -447,7 +454,7 @@ pub type LvalueElem<'tcx> =
|
||||||
ProjectionElem<'tcx,Operand<'tcx>>;
|
ProjectionElem<'tcx,Operand<'tcx>>;
|
||||||
|
|
||||||
/// Index into the list of fields found in a `VariantDef`
|
/// 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);
|
pub struct Field(u32);
|
||||||
|
|
||||||
impl Field {
|
impl Field {
|
||||||
|
@ -523,7 +530,7 @@ impl<'tcx> Debug for Lvalue<'tcx> {
|
||||||
// lvalue). They are intentionally limited to prevent rvalues from
|
// lvalue). They are intentionally limited to prevent rvalues from
|
||||||
// being nested in one another.
|
// being nested in one another.
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum Operand<'tcx> {
|
pub enum Operand<'tcx> {
|
||||||
Consume(Lvalue<'tcx>),
|
Consume(Lvalue<'tcx>),
|
||||||
Constant(Constant<'tcx>),
|
Constant(Constant<'tcx>),
|
||||||
|
@ -542,7 +549,7 @@ impl<'tcx> Debug for Operand<'tcx> {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Rvalues
|
// Rvalues
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub enum Rvalue<'tcx> {
|
pub enum Rvalue<'tcx> {
|
||||||
// x (either a move or copy, depending on type of x)
|
// x (either a move or copy, depending on type of x)
|
||||||
Use(Operand<'tcx>),
|
Use(Operand<'tcx>),
|
||||||
|
@ -583,10 +590,10 @@ pub enum Rvalue<'tcx> {
|
||||||
from_end: usize,
|
from_end: usize,
|
||||||
},
|
},
|
||||||
|
|
||||||
InlineAsm(&'tcx InlineAsm),
|
InlineAsm(InlineAsm),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum CastKind {
|
pub enum CastKind {
|
||||||
Misc,
|
Misc,
|
||||||
|
|
||||||
|
@ -604,7 +611,7 @@ pub enum CastKind {
|
||||||
Unsize,
|
Unsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum AggregateKind<'tcx> {
|
pub enum AggregateKind<'tcx> {
|
||||||
Vec,
|
Vec,
|
||||||
Tuple,
|
Tuple,
|
||||||
|
@ -612,7 +619,7 @@ pub enum AggregateKind<'tcx> {
|
||||||
Closure(DefId, &'tcx ClosureSubsts<'tcx>),
|
Closure(DefId, &'tcx ClosureSubsts<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum BinOp {
|
pub enum BinOp {
|
||||||
/// The `+` operator (addition)
|
/// The `+` operator (addition)
|
||||||
Add,
|
Add,
|
||||||
|
@ -648,7 +655,7 @@ pub enum BinOp {
|
||||||
Gt,
|
Gt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum UnOp {
|
pub enum UnOp {
|
||||||
/// The `!` operator for logical inversion
|
/// The `!` operator for logical inversion
|
||||||
Not,
|
Not,
|
||||||
|
@ -684,14 +691,14 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||||
// this does not necessarily mean that they are "==" in Rust -- in
|
// this does not necessarily mean that they are "==" in Rust -- in
|
||||||
// particular one must be wary of `NaN`!
|
// particular one must be wary of `NaN`!
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Constant<'tcx> {
|
pub struct Constant<'tcx> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
pub literal: Literal<'tcx>,
|
pub literal: Literal<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum Literal<'tcx> {
|
pub enum Literal<'tcx> {
|
||||||
Item {
|
Item {
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
|
|
@ -8,8 +8,11 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use middle::def_id::DefId;
|
||||||
use middle::ty::Region;
|
use middle::ty::Region;
|
||||||
use mir::repr::*;
|
use mir::repr::*;
|
||||||
|
use rustc_data_structures::tuple_slice::TupleSlice;
|
||||||
|
use syntax::codemap::Span;
|
||||||
|
|
||||||
pub trait Visitor<'tcx> {
|
pub trait Visitor<'tcx> {
|
||||||
// Override these, and call `self.super_xxx` to revert back to the
|
// Override these, and call `self.super_xxx` to revert back to the
|
||||||
|
@ -55,6 +58,18 @@ pub trait Visitor<'tcx> {
|
||||||
self.super_constant(constant);
|
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
|
// The `super_xxx` methods comprise the default behavior and are
|
||||||
// not meant to be overidden.
|
// not meant to be overidden.
|
||||||
|
|
||||||
|
@ -73,6 +88,8 @@ pub trait Visitor<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn super_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) {
|
fn super_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) {
|
||||||
|
self.visit_span(statement.span);
|
||||||
|
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
StatementKind::Assign(ref lvalue, ref rvalue) => {
|
StatementKind::Assign(ref lvalue, ref rvalue) => {
|
||||||
self.visit_assign(block, lvalue, rvalue);
|
self.visit_assign(block, lvalue, rvalue);
|
||||||
|
@ -97,7 +114,7 @@ pub trait Visitor<'tcx> {
|
||||||
|
|
||||||
Terminator::If { ref cond, ref targets } => {
|
Terminator::If { ref cond, ref targets } => {
|
||||||
self.visit_operand(cond);
|
self.visit_operand(cond);
|
||||||
for &target in &targets[..] {
|
for &target in targets.as_slice() {
|
||||||
self.visit_branch(block, target);
|
self.visit_branch(block, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +143,7 @@ pub trait Visitor<'tcx> {
|
||||||
for arg in &data.args {
|
for arg in &data.args {
|
||||||
self.visit_operand(arg);
|
self.visit_operand(arg);
|
||||||
}
|
}
|
||||||
for &target in &targets[..] {
|
for &target in targets.as_slice() {
|
||||||
self.visit_branch(block, target);
|
self.visit_branch(block, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +234,26 @@ pub trait Visitor<'tcx> {
|
||||||
fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) {
|
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
|
// Consumed as part of an operand
|
||||||
Consume,
|
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 transitive_relation;
|
||||||
pub mod unify;
|
pub mod unify;
|
||||||
pub mod fnv;
|
pub mod fnv;
|
||||||
|
pub mod tuple_slice;
|
||||||
|
|
||||||
// See comments in src/librustc/lib.rs
|
// See comments in src/librustc/lib.rs
|
||||||
#[doc(hidden)]
|
#[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,
|
tag_tree = 0x51,
|
||||||
|
|
||||||
// GAP 0x52
|
tag_mir = 0x52,
|
||||||
|
|
||||||
tag_table = 0x53,
|
tag_table = 0x53,
|
||||||
// GAP 0x54, 0x55
|
// GAP 0x54, 0x55
|
||||||
tag_table_def = 0x56,
|
tag_table_def = 0x56,
|
||||||
|
|
|
@ -22,6 +22,7 @@ use middle::ty::{self, Ty};
|
||||||
use middle::def_id::{DefId, DefIndex};
|
use middle::def_id::{DefId, DefIndex};
|
||||||
|
|
||||||
use rustc::front::map as hir_map;
|
use rustc::front::map as hir_map;
|
||||||
|
use rustc::mir::repr::Mir;
|
||||||
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||||
|
|
||||||
use std::cell::RefCell;
|
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)
|
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>
|
fn crates(&self) -> Vec<ast::CrateNum>
|
||||||
{
|
{
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
|
@ -473,6 +480,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||||
item_symbols: &RefCell<NodeMap<String>>,
|
item_symbols: &RefCell<NodeMap<String>>,
|
||||||
link_meta: &LinkMeta,
|
link_meta: &LinkMeta,
|
||||||
reachable: &NodeSet,
|
reachable: &NodeSet,
|
||||||
|
mir_map: &NodeMap<Mir<'tcx>>,
|
||||||
krate: &hir::Crate) -> Vec<u8>
|
krate: &hir::Crate) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let encode_inlined_item: encoder::EncodeInlinedItem =
|
let encode_inlined_item: encoder::EncodeInlinedItem =
|
||||||
|
@ -486,7 +494,8 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||||
link_meta: link_meta,
|
link_meta: link_meta,
|
||||||
cstore: self,
|
cstore: self,
|
||||||
encode_inlined_item: encode_inlined_item,
|
encode_inlined_item: encode_inlined_item,
|
||||||
reachable: reachable
|
reachable: reachable,
|
||||||
|
mir_map: mir_map,
|
||||||
};
|
};
|
||||||
encoder::encode_metadata(encode_params, krate)
|
encoder::encode_metadata(encode_params, krate)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ use cstore::{self, crate_metadata};
|
||||||
use common::*;
|
use common::*;
|
||||||
use encoder::def_to_u64;
|
use encoder::def_to_u64;
|
||||||
use index;
|
use index;
|
||||||
|
use tls_context;
|
||||||
use tydecode::TyDecoder;
|
use tydecode::TyDecoder;
|
||||||
|
|
||||||
use rustc::back::svh::Svh;
|
use rustc::back::svh::Svh;
|
||||||
|
@ -26,7 +27,7 @@ use rustc::util::nodemap::FnvHashMap;
|
||||||
use rustc_front::hir;
|
use rustc_front::hir;
|
||||||
|
|
||||||
use middle::cstore::{LOCAL_CRATE, FoundAst, InlinedItem, LinkagePreference};
|
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;
|
||||||
use middle::def_id::{DefId, DefIndex};
|
use middle::def_id::{DefId, DefIndex};
|
||||||
use middle::lang_items;
|
use middle::lang_items;
|
||||||
|
@ -34,6 +35,9 @@ use middle::subst;
|
||||||
use middle::ty::{ImplContainer, TraitContainer};
|
use middle::ty::{ImplContainer, TraitContainer};
|
||||||
use middle::ty::{self, RegionEscape, Ty};
|
use middle::ty::{self, RegionEscape, Ty};
|
||||||
|
|
||||||
|
use rustc::mir;
|
||||||
|
use rustc::mir::visit::MutVisitor;
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -48,7 +52,7 @@ use syntax::parse::token::{IdentInterner, special_idents};
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::codemap;
|
use syntax::codemap::{self, Span};
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
use syntax::ptr::P;
|
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_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
|
||||||
fn get_mutability(ch: u8) -> hir::Mutability {
|
fn get_mutability(ch: u8) -> hir::Mutability {
|
||||||
match ch as char {
|
match ch as char {
|
||||||
|
|
|
@ -30,6 +30,7 @@ use middle::ty::{self, Ty};
|
||||||
use rustc::back::svh::Svh;
|
use rustc::back::svh::Svh;
|
||||||
use rustc::front::map::{LinkedPath, PathElem, PathElems};
|
use rustc::front::map::{LinkedPath, PathElem, PathElems};
|
||||||
use rustc::front::map as ast_map;
|
use rustc::front::map as ast_map;
|
||||||
|
use rustc::mir::repr::Mir;
|
||||||
use rustc::session::config;
|
use rustc::session::config;
|
||||||
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||||
|
|
||||||
|
@ -64,6 +65,7 @@ pub struct EncodeParams<'a, 'tcx: 'a> {
|
||||||
pub cstore: &'a cstore::CStore,
|
pub cstore: &'a cstore::CStore,
|
||||||
pub encode_inlined_item: EncodeInlinedItem<'a>,
|
pub encode_inlined_item: EncodeInlinedItem<'a>,
|
||||||
pub reachable: &'a NodeSet,
|
pub reachable: &'a NodeSet,
|
||||||
|
pub mir_map: &'a NodeMap<Mir<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EncodeContext<'a, 'tcx: 'a> {
|
pub struct EncodeContext<'a, 'tcx: 'a> {
|
||||||
|
@ -76,6 +78,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
|
||||||
pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
|
pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
|
||||||
pub type_abbrevs: tyencode::abbrev_map<'tcx>,
|
pub type_abbrevs: tyencode::abbrev_map<'tcx>,
|
||||||
pub reachable: &'a NodeSet,
|
pub reachable: &'a NodeSet,
|
||||||
|
pub mir_map: &'a NodeMap<Mir<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> EncodeContext<'a,'tcx> {
|
impl<'a, 'tcx> EncodeContext<'a,'tcx> {
|
||||||
|
@ -840,7 +843,24 @@ fn encode_inlined_item(ecx: &EncodeContext,
|
||||||
ii: InlinedItemRef) {
|
ii: InlinedItemRef) {
|
||||||
let mut eii = ecx.encode_inlined_item.borrow_mut();
|
let mut eii = ecx.encode_inlined_item.borrow_mut();
|
||||||
let eii: &mut EncodeInlinedItem = &mut *eii;
|
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';
|
const FN_FAMILY: char = 'f';
|
||||||
|
@ -1884,6 +1904,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
|
||||||
encode_inlined_item,
|
encode_inlined_item,
|
||||||
link_meta,
|
link_meta,
|
||||||
reachable,
|
reachable,
|
||||||
|
mir_map,
|
||||||
..
|
..
|
||||||
} = parms;
|
} = parms;
|
||||||
let ecx = EncodeContext {
|
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),
|
encode_inlined_item: RefCell::new(encode_inlined_item),
|
||||||
type_abbrevs: RefCell::new(FnvHashMap()),
|
type_abbrevs: RefCell::new(FnvHashMap()),
|
||||||
reachable: reachable,
|
reachable: reachable,
|
||||||
|
mir_map: mir_map,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut wr = Cursor::new(Vec::new());
|
let mut wr = Cursor::new(Vec::new());
|
||||||
|
|
|
@ -69,7 +69,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||||
this.cfg.terminate(block,
|
this.cfg.terminate(block,
|
||||||
Terminator::If {
|
Terminator::If {
|
||||||
cond: Operand::Consume(lt),
|
cond: Operand::Consume(lt),
|
||||||
targets: [success, failure],
|
targets: (success, failure),
|
||||||
});
|
});
|
||||||
this.panic(failure);
|
this.panic(failure);
|
||||||
success.and(slice.index(idx))
|
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))
|
this.in_scope(extent, block, |this| this.as_rvalue(block, value))
|
||||||
}
|
}
|
||||||
ExprKind::InlineAsm { asm } => {
|
ExprKind::InlineAsm { asm } => {
|
||||||
block.and(Rvalue::InlineAsm(asm))
|
block.and(Rvalue::InlineAsm(asm.clone()))
|
||||||
}
|
}
|
||||||
ExprKind::Repeat { value, count } => {
|
ExprKind::Repeat { value, count } => {
|
||||||
let value_operand = unpack!(block = this.as_operand(block, value));
|
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();
|
let mut else_block = this.cfg.start_new_block();
|
||||||
this.cfg.terminate(block, Terminator::If {
|
this.cfg.terminate(block, Terminator::If {
|
||||||
cond: operand,
|
cond: operand,
|
||||||
targets: [then_block, else_block]
|
targets: (then_block, else_block)
|
||||||
});
|
});
|
||||||
|
|
||||||
unpack!(then_block = this.into(destination, then_block, then_expr));
|
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 lhs = unpack!(block = this.as_operand(block, lhs));
|
||||||
let blocks = match op {
|
let blocks = match op {
|
||||||
LogicalOp::And => [else_block, false_block],
|
LogicalOp::And => (else_block, false_block),
|
||||||
LogicalOp::Or => [true_block, else_block],
|
LogicalOp::Or => (true_block, else_block),
|
||||||
};
|
};
|
||||||
this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });
|
this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });
|
||||||
|
|
||||||
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
|
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
|
||||||
this.cfg.terminate(else_block, Terminator::If {
|
this.cfg.terminate(else_block, Terminator::If {
|
||||||
cond: rhs,
|
cond: rhs,
|
||||||
targets: [true_block, false_block]
|
targets: (true_block, false_block)
|
||||||
});
|
});
|
||||||
|
|
||||||
this.cfg.push_assign_constant(
|
this.cfg.push_assign_constant(
|
||||||
|
@ -149,7 +149,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||||
this.cfg.terminate(loop_block_end,
|
this.cfg.terminate(loop_block_end,
|
||||||
Terminator::If {
|
Terminator::If {
|
||||||
cond: cond,
|
cond: cond,
|
||||||
targets: [body_block, exit_block]
|
targets: (body_block, exit_block)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
body_block = loop_block;
|
body_block = loop_block;
|
||||||
|
@ -225,7 +225,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||||
func: fun,
|
func: fun,
|
||||||
args: args,
|
args: args,
|
||||||
},
|
},
|
||||||
targets: [success, panic],
|
targets: (success, panic),
|
||||||
});
|
});
|
||||||
success.unit()
|
success.unit()
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,7 +555,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||||
let cond = unpack!(block = self.as_operand(block, guard));
|
let cond = unpack!(block = self.as_operand(block, guard));
|
||||||
let otherwise = self.cfg.start_new_block();
|
let otherwise = self.cfg.start_new_block();
|
||||||
self.cfg.terminate(block, Terminator::If { cond: cond,
|
self.cfg.terminate(block, Terminator::If { cond: cond,
|
||||||
targets: [arm_block, otherwise]});
|
targets: (arm_block, otherwise)});
|
||||||
Some(otherwise)
|
Some(otherwise)
|
||||||
} else {
|
} else {
|
||||||
self.cfg.terminate(block, Terminator::Goto { target: arm_block });
|
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.start_new_block()];
|
||||||
self.cfg.terminate(block, Terminator::If {
|
self.cfg.terminate(block, Terminator::If {
|
||||||
cond: Operand::Consume(result),
|
cond: Operand::Consume(result),
|
||||||
targets: [target_blocks[0], target_blocks[1]]
|
targets: (target_blocks[0], target_blocks[1])
|
||||||
});
|
});
|
||||||
|
|
||||||
target_blocks
|
target_blocks
|
||||||
|
@ -252,7 +252,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||||
let bool_ty = self.hir.bool_ty();
|
let bool_ty = self.hir.bool_ty();
|
||||||
let eq_result = self.temp(bool_ty);
|
let eq_result = self.temp(bool_ty);
|
||||||
let func = self.item_ref_operand(span, item_ref);
|
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,
|
self.cfg.terminate(block,
|
||||||
Terminator::Call {
|
Terminator::Call {
|
||||||
data: CallData {
|
data: CallData {
|
||||||
|
@ -264,10 +264,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||||
});
|
});
|
||||||
|
|
||||||
// check the result
|
// check the result
|
||||||
self.cfg.terminate(call_blocks[0],
|
self.cfg.terminate(call_blocks.0,
|
||||||
Terminator::If {
|
Terminator::If {
|
||||||
cond: Operand::Consume(eq_result),
|
cond: Operand::Consume(eq_result),
|
||||||
targets: [target_blocks[0], target_blocks[1]],
|
targets: (target_blocks[0], target_blocks[1]),
|
||||||
});
|
});
|
||||||
|
|
||||||
target_blocks
|
target_blocks
|
||||||
|
|
|
@ -96,9 +96,9 @@ impl SimplifyCfg {
|
||||||
mem::swap(&mut terminator, &mut mir.basic_block_data_mut(bb).terminator);
|
mem::swap(&mut terminator, &mut mir.basic_block_data_mut(bb).terminator);
|
||||||
|
|
||||||
mir.basic_block_data_mut(bb).terminator = match 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;
|
changed = true;
|
||||||
Terminator::Goto { target: targets[0] }
|
Terminator::Goto { target: targets.0 }
|
||||||
}
|
}
|
||||||
Terminator::If { ref targets, cond: Operand::Constant(Constant {
|
Terminator::If { ref targets, cond: Operand::Constant(Constant {
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
|
@ -106,8 +106,11 @@ impl SimplifyCfg {
|
||||||
}, ..
|
}, ..
|
||||||
}) } => {
|
}) } => {
|
||||||
changed = true;
|
changed = true;
|
||||||
let target_idx = if cond { 0 } else { 1 };
|
if cond {
|
||||||
Terminator::Goto { target: targets[target_idx] }
|
Terminator::Goto { target: targets.0 }
|
||||||
|
} else {
|
||||||
|
Terminator::Goto { target: targets.1 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Terminator::SwitchInt { ref targets, .. } if targets.len() == 1 => {
|
Terminator::SwitchInt { ref targets, .. } if targets.len() == 1 => {
|
||||||
Terminator::Goto { target: targets[0] }
|
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;
|
use flate;
|
||||||
|
|
||||||
let any_library = cx.sess()
|
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 cstore = &cx.tcx().sess.cstore;
|
||||||
let metadata = cstore.encode_metadata(
|
let metadata = cstore.encode_metadata(cx.tcx(),
|
||||||
cx.tcx(), cx.export_map(), cx.item_symbols(), cx.link_meta(), reachable,
|
cx.export_map(),
|
||||||
krate);
|
cx.item_symbols(),
|
||||||
|
cx.link_meta(),
|
||||||
|
reachable,
|
||||||
|
mir_map,
|
||||||
|
krate);
|
||||||
let mut compressed = cstore.metadata_encoding_version().to_vec();
|
let mut compressed = cstore.metadata_encoding_version().to_vec();
|
||||||
compressed.extend_from_slice(&flate::deflate_bytes(&metadata));
|
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);
|
let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
|
||||||
|
|
||||||
// Translate the metadata.
|
// 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() {
|
if shared_ccx.sess().trans_stats() {
|
||||||
let stats = shared_ccx.stats();
|
let stats = shared_ccx.stats();
|
||||||
|
|
|
@ -39,7 +39,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||||
unimplemented!()
|
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 cond = self.trans_operand(bcx, cond);
|
||||||
let lltrue = self.llblock(true_bb);
|
let lltrue = self.llblock(true_bb);
|
||||||
let llfalse = self.llblock(false_bb);
|
let llfalse = self.llblock(false_bb);
|
||||||
|
|
|
@ -120,7 +120,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||||
bcx
|
bcx
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::InlineAsm(inline_asm) => {
|
mir::Rvalue::InlineAsm(ref inline_asm) => {
|
||||||
asm::trans_inline_asm(bcx, inline_asm)
|
asm::trans_inline_asm(bcx, inline_asm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue