diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index c58e548f69ddd..d55c156cead6e 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -39,7 +39,7 @@ use rustc::middle::weak_lang_items; use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder}; use rustc::middle::cstore::{EncodedMetadata}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx}; +use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::ty::query::Providers; use rustc::middle::cstore::{self, LinkagePreference}; use rustc::middle::exported_symbols; @@ -76,6 +76,7 @@ use interfaces::*; use std::any::Any; use std::cmp; use std::ffi::CString; +use std::marker; use std::ops::{Deref, DerefMut}; use std::sync::mpsc; use std::time::{Instant, Duration}; @@ -90,27 +91,29 @@ use mir::operand::OperandValue; use rustc_codegen_utils::check_for_rustc_errors_attr; -pub struct StatRecorder<'a, 'll: 'a, 'tcx: 'll> { - cx: &'a CodegenCx<'ll, 'tcx>, +pub struct StatRecorder<'a, 'tcx, Cx: 'a + CodegenMethods<'tcx>> { + cx: &'a Cx, name: Option, istart: usize, + _marker: marker::PhantomData<&'tcx ()>, } -impl StatRecorder<'a, 'll, 'tcx> { - pub fn new(cx: &'a CodegenCx<'ll, 'tcx>, name: String) -> Self { - let istart = cx.stats.borrow().n_llvm_insns; +impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> StatRecorder<'a, 'tcx, Cx> { + pub fn new(cx: &'a Cx, name: String) -> Self { + let istart = cx.stats().borrow().n_llvm_insns; StatRecorder { cx, name: Some(name), istart, + _marker: marker::PhantomData, } } } -impl Drop for StatRecorder<'a, 'll, 'tcx> { +impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> Drop for StatRecorder<'a, 'tcx, Cx> { fn drop(&mut self) { if self.cx.sess().codegen_stats() { - let mut stats = self.cx.stats.borrow_mut(); + let mut stats = self.cx.stats().borrow_mut(); let iend = stats.n_llvm_insns; stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart)); stats.n_fns += 1; @@ -449,10 +452,13 @@ pub fn memcpy_ty<'a, 'tcx: 'a, Builder: BuilderMethods<'a, 'tcx>>( bx.memcpy(dst, dst_align, src, src_align, bx.cx().const_usize(size), flags); } -pub fn codegen_instance(cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) { +pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( + cx: &'a Bx::CodegenCx, + instance: Instance<'tcx>, +) { let _s = if cx.sess().codegen_stats() { let mut instance_name = String::new(); - DefPathBasedNames::new(cx.tcx, true, true) + DefPathBasedNames::new(cx.tcx(), true, true) .push_def_path(instance.def_id(), &mut instance_name); Some(StatRecorder::new(cx, instance_name)) } else { @@ -464,16 +470,16 @@ pub fn codegen_instance(cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) { // release builds. info!("codegen_instance({})", instance); - let sig = instance.fn_sig(cx.tcx); - let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); + let sig = instance.fn_sig(cx.tcx()); + let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - let lldecl = cx.instances.borrow().get(&instance).cloned().unwrap_or_else(|| + let lldecl = cx.instances().borrow().get(&instance).cloned().unwrap_or_else(|| bug!("Instance `{:?}` not already declared", instance)); - cx.stats.borrow_mut().n_closures += 1; + cx.stats().borrow_mut().n_closures += 1; - let mir = cx.tcx.instance_mir(instance.def); - mir::codegen_mir::(cx, lldecl, &mir, instance, sig); + let mir = cx.tcx().instance_mir(instance.def); + mir::codegen_mir::(cx, lldecl, &mir, instance, sig); } pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index d7f850b84a919..1ccab0ec81a89 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -417,6 +417,14 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn check_overflow(&self) -> bool { self.check_overflow } + + fn stats(&self) -> &RefCell { + &self.stats + } + + fn codegen_unit(&self) -> &Arc> { + &self.codegen_unit + } } impl IntrinsicDeclarationMethods<'tcx> for CodegenCx<'b, 'tcx> { diff --git a/src/librustc_codegen_llvm/interfaces/declare.rs b/src/librustc_codegen_llvm/interfaces/declare.rs index d8a7382e45ff2..e3cdc93e5d213 100644 --- a/src/librustc_codegen_llvm/interfaces/declare.rs +++ b/src/librustc_codegen_llvm/interfaces/declare.rs @@ -9,6 +9,9 @@ // except according to those terms. use super::backend::Backend; +use monomorphize::Instance; +use rustc::hir::def_id::DefId; +use rustc::mir::mono::{Linkage, Visibility}; use rustc::ty; pub trait DeclareMethods<'tcx>: Backend<'tcx> { @@ -22,3 +25,20 @@ pub trait DeclareMethods<'tcx>: Backend<'tcx> { fn get_declared_value(&self, name: &str) -> Option; fn get_defined_value(&self, name: &str) -> Option; } + +pub trait PreDefineMethods<'tcx>: Backend<'tcx> { + fn predefine_static( + &self, + def_id: DefId, + linkage: Linkage, + visibility: Visibility, + symbol_name: &str, + ); + fn predefine_fn( + &self, + instance: Instance<'tcx>, + linkage: Linkage, + visibility: Visibility, + symbol_name: &str, + ); +} diff --git a/src/librustc_codegen_llvm/interfaces/misc.rs b/src/librustc_codegen_llvm/interfaces/misc.rs index eb278a36b09f2..a9e6f930a8d63 100644 --- a/src/librustc_codegen_llvm/interfaces/misc.rs +++ b/src/librustc_codegen_llvm/interfaces/misc.rs @@ -10,10 +10,13 @@ use super::backend::Backend; use libc::c_uint; +use monomorphize::partitioning::CodegenUnit; +use rustc::mir::mono::Stats; use rustc::session::Session; use rustc::ty::{self, Instance, Ty}; use rustc::util::nodemap::FxHashMap; use std::cell::RefCell; +use std::sync::Arc; pub trait MiscMethods<'tcx>: Backend<'tcx> { fn vtables( @@ -26,4 +29,6 @@ pub trait MiscMethods<'tcx>: Backend<'tcx> { fn eh_personality(&self) -> Self::Value; fn eh_unwind_resume(&self) -> Self::Value; fn sess(&self) -> &Session; + fn stats(&self) -> &RefCell; + fn codegen_unit(&self) -> &Arc>; } diff --git a/src/librustc_codegen_llvm/interfaces/mod.rs b/src/librustc_codegen_llvm/interfaces/mod.rs index d1365fb62a6ab..6ff662614167e 100644 --- a/src/librustc_codegen_llvm/interfaces/mod.rs +++ b/src/librustc_codegen_llvm/interfaces/mod.rs @@ -26,7 +26,7 @@ pub use self::backend::{Backend, BackendTypes}; pub use self::builder::BuilderMethods; pub use self::consts::ConstMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; -pub use self::declare::DeclareMethods; +pub use self::declare::{DeclareMethods, PreDefineMethods}; pub use self::intrinsic::{IntrinsicCallMethods, IntrinsicDeclarationMethods}; pub use self::misc::MiscMethods; pub use self::statics::StaticMethods; @@ -47,6 +47,7 @@ pub trait CodegenMethods<'tcx>: + IntrinsicDeclarationMethods<'tcx> + DeclareMethods<'tcx> + AsmMethods<'tcx> + + PreDefineMethods<'tcx> { } @@ -61,6 +62,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where + IntrinsicDeclarationMethods<'tcx> + DeclareMethods<'tcx> + AsmMethods<'tcx> + + PreDefineMethods<'tcx> {} pub trait HasCodegen<'tcx>: Backend<'tcx> { diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index 2e54c52cb0e2e..041cfbf00c6fe 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -25,24 +25,27 @@ use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::mono::{Linkage, Visibility}; use rustc::ty::TypeFoldable; -use rustc::ty::layout::LayoutOf; +use rustc::ty::layout::{LayoutOf, HasTyCtxt}; use std::fmt; +use builder::Builder; use interfaces::*; pub use rustc::mir::mono::MonoItem; pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt; -pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { - fn define(&self, cx: &CodegenCx<'a, 'tcx>) { +pub trait MonoItemExt<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> : + fmt::Debug + BaseMonoItemExt<'a, 'tcx> +{ + fn define(&self, cx: &'a Bx::CodegenCx) { debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}", - self.to_string(cx.tcx), + self.to_string(cx.tcx()), self.to_raw_string(), - cx.codegen_unit.name()); + cx.codegen_unit().name()); match *self.as_mono_item() { MonoItem::Static(def_id) => { - let tcx = cx.tcx; + let tcx = cx.tcx(); let is_mutable = match tcx.describe_def(def_id) { Some(Def::Static(_, is_mutable)) => is_mutable, Some(other) => { @@ -55,7 +58,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { cx.codegen_static(def_id, is_mutable); } MonoItem::GlobalAsm(node_id) => { - let item = cx.tcx.hir.expect_item(node_id); + let item = cx.tcx().hir.expect_item(node_id); if let hir::ItemKind::GlobalAsm(ref ga) = item.node { cx.codegen_global_asm(ga); } else { @@ -63,43 +66,43 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { } } MonoItem::Fn(instance) => { - base::codegen_instance(&cx, instance); + base::codegen_instance::(&cx, instance); } } debug!("END IMPLEMENTING '{} ({})' in cgu {}", - self.to_string(cx.tcx), + self.to_string(cx.tcx()), self.to_raw_string(), - cx.codegen_unit.name()); + cx.codegen_unit().name()); } fn predefine(&self, - cx: &CodegenCx<'a, 'tcx>, + cx: &'a Bx::CodegenCx, linkage: Linkage, visibility: Visibility) { debug!("BEGIN PREDEFINING '{} ({})' in cgu {}", - self.to_string(cx.tcx), + self.to_string(cx.tcx()), self.to_raw_string(), - cx.codegen_unit.name()); + cx.codegen_unit().name()); - let symbol_name = self.symbol_name(cx.tcx).as_str(); + let symbol_name = self.symbol_name(cx.tcx()).as_str(); debug!("symbol {}", &symbol_name); match *self.as_mono_item() { MonoItem::Static(def_id) => { - predefine_static(cx, def_id, linkage, visibility, &symbol_name); + cx.predefine_static(def_id, linkage, visibility, &symbol_name); } MonoItem::Fn(instance) => { - predefine_fn(cx, instance, linkage, visibility, &symbol_name); + cx.predefine_fn(instance, linkage, visibility, &symbol_name); } MonoItem::GlobalAsm(..) => {} } debug!("END PREDEFINING '{} ({})' in cgu {}", - self.to_string(cx.tcx), + self.to_string(cx.tcx()), self.to_raw_string(), - cx.codegen_unit.name()); + cx.codegen_unit().name()); } fn to_raw_string(&self) -> String { @@ -119,68 +122,70 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { } } -impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {} +impl MonoItemExt<'a, 'tcx, Builder<'a, 'll, 'tcx>> for MonoItem<'tcx> {} -fn predefine_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - def_id: DefId, - linkage: Linkage, - visibility: Visibility, - symbol_name: &str) { - let instance = Instance::mono(cx.tcx, def_id); - let ty = instance.ty(cx.tcx); - let llty = cx.layout_of(ty).llvm_type(cx); - - let g = cx.define_global(symbol_name, llty).unwrap_or_else(|| { - cx.sess().span_fatal(cx.tcx.def_span(def_id), - &format!("symbol `{}` is already defined", symbol_name)) - }); - - unsafe { - llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage)); - llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility)); - } +impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { + fn predefine_static(&self, + def_id: DefId, + linkage: Linkage, + visibility: Visibility, + symbol_name: &str) { + let instance = Instance::mono(self.tcx, def_id); + let ty = instance.ty(self.tcx); + let llty = self.layout_of(ty).llvm_type(self); - cx.instances.borrow_mut().insert(instance, g); -} + let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { + self.sess().span_fatal(self.tcx.def_span(def_id), + &format!("symbol `{}` is already defined", symbol_name)) + }); -fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - instance: Instance<'tcx>, - linkage: Linkage, - visibility: Visibility, - symbol_name: &str) { - assert!(!instance.substs.needs_infer() && - !instance.substs.has_param_types()); - - let mono_sig = instance.fn_sig(cx.tcx); - let attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); - let lldecl = cx.declare_fn(symbol_name, mono_sig); - unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; - base::set_link_section(lldecl, &attrs); - if linkage == Linkage::LinkOnceODR || - linkage == Linkage::WeakODR { - llvm::SetUniqueComdat(cx.llmod, lldecl); + unsafe { + llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage)); + llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility)); + } + + self.instances.borrow_mut().insert(instance, g); } - // If we're compiling the compiler-builtins crate, e.g. the equivalent of - // compiler-rt, then we want to implicitly compile everything with hidden - // visibility as we're going to link this object all over the place but - // don't want the symbols to get exported. - if linkage != Linkage::Internal && linkage != Linkage::Private && - cx.tcx.is_compiler_builtins(LOCAL_CRATE) { - unsafe { - llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden); + fn predefine_fn(&self, + instance: Instance<'tcx>, + linkage: Linkage, + visibility: Visibility, + symbol_name: &str) { + assert!(!instance.substs.needs_infer() && + !instance.substs.has_param_types()); + + let mono_sig = instance.fn_sig(self.tcx()); + let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); + let lldecl = self.declare_fn(symbol_name, mono_sig); + unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; + base::set_link_section(lldecl, &attrs); + if linkage == Linkage::LinkOnceODR || + linkage == Linkage::WeakODR { + llvm::SetUniqueComdat(self.llmod, lldecl); } - } else { - unsafe { - llvm::LLVMRustSetVisibility(lldecl, base::visibility_to_llvm(visibility)); + + // If we're compiling the compiler-builtins crate, e.g. the equivalent of + // compiler-rt, then we want to implicitly compile everything with hidden + // visibility as we're going to link this object all over the place but + // don't want the symbols to get exported. + if linkage != Linkage::Internal && linkage != Linkage::Private && + self.tcx.is_compiler_builtins(LOCAL_CRATE) { + unsafe { + llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden); + } + } else { + unsafe { + llvm::LLVMRustSetVisibility(lldecl, base::visibility_to_llvm(visibility)); + } } - } - debug!("predefine_fn: mono_sig = {:?} instance = {:?}", mono_sig, instance); - if instance.def.is_inline(cx.tcx) { - attributes::inline(cx, lldecl, attributes::InlineAttr::Hint); - } - attributes::from_fn_attrs(cx, lldecl, Some(instance.def.def_id())); + debug!("predefine_fn: mono_sig = {:?} instance = {:?}", mono_sig, instance); + if instance.def.is_inline(self.tcx) { + attributes::inline(self, lldecl, attributes::InlineAttr::Hint); + } + attributes::from_fn_attrs(self, lldecl, Some(instance.def.def_id())); - cx.instances.borrow_mut().insert(instance, lldecl); + self.instances.borrow_mut().insert(instance, lldecl); + } }