From db183dbb8a110a85caaaafa3b127750e485ffc89 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Mon, 2 Dec 2019 14:12:05 +0000 Subject: [PATCH 1/2] Cache the results of the monomorphisation call resolver. To cut a long story short, in order to determine static call targets (where possible) it is necessary to call Instance::resolve(). However, only the monomorphisation stage is permitted to do so. This change caches the results of resolutions so that we can use them during SIR lowering. We also utilise the new CallOperand::Virtual variant for calls which cannot be statically known at compile time. Discussion here: https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Calls.20in.20MIR --- src/librustc/ty/context.rs | 7 ++++- src/librustc_mir/monomorphize/collector.rs | 11 ++++++++ src/librustc_yk_sections/emit_sir.rs | 31 +++++++++++++++------- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0906d9ebd8e..97e753652a5 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -28,7 +28,7 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; use crate::traits; use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals}; -use crate::ty::{self, DefIdTree, Ty, TypeAndMut}; +use crate::ty::{self, DefIdTree, Ty, TypeAndMut, Instance}; use crate::ty::{TyS, TyKind, List}; use crate::ty::{AdtKind, AdtDef, Region, Const}; use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; @@ -1107,6 +1107,10 @@ pub struct GlobalCtxt<'tcx> { layout_interner: ShardedHashMap<&'tcx LayoutDetails, ()>, output_filenames: Arc, + + /// Caches the results of `Instance::resolve()` so that Yorick's SIR lowering can use them + /// later. Normally only the monomorphisation collector can resolve instances. + pub call_resolution_map: Lock), Instance<'tcx>>>>, } impl<'tcx> TyCtxt<'tcx> { @@ -1302,6 +1306,7 @@ impl<'tcx> TyCtxt<'tcx> { allocation_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames.clone()), + call_resolution_map: Lock::new(None), } } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 5e31b80bec6..32d521e1ad4 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -285,6 +285,13 @@ pub fn collect_crate_mono_items( tcx: TyCtxt<'_>, mode: MonoItemCollectionMode, ) -> (FxHashSet>, InliningMap<'_>) { + // Initialise Yorick call resolution map. + { + let mut resolutions = tcx.call_resolution_map.borrow_mut(); + assert!(resolutions.is_none()); // Should only be initialised once. + *resolutions = Some(FxHashMap::default()); + } + let _prof_timer = tcx.prof.generic_activity("monomorphization_collector"); let roots = time(tcx.sess, "collecting roots", || { @@ -727,6 +734,10 @@ fn visit_fn_use<'tcx>( ty::Instance::resolve_for_fn_ptr }; let instance = resolver(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap(); + + let mut resolutions = tcx.call_resolution_map.borrow_mut(); + resolutions.as_mut().unwrap().insert((def_id, substs), instance); + visit_instance_use(tcx, instance, is_direct_call, output); } } diff --git a/src/librustc_yk_sections/emit_sir.rs b/src/librustc_yk_sections/emit_sir.rs index 8fc6ee4a136..806f26ffdd9 100644 --- a/src/librustc_yk_sections/emit_sir.rs +++ b/src/librustc_yk_sections/emit_sir.rs @@ -13,7 +13,7 @@ //! //! Serialisation itself is performed by an external library: ykpack. -use rustc::ty::{self, TyCtxt, TyS, Const, Ty, Instance}; +use rustc::ty::{self, TyCtxt, TyS, Const, Ty}; use syntax::ast::{UintTy, IntTy}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::{ @@ -34,6 +34,7 @@ use std::convert::{TryFrom, TryInto}; use rustc_index::vec::IndexVec; use ykpack; use rustc::ty::fold::TypeFoldable; +use rustc::ty::InstanceDef; use syntax_pos::sym; const SECTION_NAME: &'static str = ".yk_sir"; @@ -210,14 +211,26 @@ impl<'a, 'tcx> ConvCx<'a, 'tcx> { }, .. }, .. }, ..) = func { - // A statically known call target. - let inst = Instance::new(*target_def_id, substs); - let sym_name = match substs.needs_subst() { - // If the instance isn't full instantiated, then it has no symbol name. - true => None, - false => Some(String::from(&*self.tcx.symbol_name(inst).name.as_str())), - }; - ykpack::CallOperand::Fn(self.lower_def_id(target_def_id), sym_name) + let map = self.tcx.call_resolution_map.borrow(); + let maybe_inst = map.as_ref().unwrap().get(&(*target_def_id, substs)); + if let Some(inst) = maybe_inst { + let sym_name = match substs.needs_subst() { + // If the instance isn't fully instantiated, then it has no symbol name. + true => None, + false => Some(String::from( + &*self.tcx.symbol_name(*inst).name.as_str())), + }; + + match inst.def { + InstanceDef::Item(def_id) => ykpack::CallOperand::Fn( + self.lower_def_id(&def_id), sym_name), + InstanceDef::Virtual(def_id, _) => ykpack::CallOperand::Virtual( + self.lower_def_id(&def_id), sym_name), + _ => ykpack::CallOperand::Unknown, + } + } else { + ykpack::CallOperand::Unknown + } } else { // FIXME -- implement other callables. ykpack::CallOperand::Unknown From de2c5d936f0da96dfd580f8b836a6dca2f6a3845 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Mon, 2 Dec 2019 14:18:38 +0000 Subject: [PATCH 2/2] Cycle breaker. --- src/librustc_yk_sections/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_yk_sections/Cargo.toml b/src/librustc_yk_sections/Cargo.toml index 352628c6ae9..c2894b57145 100644 --- a/src/librustc_yk_sections/Cargo.toml +++ b/src/librustc_yk_sections/Cargo.toml @@ -13,7 +13,7 @@ test = false [dependencies] rustc = { path = "../librustc" } rustc_yk_link = { path = "../librustc_yk_link" } -ykpack = { git = "https://github.com/softdevteam/yk" } +ykpack = { git = "https://github.com/vext01/yk", rev = "b4da4c7d08661b38f265fe072f88d354a2c4c8fa" } rustc_index = { path = "../librustc_index" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_data_structures = { path = "../librustc_data_structures" }