Make MIR encodable and store it in crate metadata.

This commit is contained in:
Michael Woerister 2015-12-08 15:53:19 -05:00
parent 8eee116cb8
commit 5addc31adb
9 changed files with 163 additions and 34 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

@ -21,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.
@ -71,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,
@ -128,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,
@ -136,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>,
}
@ -151,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>,
}
@ -162,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 {
@ -186,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 {
@ -289,7 +294,7 @@ impl<'tcx> Terminator<'tcx> {
}
}
#[derive(Debug)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct CallData<'tcx> {
/// where the return value is written to
pub destination: Lvalue<'tcx>,
@ -346,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
@ -378,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),
@ -404,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),
@ -448,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 {
@ -524,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>),
@ -543,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>),
@ -587,7 +593,7 @@ pub enum Rvalue<'tcx> {
InlineAsm(InlineAsm),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum CastKind {
Misc,
@ -605,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,
@ -613,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,
@ -649,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,
@ -685,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

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

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