trans: Load and cache cross-crate Mir instances in the shared context.

This commit is contained in:
Eduard Burtescu 2016-03-08 14:38:13 +02:00
parent 47cd05c8c1
commit 6c551b3766
15 changed files with 210 additions and 232 deletions

View File

@ -77,6 +77,7 @@ use trans::debuginfo::{self, DebugLoc, ToDebugLoc};
use trans::declare;
use trans::expr;
use trans::glue;
use trans::inline;
use trans::intrinsic;
use trans::machine;
use trans::machine::{llalign_of_min, llsize_of, llsize_of_real};
@ -1392,34 +1393,53 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>,
llfndecl: ValueRef,
fn_ty: FnType,
id: ast::NodeId,
def_id: Option<DefId>,
param_substs: &'tcx Substs<'tcx>,
sp: Option<Span>,
block_arena: &'blk TypedArena<common::BlockS<'blk, 'tcx>>)
-> FunctionContext<'blk, 'tcx> {
common::validate_substs(param_substs);
debug!("FunctionContext::new(path={}, id={}, param_substs={:?})",
if id == !0 {
"".to_string()
} else {
let inlined_did = def_id.and_then(|def_id| inline::get_local_instance(ccx, def_id));
let inlined_id = inlined_did.and_then(|id| ccx.tcx().map.as_local_node_id(id));
let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id));
debug!("FunctionContext::new(path={}, def_id={:?}, param_substs={:?})",
inlined_id.map_or(String::new(), |id| {
ccx.tcx().map.path_to_string(id).to_string()
},
id,
}),
def_id,
param_substs);
let debug_context = debuginfo::create_function_debug_context(ccx, id,
param_substs,
llfndecl);
let (blk_id, cfg) = build_cfg(ccx.tcx(), id);
let nested_returns = if let Some(ref cfg) = cfg {
let debug_context = debuginfo::create_function_debug_context(ccx,
inlined_id.unwrap_or(ast::DUMMY_NODE_ID), param_substs, llfndecl);
let cfg = inlined_id.map(|id| build_cfg(ccx.tcx(), id));
let nested_returns = if let Some((blk_id, Some(ref cfg))) = cfg {
has_nested_returns(ccx.tcx(), cfg, blk_id)
} else {
false
};
let check_attrs = |attrs: &[ast::Attribute]| {
attrs.iter().any(|item| item.check_name("rustc_mir"))
};
let use_mir = if let Some(id) = local_id {
check_attrs(ccx.tcx().map.attrs(id))
} else if let Some(def_id) = def_id {
check_attrs(&ccx.sess().cstore.item_attrs(def_id))
} else {
check_attrs(&[])
};
let mir = if use_mir {
def_id.and_then(|id| ccx.get_mir(id))
} else {
None
};
FunctionContext {
mir: ccx.mir_map().map.get(&id),
mir: mir,
llfn: llfndecl,
llretslotptr: Cell::new(None),
param_env: ccx.tcx().empty_parameter_environment(),
@ -1431,21 +1451,21 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
llupvars: RefCell::new(NodeMap()),
lldropflag_hints: RefCell::new(DropFlagHintsMap::new()),
fn_ty: fn_ty,
id: id,
param_substs: param_substs,
span: sp,
span: inlined_id.and_then(|id| ccx.tcx().map.opt_span(id)),
block_arena: block_arena,
lpad_arena: TypedArena::new(),
ccx: ccx,
debug_context: debug_context,
scopes: RefCell::new(Vec::new()),
cfg: cfg,
cfg: cfg.and_then(|(_, cfg)| cfg)
}
}
/// Performs setup on a newly created function, creating the entry
/// scope block and allocating space for the return pointer.
pub fn init(&'blk self, skip_retptr: bool) -> Block<'blk, 'tcx> {
pub fn init(&'blk self, skip_retptr: bool, fn_did: Option<DefId>)
-> Block<'blk, 'tcx> {
let entry_bcx = self.new_temp_block("entry-block");
// Use a dummy instruction as the insertion point for all allocas.
@ -1493,7 +1513,6 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
// Create the drop-flag hints for every unfragmented path in the function.
let tcx = self.ccx.tcx();
let fn_did = tcx.map.local_def_id(self.id);
let tables = tcx.tables.borrow();
let mut hints = self.lldropflag_hints.borrow_mut();
let fragment_infos = tcx.fragment_infos.borrow();
@ -1501,7 +1520,8 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
// Intern table for drop-flag hint datums.
let mut seen = HashMap::new();
if let Some(fragment_infos) = fragment_infos.get(&fn_did) {
let fragment_infos = fn_did.and_then(|did| fragment_infos.get(&did));
if let Some(fragment_infos) = fragment_infos {
for &info in fragment_infos {
let make_datum = |id| {
@ -1558,11 +1578,13 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
fn bind_args(&'blk self,
args: &[hir::Arg],
abi: Abi,
id: ast::NodeId,
closure_env: closure::ClosureEnv,
arg_scope: cleanup::CustomScopeIndex)
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("FunctionContext::bind_args");
let mut bcx = self.init(false);
let fn_did = self.ccx.tcx().map.local_def_id(id);
let mut bcx = self.init(false, Some(fn_did));
let arg_scope_id = cleanup::CustomScope(arg_scope);
let mut idx = 0;
@ -1774,19 +1796,24 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
/// Builds an LLVM function out of a source function.
///
/// If the function closes over its environment a closure will be returned.
pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
decl: &hir::FnDecl,
body: &hir::Block,
llfndecl: ValueRef,
param_substs: &'tcx Substs<'tcx>,
fn_ast_id: ast::NodeId,
attributes: &[ast::Attribute],
fn_ty: FnType,
abi: Abi,
closure_env: closure::ClosureEnv<'b>) {
pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
decl: &hir::FnDecl,
body: &hir::Block,
llfndecl: ValueRef,
param_substs: &'tcx Substs<'tcx>,
def_id: DefId,
inlined_id: ast::NodeId,
fn_ty: FnType,
abi: Abi,
closure_env: closure::ClosureEnv) {
ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
record_translation_item_as_generated(ccx, fn_ast_id, param_substs);
if collector::collecting_debug_information(ccx) {
ccx.record_translation_item_as_generated(TransItem::Fn(Instance {
def: def_id,
params: &param_substs.types
}))
}
let _icx = push_ctxt("trans_closure");
attributes::emit_uwtable(llfndecl, true);
@ -1795,23 +1822,20 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let (arena, fcx): (TypedArena<_>, FunctionContext);
arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfndecl, fn_ty, fn_ast_id,
param_substs, Some(body.span), &arena);
fcx = FunctionContext::new(ccx, llfndecl, fn_ty, Some(def_id), param_substs, &arena);
if attributes.iter().any(|item| item.check_name("rustc_mir")) {
if fcx.mir.is_some() {
return mir::trans_mir(&fcx);
}
// cleanup scope for the incoming arguments
let fn_cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(ccx,
fn_ast_id,
body.span,
true);
let fn_cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(
ccx, inlined_id, body.span, true);
let arg_scope = fcx.push_custom_cleanup_scope_with_debug_loc(fn_cleanup_debug_loc);
// Set up arguments to the function.
debug!("trans_closure: function: {:?}", Value(fcx.llfn));
let bcx = fcx.bind_args(&decl.inputs, abi, closure_env, arg_scope);
let bcx = fcx.bind_args(&decl.inputs, abi, inlined_id, closure_env, arg_scope);
// Up until here, IR instructions for this function have explicitly not been annotated with
// source code location, so we don't step into call setup code. From here on, source location
@ -1862,28 +1886,6 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// Insert the mandatory first few basic blocks before lltop.
fcx.finish(bcx, ret_debug_loc);
fn record_translation_item_as_generated<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
node_id: ast::NodeId,
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 {
ty::TyClosure(def_id, _) => def_id,
_ => ccx.external_srcs()
.borrow()
.get(&node_id)
.map(|did| *did)
.unwrap_or_else(|| ccx.tcx().map.local_def_id(node_id)),
};
ccx.record_translation_item_as_generated(TransItem::Fn(Instance {
def: def_id,
params: &param_substs.types,
}));
}
}
/// Creates an LLVM function corresponding to a source language function.
@ -1892,8 +1894,7 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
body: &hir::Block,
llfndecl: ValueRef,
param_substs: &'tcx Substs<'tcx>,
id: ast::NodeId,
attrs: &[ast::Attribute]) {
id: ast::NodeId) {
let _s = StatRecorder::new(ccx, ccx.tcx().map.path_to_string(id).to_string());
debug!("trans_fn(param_substs={:?})", param_substs);
let _icx = push_ctxt("trans_fn");
@ -1903,13 +1904,18 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
let abi = fn_ty.fn_abi();
let fn_ty = FnType::new(ccx, abi, &sig, &[]);
let def_id = if let Some(&def_id) = ccx.external_srcs().borrow().get(&id) {
def_id
} else {
ccx.tcx().map.local_def_id(id)
};
trans_closure(ccx,
decl,
body,
llfndecl,
param_substs,
def_id,
id,
attrs,
fn_ty,
abi,
closure::ClosureEnv::NotClosure);
@ -2001,9 +2007,10 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let (arena, fcx): (TypedArena<_>, FunctionContext);
arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfndecl, fn_ty, ctor_id,
param_substs, None, &arena);
let bcx = fcx.init(false);
fcx = FunctionContext::new(ccx, llfndecl, fn_ty,
Some(ccx.tcx().map.local_def_id(ctor_id)),
param_substs, &arena);
let bcx = fcx.init(false, None);
assert!(!fcx.needs_ret_allocas);
@ -2239,7 +2246,7 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
let empty_substs = tcx.mk_substs(Substs::trans_empty());
let def_id = tcx.map.local_def_id(item.id);
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
trans_fn(ccx, &decl, &body, llfn, empty_substs, item.id, &item.attrs);
trans_fn(ccx, &decl, &body, llfn, empty_substs, item.id);
set_global_section(ccx, llfn, item);
update_linkage(ccx,
llfn,
@ -2278,8 +2285,7 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
let empty_substs = tcx.mk_substs(Substs::trans_empty());
let def_id = tcx.map.local_def_id(impl_item.id);
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
trans_fn(ccx, &sig.decl, body, llfn, empty_substs,
impl_item.id, &impl_item.attrs);
trans_fn(ccx, &sig.decl, body, llfn, empty_substs, impl_item.id);
update_linkage(ccx, llfn, Some(impl_item.id),
if is_origin {
OriginalTranslation

View File

@ -387,9 +387,8 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
let empty_substs = tcx.mk_substs(Substs::trans_empty());
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
block_arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfn, fn_ty, ast::DUMMY_NODE_ID,
empty_substs, None, &block_arena);
let mut bcx = fcx.init(false);
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
let mut bcx = fcx.init(false, None);
let llargs = get_params(fcx.llfn);

View File

@ -34,7 +34,6 @@ use middle::ty::{self, Ty, TyCtxt};
use session::config::FullDebugInfo;
use syntax::ast;
use syntax::attr::{ThinAttributes, ThinAttributesExt};
use rustc_front::hir;
@ -43,7 +42,7 @@ use libc::c_uint;
fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
closure_def_id: DefId,
arg_scope_id: ScopeId,
freevars: &[ty::Freevar]) {
id: ast::NodeId) {
let _icx = push_ctxt("closure::load_closure_environment");
let kind = kind_for_closure(bcx.ccx(), closure_def_id);
@ -52,7 +51,7 @@ fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// Special case for small by-value selfs.
let llenv = if kind == ty::ClosureKind::FnOnce && !env_arg.is_indirect() {
let closure_ty = node_id_type(bcx, bcx.fcx.id);
let closure_ty = node_id_type(bcx, id);
let llenv = rvalue_scratch_datum(bcx, closure_ty, "closure_env").val;
env_arg.store_fn_arg(bcx, &mut env_idx, llenv);
llenv
@ -70,52 +69,52 @@ fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
None
};
for (i, freevar) in freevars.iter().enumerate() {
let upvar_id = ty::UpvarId { var_id: freevar.def.var_id(),
closure_expr_id: bcx.fcx.id };
let upvar_capture = bcx.tcx().upvar_capture(upvar_id).unwrap();
let mut upvar_ptr = StructGEP(bcx, llenv, i);
let captured_by_ref = match upvar_capture {
ty::UpvarCapture::ByValue => false,
ty::UpvarCapture::ByRef(..) => {
upvar_ptr = Load(bcx, upvar_ptr);
true
bcx.tcx().with_freevars(id, |fv| {
for (i, freevar) in fv.iter().enumerate() {
let upvar_id = ty::UpvarId { var_id: freevar.def.var_id(),
closure_expr_id: id };
let upvar_capture = bcx.tcx().upvar_capture(upvar_id).unwrap();
let mut upvar_ptr = StructGEP(bcx, llenv, i);
let captured_by_ref = match upvar_capture {
ty::UpvarCapture::ByValue => false,
ty::UpvarCapture::ByRef(..) => {
upvar_ptr = Load(bcx, upvar_ptr);
true
}
};
let node_id = freevar.def.var_id();
bcx.fcx.llupvars.borrow_mut().insert(node_id, upvar_ptr);
if kind == ty::ClosureKind::FnOnce && !captured_by_ref {
let hint = bcx.fcx.lldropflag_hints.borrow().hint_datum(upvar_id.var_id);
bcx.fcx.schedule_drop_mem(arg_scope_id,
upvar_ptr,
node_id_type(bcx, node_id),
hint)
}
};
let node_id = freevar.def.var_id();
bcx.fcx.llupvars.borrow_mut().insert(node_id, upvar_ptr);
if kind == ty::ClosureKind::FnOnce && !captured_by_ref {
let hint = bcx.fcx.lldropflag_hints.borrow().hint_datum(upvar_id.var_id);
bcx.fcx.schedule_drop_mem(arg_scope_id,
upvar_ptr,
node_id_type(bcx, node_id),
hint)
if let Some(env_pointer_alloca) = env_pointer_alloca {
debuginfo::create_captured_var_metadata(
bcx,
node_id,
env_pointer_alloca,
i,
captured_by_ref,
freevar.span);
}
}
if let Some(env_pointer_alloca) = env_pointer_alloca {
debuginfo::create_captured_var_metadata(
bcx,
node_id,
env_pointer_alloca,
i,
captured_by_ref,
freevar.span);
}
}
})
}
pub enum ClosureEnv<'a> {
pub enum ClosureEnv {
NotClosure,
Closure(DefId, &'a [ty::Freevar]),
Closure(DefId, ast::NodeId),
}
impl<'a> ClosureEnv<'a> {
impl ClosureEnv {
pub fn load<'blk,'tcx>(self, bcx: Block<'blk, 'tcx>, arg_scope: ScopeId) {
if let ClosureEnv::Closure(def_id, freevars) = self {
if !freevars.is_empty() {
load_closure_environment(bcx, def_id, arg_scope, freevars);
}
if let ClosureEnv::Closure(def_id, id) = self {
load_closure_environment(bcx, def_id, arg_scope, id);
}
}
}
@ -198,8 +197,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
body: &hir::Block,
id: ast::NodeId,
closure_def_id: DefId, // (*)
closure_substs: &'tcx ty::ClosureSubsts<'tcx>,
closure_expr_attrs: &ThinAttributes)
closure_substs: &ty::ClosureSubsts<'tcx>)
-> Option<Block<'a, 'tcx>>
{
// (*) Note that in the case of inlined functions, the `closure_def_id` will be the
@ -229,9 +227,6 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables, ProjectionMode::Any);
let function_type = infcx.closure_type(closure_def_id, closure_substs);
let freevars: Vec<ty::Freevar> =
tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
let sig = tcx.erase_late_bound_regions(&function_type.sig);
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
@ -250,11 +245,11 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
body,
llfn,
param_substs,
closure_def_id,
id,
closure_expr_attrs.as_attr_slice(),
fn_ty,
Abi::RustCall,
ClosureEnv::Closure(closure_def_id, &freevars));
ClosureEnv::Closure(closure_def_id, id));
// Don't hoist this to the top of the function. It's perfectly legitimate
// to have a zero-size closure (in which case dest will be `Ignore`) and
@ -270,21 +265,23 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
let repr = adt::represent_type(ccx, node_id_type(bcx, id));
// Create the closure.
for (i, freevar) in freevars.iter().enumerate() {
let datum = expr::trans_var(bcx, freevar.def);
let upvar_slot_dest = adt::trans_field_ptr(
bcx, &repr, adt::MaybeSizedValue::sized(dest_addr), Disr(0), i);
let upvar_id = ty::UpvarId { var_id: freevar.def.var_id(),
closure_expr_id: id };
match tcx.upvar_capture(upvar_id).unwrap() {
ty::UpvarCapture::ByValue => {
bcx = datum.store_to(bcx, upvar_slot_dest);
}
ty::UpvarCapture::ByRef(..) => {
Store(bcx, datum.to_llref(), upvar_slot_dest);
tcx.with_freevars(id, |fv| {
for (i, freevar) in fv.iter().enumerate() {
let datum = expr::trans_var(bcx, freevar.def);
let upvar_slot_dest = adt::trans_field_ptr(
bcx, &repr, adt::MaybeSizedValue::sized(dest_addr), Disr(0), i);
let upvar_id = ty::UpvarId { var_id: freevar.def.var_id(),
closure_expr_id: id };
match tcx.upvar_capture(upvar_id).unwrap() {
ty::UpvarCapture::ByValue => {
bcx = datum.store_to(bcx, upvar_slot_dest);
}
ty::UpvarCapture::ByRef(..) => {
Store(bcx, datum.to_llref(), upvar_slot_dest);
}
}
}
}
});
adt::trans_set_discr(bcx, &repr, dest_addr, Disr(0));
Some(bcx)
@ -394,9 +391,8 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
block_arena = TypedArena::new();
fcx = FunctionContext::new(ccx, lloncefn, fn_ty, ast::DUMMY_NODE_ID,
substs.func_substs, None, &block_arena);
let mut bcx = fcx.init(false);
fcx = FunctionContext::new(ccx, lloncefn, fn_ty, None, substs.func_substs, &block_arena);
let mut bcx = fcx.init(false, None);
// the first argument (`self`) will be the (by value) closure env.

View File

@ -217,7 +217,6 @@ use trans::monomorphize::{self, Instance};
use util::nodemap::{FnvHashSet, FnvHashMap, DefIdMap};
use std::hash::{Hash, Hasher};
use std::rc::Rc;
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum TransItemCollectionMode {
@ -263,14 +262,9 @@ pub fn collect_crate_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
debug!("Building translation item graph, beginning at roots");
let mut visited = FnvHashSet();
let mut recursion_depths = DefIdMap();
let mut mir_cache = DefIdMap();
for root in roots {
collect_items_rec(ccx,
root,
&mut visited,
&mut recursion_depths,
&mut mir_cache);
collect_items_rec(ccx, root, &mut visited, &mut recursion_depths);
}
visited
@ -300,27 +294,11 @@ fn collect_roots<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
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`
fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
starting_point: TransItem<'tcx>,
visited: &mut FnvHashSet<TransItem<'tcx>>,
recursion_depths: &mut DefIdMap<usize>,
mir_cache: &mut DefIdMap<CachedMir<'a, 'tcx>>) {
recursion_depths: &mut DefIdMap<usize>) {
if !visited.insert(starting_point.clone()) {
// We've been here already, no need to search again.
return;
@ -346,11 +324,12 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
// Scan the MIR in order to find function calls, closures, and
// drop-glue
let mir = load_mir(ccx, instance.def, mir_cache);
let mir = errors::expect(ccx.sess().diagnostic(), ccx.get_mir(instance.def),
|| format!("Could not find MIR for function: {}", instance));
let mut visitor = MirNeighborCollector {
ccx: ccx,
mir: mir.get_ref(),
mir: &mir,
output: &mut neighbors,
param_substs: ccx.tcx().mk_substs(Substs {
types: instance.params.clone(),
@ -358,12 +337,12 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
})
};
visitor.visit_mir(mir.get_ref());
visitor.visit_mir(&mir);
}
}
for neighbour in neighbors {
collect_items_rec(ccx, neighbour, visited, recursion_depths, mir_cache);
collect_items_rec(ccx, neighbour, visited, recursion_depths);
}
if let Some((def_id, depth)) = recursion_depth_reset {
@ -373,37 +352,6 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
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().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>,
instance: Instance<'tcx>,
recursion_depths: &mut DefIdMap<usize>)

View File

@ -33,6 +33,7 @@ use trans::datum;
use trans::debuginfo::{self, DebugLoc};
use trans::declare;
use trans::machine;
use trans::mir::CachedMir;
use trans::monomorphize;
use trans::type_::Type;
use trans::value::Value;
@ -40,7 +41,6 @@ use middle::ty::{self, Ty, TyCtxt};
use middle::traits::{self, SelectionContext, ProjectionMode};
use middle::ty::fold::{TypeFolder, TypeFoldable};
use rustc_front::hir;
use rustc::mir::repr::Mir;
use util::nodemap::NodeMap;
use arena::TypedArena;
@ -273,7 +273,7 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
// The MIR for this function. At present, this is optional because
// we only have MIR available for things that are local to the
// crate.
pub mir: Option<&'a Mir<'tcx>>,
pub mir: Option<CachedMir<'a, 'tcx>>,
// The ValueRef returned from a call to llvm::LLVMAddFunction; the
// address of the first instruction in the sequence of
@ -325,10 +325,6 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
// Describes the return/argument LLVM types and their ABI handling.
pub fn_ty: FnType,
// The NodeId of the function, or -1 if it doesn't correspond to
// a user-defined function.
pub id: ast::NodeId,
// If this function is being monomorphized, this contains the type
// substitutions used.
pub param_substs: &'tcx Substs<'tcx>,
@ -356,8 +352,8 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
}
impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
pub fn mir(&self) -> &'a Mir<'tcx> {
self.mir.unwrap()
pub fn mir(&self) -> CachedMir<'a, 'tcx> {
self.mir.clone().expect("fcx.mir was empty")
}
pub fn cleanup(&self) {
@ -584,7 +580,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
self.lpad.get()
}
pub fn mir(&self) -> &'blk Mir<'tcx> {
pub fn mir(&self) -> CachedMir<'blk, 'tcx> {
self.fcx.mir()
}
@ -709,7 +705,7 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> {
self.bcx.llbb
}
pub fn mir(&self) -> &'blk Mir<'tcx> {
pub fn mir(&self) -> CachedMir<'blk, 'tcx> {
self.bcx.mir()
}

View File

@ -1003,8 +1003,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
body,
e.id,
def_id,
substs,
&e.attrs);
substs);
}
_ =>
cx.sess().span_bug(

View File

@ -16,6 +16,7 @@ use middle::def::ExportMap;
use middle::def_id::DefId;
use middle::traits;
use rustc::mir::mir_map::MirMap;
use rustc::mir::repr as mir;
use trans::adt;
use trans::base;
use trans::builder::Builder;
@ -23,6 +24,7 @@ use trans::common::BuilderRef_res;
use trans::debuginfo;
use trans::declare;
use trans::glue::DropGlueKind;
use trans::mir::CachedMir;
use trans::monomorphize::Instance;
use trans::collector::{TransItem, TransItemState};
use trans::type_::{Type, TypeNames};
@ -75,6 +77,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
check_overflow: bool,
check_drop_flag_for_sanity: bool,
mir_map: &'a MirMap<'tcx>,
mir_cache: RefCell<DefIdMap<Rc<mir::Mir<'tcx>>>>,
available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
use_dll_storage_attrs: bool,
@ -338,6 +341,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
symbol_hasher: RefCell::new(symbol_hasher),
tcx: tcx,
mir_map: mir_map,
mir_cache: RefCell::new(DefIdMap()),
stats: Stats {
n_glues_created: Cell::new(0),
n_null_glues: Cell::new(0),
@ -817,8 +821,22 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
self.shared.use_dll_storage_attrs()
}
pub fn mir_map(&self) -> &'b MirMap<'tcx> {
self.shared.mir_map
pub fn get_mir(&self, def_id: DefId) -> Option<CachedMir<'b, 'tcx>> {
if def_id.is_local() {
let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
self.shared.mir_map.map.get(&node_id).map(CachedMir::Ref)
} else {
if let Some(mir) = self.shared.mir_cache.borrow().get(&def_id).cloned() {
return Some(CachedMir::Owned(mir));
}
let mir = self.sess().cstore.maybe_get_item_mir(self.tcx(), def_id);
let cached = mir.map(Rc::new);
if let Some(ref mir) = cached {
self.shared.mir_cache.borrow_mut().insert(def_id, mir.clone());
}
cached.map(CachedMir::Owned)
}
}
pub fn translation_items(&self) -> &RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>> {

View File

@ -1141,8 +1141,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
body,
expr.id,
def_id,
substs,
&expr.attrs).unwrap_or(bcx)
substs).unwrap_or(bcx)
}
hir::ExprCall(ref f, ref args) => {
let method = bcx.tcx().tables.borrow().method_map.get(&method_call).cloned();

View File

@ -41,7 +41,6 @@ use trans::type_::Type;
use trans::value::Value;
use arena::TypedArena;
use syntax::ast;
use syntax::codemap::DUMMY_SP;
pub fn trans_exchange_free_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@ -271,10 +270,9 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let empty_substs = tcx.mk_substs(Substs::trans_empty());
let (arena, fcx): (TypedArena<_>, FunctionContext);
arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfn, fn_ty, ast::DUMMY_NODE_ID,
empty_substs, None, &arena);
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &arena);
let bcx = fcx.init(false);
let bcx = fcx.init(false, None);
update_linkage(ccx, llfn, None, OriginalTranslation);

View File

@ -152,8 +152,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
body,
llfn,
empty_substs,
impl_item.id,
&impl_item.attrs);
impl_item.id);
// See linkage comments on items.
if ccx.sess().opts.cg.codegen_units == 1 {
SetLinkage(llfn, InternalLinkage);

View File

@ -1267,12 +1267,11 @@ fn gen_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
sig: ty::Binder(sig)
});
let llfn = declare::define_internal_fn(ccx, name, rust_fn_ty);
let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
let (fcx, block_arena);
block_arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfn, fn_ty, ast::DUMMY_NODE_ID,
ccx.tcx().mk_substs(Substs::trans_empty()),
None, &block_arena);
let bcx = fcx.init(true);
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
let bcx = fcx.init(true, None);
trans(bcx);
fcx.cleanup();
llfn

View File

@ -35,7 +35,7 @@ use trans::type_of::*;
use trans::value::Value;
use middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use syntax::ast::{self, Name};
use syntax::ast::Name;
use syntax::codemap::DUMMY_SP;
// drop_glue pointer, size, align.
@ -95,9 +95,8 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
let empty_substs = tcx.mk_substs(Substs::trans_empty());
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
block_arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfn, fn_ty, ast::DUMMY_NODE_ID,
empty_substs, None, &block_arena);
let mut bcx = fcx.init(false);
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
let mut bcx = fcx.init(false, None);
assert!(!fcx.needs_ret_allocas);

View File

@ -34,7 +34,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
debug!("trans_block({:?})", bb);
let mut bcx = self.bcx(bb);
let data = self.mir.basic_block_data(bb);
let mir = self.mir.clone();
let data = mir.basic_block_data(bb);
// MSVC SEH bits
let (cleanup_pad, cleanup_bundle) = if let Some((cp, cb)) = self.make_cleanup_pad(bb) {

View File

@ -10,20 +10,41 @@
use libc::c_uint;
use llvm::{self, ValueRef};
use middle::ty;
use rustc::mir::repr as mir;
use rustc::mir::tcx::LvalueTy;
use trans::base;
use trans::build;
use trans::common::{self, Block, BlockAndBuilder, FunctionContext};
use trans::expr;
use std::ops::Deref;
use std::rc::Rc;
use self::lvalue::LvalueRef;
use self::operand::OperandRef;
#[derive(Clone)]
pub enum CachedMir<'mir, 'tcx: 'mir> {
Ref(&'mir mir::Mir<'tcx>),
Owned(Rc<mir::Mir<'tcx>>)
}
impl<'mir, 'tcx: 'mir> Deref for CachedMir<'mir, 'tcx> {
type Target = mir::Mir<'tcx>;
fn deref(&self) -> &mir::Mir<'tcx> {
match *self {
CachedMir::Ref(r) => r,
CachedMir::Owned(ref rc) => rc
}
}
}
// FIXME DebugLoc is always None right now
/// Master context for translating MIR.
pub struct MirContext<'bcx, 'tcx:'bcx> {
mir: &'bcx mir::Mir<'tcx>,
mir: CachedMir<'bcx, 'tcx>,
/// Function context
fcx: &'bcx common::FunctionContext<'bcx, 'tcx>,
@ -77,7 +98,7 @@ enum TempRef<'tcx> {
///////////////////////////////////////////////////////////////////////////
pub fn trans_mir<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
let bcx = fcx.init(false).build();
let bcx = fcx.init(false, None).build();
let mir = bcx.mir();
let mir_blocks = mir.all_basic_blocks();
@ -85,7 +106,7 @@ pub fn trans_mir<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
// Analyze the temps to determine which must be lvalues
// FIXME
let lvalue_temps = bcx.with_block(|bcx| {
analyze::lvalue_temps(bcx, mir)
analyze::lvalue_temps(bcx, &mir)
});
// Allocate variable and temp allocas
@ -107,7 +128,7 @@ pub fn trans_mir<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
TempRef::Operand(None)
})
.collect();
let args = arg_value_refs(&bcx, mir);
let args = arg_value_refs(&bcx, &mir);
// Allocate a `Block` for every basic block
let block_bcxs: Vec<Block<'blk,'tcx>> =

View File

@ -151,7 +151,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
if trans_everywhere || is_first {
trans_fn(ccx, decl, body, lldecl, psubsts, fn_node_id, attrs);
trans_fn(ccx, decl, body, lldecl, psubsts, fn_node_id);
}
}