mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 03:33:59 +00:00
Add caching of external MIR in trans::collector
This commit is contained in:
parent
862911df9a
commit
9e969808e2
@ -25,7 +25,7 @@ use std::{iter, u32};
|
|||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
/// Lowered representation of a single function.
|
/// Lowered representation of a single function.
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(Clone, 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.
|
||||||
@ -146,7 +146,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)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct VarDecl<'tcx> {
|
pub struct VarDecl<'tcx> {
|
||||||
pub mutability: Mutability,
|
pub mutability: Mutability,
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
@ -155,7 +155,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)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct TempDecl<'tcx> {
|
pub struct TempDecl<'tcx> {
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
@ -171,7 +171,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)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct ArgDecl<'tcx> {
|
pub struct ArgDecl<'tcx> {
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
@ -207,14 +207,14 @@ impl Debug for BasicBlock {
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// BasicBlock and Terminator
|
// BasicBlock and Terminator
|
||||||
|
|
||||||
#[derive(Debug, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub struct BasicBlockData<'tcx> {
|
pub struct BasicBlockData<'tcx> {
|
||||||
pub statements: Vec<Statement<'tcx>>,
|
pub statements: Vec<Statement<'tcx>>,
|
||||||
pub terminator: Option<Terminator<'tcx>>,
|
pub terminator: Option<Terminator<'tcx>>,
|
||||||
pub is_cleanup: bool,
|
pub is_cleanup: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(Clone, 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 {
|
||||||
@ -481,13 +481,13 @@ impl<'tcx> Terminator<'tcx> {
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Statements
|
// Statements
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(Clone, 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, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, 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>),
|
||||||
|
@ -2110,6 +2110,10 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
fn record_translation_item_as_generated<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
fn record_translation_item_as_generated<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
node_id: ast::NodeId,
|
node_id: ast::NodeId,
|
||||||
param_substs: &'tcx Substs<'tcx>) {
|
param_substs: &'tcx Substs<'tcx>) {
|
||||||
|
if !collector::collecting_debug_information(ccx) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let def_id = match ccx.tcx().node_id_to_type(node_id).sty {
|
let def_id = match ccx.tcx().node_id_to_type(node_id).sty {
|
||||||
ty::TyClosure(def_id, _) => def_id,
|
ty::TyClosure(def_id, _) => def_id,
|
||||||
_ => ccx.external_srcs()
|
_ => ccx.external_srcs()
|
||||||
|
@ -217,6 +217,7 @@ use trans::monomorphize;
|
|||||||
use util::nodemap::{FnvHashSet, FnvHashMap, DefIdMap};
|
use util::nodemap::{FnvHashSet, FnvHashMap, DefIdMap};
|
||||||
|
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
||||||
pub enum TransItemCollectionMode {
|
pub enum TransItemCollectionMode {
|
||||||
@ -281,9 +282,14 @@ pub fn collect_crate_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
debug!("Building translation item graph, beginning at roots");
|
debug!("Building translation item graph, beginning at roots");
|
||||||
let mut visited = FnvHashSet();
|
let mut visited = FnvHashSet();
|
||||||
let mut recursion_depths = DefIdMap();
|
let mut recursion_depths = DefIdMap();
|
||||||
|
let mut mir_cache = DefIdMap();
|
||||||
|
|
||||||
for root in roots {
|
for root in roots {
|
||||||
collect_items_rec(ccx, root, &mut visited, &mut recursion_depths);
|
collect_items_rec(ccx,
|
||||||
|
root,
|
||||||
|
&mut visited,
|
||||||
|
&mut recursion_depths,
|
||||||
|
&mut mir_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
visited
|
visited
|
||||||
@ -313,11 +319,27 @@ fn collect_roots<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
roots
|
roots
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum CachedMir<'mir, 'tcx: 'mir> {
|
||||||
|
Ref(&'mir mir::Mir<'tcx>),
|
||||||
|
Owned(Rc<mir::Mir<'tcx>>)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'mir, 'tcx: 'mir> CachedMir<'mir, 'tcx> {
|
||||||
|
fn get_ref<'a>(&'a self) -> &'a mir::Mir<'tcx> {
|
||||||
|
match *self {
|
||||||
|
CachedMir::Ref(r) => r,
|
||||||
|
CachedMir::Owned(ref rc) => &**rc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collect all monomorphized translation items reachable from `starting_point`
|
// Collect all monomorphized translation items reachable from `starting_point`
|
||||||
fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
|
fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
starting_point: TransItem<'tcx>,
|
starting_point: TransItem<'tcx>,
|
||||||
visited: &mut FnvHashSet<TransItem<'tcx>>,
|
visited: &mut FnvHashSet<TransItem<'tcx>>,
|
||||||
recursion_depths: &mut DefIdMap<usize>) {
|
recursion_depths: &mut DefIdMap<usize>,
|
||||||
|
mir_cache: &mut DefIdMap<CachedMir<'a, 'tcx>>) {
|
||||||
if !visited.insert(starting_point.clone()) {
|
if !visited.insert(starting_point.clone()) {
|
||||||
// We've been here already, no need to search again.
|
// We've been here already, no need to search again.
|
||||||
return;
|
return;
|
||||||
@ -343,42 +365,21 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
|
|
||||||
// Scan the MIR in order to find function calls, closures, and
|
// Scan the MIR in order to find function calls, closures, and
|
||||||
// drop-glue
|
// drop-glue
|
||||||
let mir_not_found_error_message = || {
|
let mir = load_mir(ccx, def_id, mir_cache);
|
||||||
format!("Could not find MIR for function: {}",
|
|
||||||
ccx.tcx().item_path_str(def_id))
|
|
||||||
};
|
|
||||||
|
|
||||||
let external_mir = if !def_id.is_local() {
|
|
||||||
ccx.sess().cstore.maybe_get_item_mir(ccx.tcx(), def_id)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let mir_opt = match external_mir {
|
|
||||||
Some(ref mir) => Some(mir),
|
|
||||||
None => {
|
|
||||||
let node_id = ccx.tcx().map.as_local_node_id(def_id).unwrap();
|
|
||||||
ccx.mir_map().get(&node_id)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mir = errors::expect(ccx.sess().diagnostic(),
|
|
||||||
mir_opt,
|
|
||||||
mir_not_found_error_message);
|
|
||||||
|
|
||||||
let mut visitor = MirNeighborCollector {
|
let mut visitor = MirNeighborCollector {
|
||||||
ccx: ccx,
|
ccx: ccx,
|
||||||
mir: mir,
|
mir: mir.get_ref(),
|
||||||
output: &mut neighbors,
|
output: &mut neighbors,
|
||||||
param_substs: param_substs
|
param_substs: param_substs
|
||||||
};
|
};
|
||||||
|
|
||||||
visitor.visit_mir(mir);
|
visitor.visit_mir(mir.get_ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for neighbour in neighbors {
|
for neighbour in neighbors {
|
||||||
collect_items_rec(ccx, neighbour, visited, recursion_depths);
|
collect_items_rec(ccx, neighbour, visited, recursion_depths, mir_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((def_id, depth)) = recursion_depth_reset {
|
if let Some((def_id, depth)) = recursion_depth_reset {
|
||||||
@ -388,6 +389,37 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
debug!("END collect_items_rec({})", starting_point.to_string(ccx));
|
debug!("END collect_items_rec({})", starting_point.to_string(ccx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_mir<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
mir_cache: &mut DefIdMap<CachedMir<'a, 'tcx>>)
|
||||||
|
-> CachedMir<'a, 'tcx> {
|
||||||
|
let mir_not_found_error_message = || {
|
||||||
|
format!("Could not find MIR for function: {}",
|
||||||
|
ccx.tcx().item_path_str(def_id))
|
||||||
|
};
|
||||||
|
|
||||||
|
if def_id.is_local() {
|
||||||
|
let node_id = ccx.tcx().map.as_local_node_id(def_id).unwrap();
|
||||||
|
let mir_opt = ccx.mir_map().get(&node_id);
|
||||||
|
let mir = errors::expect(ccx.sess().diagnostic(),
|
||||||
|
mir_opt,
|
||||||
|
mir_not_found_error_message);
|
||||||
|
CachedMir::Ref(mir)
|
||||||
|
} else {
|
||||||
|
if let Some(mir) = mir_cache.get(&def_id) {
|
||||||
|
return mir.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mir_opt = ccx.sess().cstore.maybe_get_item_mir(ccx.tcx(), def_id);
|
||||||
|
let mir = errors::expect(ccx.sess().diagnostic(),
|
||||||
|
mir_opt,
|
||||||
|
mir_not_found_error_message);
|
||||||
|
let cached = CachedMir::Owned(Rc::new(mir));
|
||||||
|
mir_cache.insert(def_id, cached.clone());
|
||||||
|
cached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_recursion_limit<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
|
fn check_recursion_limit<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
recursion_depths: &mut DefIdMap<usize>)
|
recursion_depths: &mut DefIdMap<usize>)
|
||||||
@ -1488,14 +1520,15 @@ pub enum TransItemState {
|
|||||||
NotPredictedButGenerated,
|
NotPredictedButGenerated,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn collecting_debug_information(ccx: &CrateContext) -> bool {
|
||||||
|
return cfg!(debug_assertions) &&
|
||||||
|
ccx.sess().opts.debugging_opts.print_trans_items.is_some();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_collection_results<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) {
|
pub fn print_collection_results<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) {
|
||||||
use std::hash::{Hash, SipHasher, Hasher};
|
use std::hash::{Hash, SipHasher, Hasher};
|
||||||
|
|
||||||
if !cfg!(debug_assertions) {
|
if !collecting_debug_information(ccx) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ccx.sess().opts.debugging_opts.print_trans_items.is_none() {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ use middle::def::Def;
|
|||||||
use middle::def_id::DefId;
|
use middle::def_id::DefId;
|
||||||
use trans::{adt, closure, debuginfo, expr, inline, machine};
|
use trans::{adt, closure, debuginfo, expr, inline, machine};
|
||||||
use trans::base::{self, push_ctxt};
|
use trans::base::{self, push_ctxt};
|
||||||
use trans::collector::TransItem;
|
use trans::collector::{self, TransItem};
|
||||||
use trans::common::{self, type_is_sized, ExprOrMethodCall, node_id_substs, C_nil, const_get_elt};
|
use trans::common::{self, type_is_sized, ExprOrMethodCall, node_id_substs, C_nil, const_get_elt};
|
||||||
use trans::common::{CrateContext, C_integral, C_floating, C_bool, C_str_slice, C_bytes, val_ty};
|
use trans::common::{CrateContext, C_integral, C_floating, C_bool, C_str_slice, C_bytes, val_ty};
|
||||||
use trans::common::{C_struct, C_undef, const_to_opt_int, const_to_opt_uint, VariantInfo, C_uint};
|
use trans::common::{C_struct, C_undef, const_to_opt_int, const_to_opt_uint, VariantInfo, C_uint};
|
||||||
@ -1018,7 +1018,9 @@ pub fn trans_static(ccx: &CrateContext,
|
|||||||
attrs: &[ast::Attribute])
|
attrs: &[ast::Attribute])
|
||||||
-> Result<ValueRef, ConstEvalErr> {
|
-> Result<ValueRef, ConstEvalErr> {
|
||||||
|
|
||||||
ccx.record_translation_item_as_generated(TransItem::Static(id));
|
if collector::collecting_debug_information(ccx) {
|
||||||
|
ccx.record_translation_item_as_generated(TransItem::Static(id));
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _icx = push_ctxt("trans_static");
|
let _icx = push_ctxt("trans_static");
|
||||||
|
@ -28,7 +28,7 @@ use trans::build::*;
|
|||||||
use trans::callee;
|
use trans::callee;
|
||||||
use trans::cleanup;
|
use trans::cleanup;
|
||||||
use trans::cleanup::CleanupMethods;
|
use trans::cleanup::CleanupMethods;
|
||||||
use trans::collector::TransItem;
|
use trans::collector::{self, TransItem};
|
||||||
use trans::common::*;
|
use trans::common::*;
|
||||||
use trans::debuginfo::DebugLoc;
|
use trans::debuginfo::DebugLoc;
|
||||||
use trans::declare;
|
use trans::declare;
|
||||||
@ -498,9 +498,11 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
|
|||||||
-> Block<'blk, 'tcx> {
|
-> Block<'blk, 'tcx> {
|
||||||
let t = g.ty();
|
let t = g.ty();
|
||||||
|
|
||||||
bcx.ccx()
|
if collector::collecting_debug_information(bcx.ccx()) {
|
||||||
.record_translation_item_as_generated(TransItem::DropGlue(bcx.tcx()
|
bcx.ccx()
|
||||||
.erase_regions(&t)));
|
.record_translation_item_as_generated(TransItem::DropGlue(bcx.tcx()
|
||||||
|
.erase_regions(&t)));
|
||||||
|
}
|
||||||
|
|
||||||
let skip_dtor = match g { DropGlueKind::Ty(_) => false, DropGlueKind::TyContents(_) => true };
|
let skip_dtor = match g { DropGlueKind::Ty(_) => false, DropGlueKind::TyContents(_) => true };
|
||||||
// NB: v0 is an *alias* of type t here, not a direct value.
|
// NB: v0 is an *alias* of type t here, not a direct value.
|
||||||
|
Loading…
Reference in New Issue
Block a user