1
Fork 0

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:
bors 2015-12-11 00:59:48 +00:00
commit 7ce713961c
20 changed files with 567 additions and 63 deletions

View file

@ -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),

View file

@ -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!() }
}

View file

@ -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
}

View file

@ -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,

View file

@ -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) {
}
}

View file

@ -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)]

View 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]);
}

View file

@ -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,

View file

@ -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)

View file

@ -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 {

View file

@ -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());

View file

@ -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))

View file

@ -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));

View file

@ -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()
}

View file

@ -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 });

View file

@ -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

View file

@ -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] }

View file

@ -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();

View file

@ -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);

View file

@ -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)
}