use super::ModuleCodegen;
use super::ModuleKind;
use super::CachedModuleCodegen;
+use super::LlvmCodegenBackend;
use abi;
use back::write;
use callee;
use rustc_mir::monomorphize::item::DefPathBasedNames;
use common::{self, IntPredicate, RealPredicate, TypeKind};
-use context::CodegenCx;
-use debuginfo;
use meth;
use mir;
use monomorphize::Instance;
}
}
-fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+fn assert_and_save_dep_graph<'ll, 'tcx>(tcx: TyCtxt<'ll, 'tcx, 'tcx>) {
time(tcx.sess,
"assert dep graph",
|| rustc_incremental::assert_dep_graph(tcx));
}
}
-fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+fn compile_codegen_unit<'ll, 'tcx>(tcx: TyCtxt<'ll, 'tcx, 'tcx>,
cgu_name: InternedString)
-> Stats {
let start_time = Instant::now();
cost);
return stats;
- fn module_codegen<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ fn module_codegen<'ll, 'tcx>(
+ tcx: TyCtxt<'ll, 'tcx, 'tcx>,
cgu_name: InternedString)
-> (Stats, ModuleCodegen<ModuleLlvm>)
{
+ let backend = LlvmCodegenBackend(());
let cgu = tcx.codegen_unit(cgu_name);
-
// Instantiate monomorphizations without filling out definitions yet...
- let llvm_module = ModuleLlvm::new(tcx.sess, &cgu_name.as_str());
+ let llvm_module = backend.new_metadata(tcx.sess, &cgu_name.as_str());
let stats = {
- let cx = CodegenCx::new(tcx, cgu, &llvm_module);
+ let cx = backend.new_codegen_context(tcx, cgu, &llvm_module);
let mono_items = cx.codegen_unit
.items_in_deterministic_order(cx.tcx);
for &(mono_item, (linkage, visibility)) in &mono_items {
- mono_item.predefine(&cx, linkage, visibility);
+ mono_item.predefine::<Builder<&Value>>(&cx, linkage, visibility);
}
// ... and now that we have everything pre-defined, fill out those definitions.
for &(mono_item, _) in &mono_items {
- mono_item.define(&cx);
+ mono_item.define::<Builder<&Value>>(&cx);
}
// If this codegen unit contains the main function, also create the
maybe_create_entry_wrapper::<Builder<&Value>>(&cx);
// Run replace-all-uses-with for statics that need it
- for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
- unsafe {
- let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
- llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
- llvm::LLVMDeleteGlobal(old_g);
- }
+ for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
+ cx.static_replace_all_uses(old_g, new_g)
}
// Create the llvm.used variable
// This variable has type [N x i8*] and is stored in the llvm.metadata section
- if !cx.used_statics.borrow().is_empty() {
- let name = const_cstr!("llvm.used");
- let section = const_cstr!("llvm.metadata");
- let array = cx.const_array(
- &cx.type_ptr_to(cx.type_i8()),
- &*cx.used_statics.borrow()
- );
-
- unsafe {
- let g = llvm::LLVMAddGlobal(cx.llmod,
- cx.val_ty(array),
- name.as_ptr());
- llvm::LLVMSetInitializer(g, array);
- llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
- llvm::LLVMSetSection(g, section.as_ptr());
- }
+ if !cx.used_statics().borrow().is_empty() {
+ cx.create_used_variable()
}
// Finalize debuginfo
if cx.sess().opts.debuginfo != DebugInfo::None {
- debuginfo::finalize(&cx);
+ cx.debuginfo_finalize();
}
- cx.stats.into_inner()
+ cx.consume_stats().into_inner()
};
(stats, ModuleCodegen {
}
}
}
+ fn static_replace_all_uses(&self, old_g: &'ll Value, new_g: &'ll Value) {
+ unsafe {
+ let bitcast = llvm::LLVMConstPointerCast(new_g, self.val_ty(old_g));
+ llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
+ llvm::LLVMDeleteGlobal(old_g);
+ }
+ }
}
&self.stats
}
+ fn consume_stats(self) -> RefCell<Stats> {
+ self.stats
+ }
+
fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>> {
&self.codegen_unit
}
+ fn statics_to_rauw(&self) -> &RefCell<Vec<(&'ll Value, &'ll Value)>> {
+ &self.statics_to_rauw
+ }
+
+ fn used_statics(&self) -> &RefCell<Vec<&'ll Value>> {
+ &self.used_statics
+ }
+
fn set_frame_pointer_elimination(&self, llfn: &'ll Value) {
attributes::set_frame_pointer_elimination(self, llfn)
}
fn apply_target_cpu_attr(&self, llfn: &'ll Value) {
attributes::apply_target_cpu_attr(self, llfn)
}
+
+
+ fn create_used_variable(&self) {
+ let name = const_cstr!("llvm.used");
+ let section = const_cstr!("llvm.metadata");
+ let array = self.const_array(
+ &self.type_ptr_to(self.type_i8()),
+ &*self.used_statics.borrow()
+ );
+
+ unsafe {
+ let g = llvm::LLVMAddGlobal(self.llmod,
+ self.val_ty(array),
+ name.as_ptr());
+ llvm::LLVMSetInitializer(g, array);
+ llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
+ llvm::LLVMSetSection(g, section.as_ptr());
+ }
+ }
}
impl IntrinsicDeclarationMethods<'tcx> for CodegenCx<'b, 'tcx> {
) -> &'ll DILexicalBlock {
metadata::extend_scope_to_file(&self, scope_metadata, file, defining_crate)
}
+
+ fn debuginfo_finalize(&self) {
+ finalize(self)
+ }
}
use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout};
use rustc::ty::Ty;
-use super::CodegenObject;
+use super::{CodegenMethods, CodegenObject};
+use monomorphize::partitioning::CodegenUnit;
use rustc::middle::allocator::AllocatorKind;
use rustc::middle::cstore::EncodedMetadata;
use rustc::session::Session;
use rustc::ty::TyCtxt;
use std::any::Any;
use std::sync::mpsc::Receiver;
+use std::sync::Arc;
use time_graph::TimeGraph;
use ModuleCodegen;
{}
pub trait BackendMethods {
- type Metadata;
+ type Module;
type OngoingCodegen;
- fn new_metadata(&self, sess: &Session, mod_name: &str) -> Self::Metadata;
- fn write_metadata<'a, 'gcx>(
+ fn new_metadata(&self, sess: &Session, mod_name: &str) -> Self::Module;
+ fn write_metadata<'b, 'gcx>(
&self,
- tcx: TyCtxt<'a, 'gcx, 'gcx>,
- metadata: &Self::Metadata,
+ tcx: TyCtxt<'b, 'gcx, 'gcx>,
+ metadata: &Self::Module,
) -> EncodedMetadata;
- fn codegen_allocator(&self, tcx: TyCtxt, mods: &Self::Metadata, kind: AllocatorKind);
+ fn codegen_allocator(&self, tcx: TyCtxt, mods: &Self::Module, kind: AllocatorKind);
fn start_async_codegen(
&self,
&self,
codegen: &Self::OngoingCodegen,
tcx: TyCtxt,
- module: ModuleCodegen<Self::Metadata>,
+ module: ModuleCodegen<Self::Module>,
);
fn codegen_aborted(codegen: Self::OngoingCodegen);
fn codegen_finished(&self, codegen: &Self::OngoingCodegen, tcx: TyCtxt);
fn check_for_errors(&self, codegen: &Self::OngoingCodegen, sess: &Session);
fn wait_for_signal_to_codegen_item(&self, codegen: &Self::OngoingCodegen);
}
+
+pub trait BackendCodegenCxMethods<'a, 'tcx: 'a>: BackendMethods {
+ type CodegenCx: CodegenMethods<'tcx>;
+
+ fn new_codegen_context(
+ &self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ codegen_unit: Arc<CodegenUnit<'tcx>>,
+ llvm_module: &'a Self::Module,
+ ) -> Self::CodegenCx;
+}
file: &SourceFile,
defining_crate: CrateNum,
) -> Self::DIScope;
+ fn debuginfo_finalize(&self);
}
pub trait DebugInfoBuilderMethods<'tcx>: HasCodegen<'tcx> {
fn eh_unwind_resume(&self) -> Self::Value;
fn sess(&self) -> &Session;
fn stats(&self) -> &RefCell<Stats>;
+ fn consume_stats(self) -> RefCell<Stats>;
fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>;
+ fn statics_to_rauw(&self) -> &RefCell<Vec<(Self::Value, Self::Value)>>;
+ fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
fn set_frame_pointer_elimination(&self, llfn: Self::Value);
fn apply_target_cpu_attr(&self, llfn: Self::Value);
+ fn create_used_variable(&self);
}
pub use self::abi::{AbiBuilderMethods, AbiMethods};
pub use self::asm::{AsmBuilderMethods, AsmMethods};
-pub use self::backend::{Backend, BackendMethods, BackendTypes};
+pub use self::backend::{Backend, BackendCodegenCxMethods, BackendMethods, BackendTypes};
pub use self::builder::BuilderMethods;
pub use self::consts::ConstMethods;
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
fn get_static(&self, def_id: DefId) -> Self::Value;
fn codegen_static(&self, def_id: DefId, is_mutable: bool);
+ fn static_replace_all_uses(&self, old_g: Self::Value, new_g: Self::Value);
}
use time_graph::TimeGraph;
use std::sync::mpsc::Receiver;
use back::write::{self, OngoingCodegen};
+use context::CodegenCx;
+use monomorphize::partitioning::CodegenUnit;
pub use llvm_util::target_features;
use std::any::Any;
+use std::sync::Arc;
use std::sync::mpsc;
use rustc_data_structures::sync::Lrc;
pub struct LlvmCodegenBackend(());
impl BackendMethods for LlvmCodegenBackend {
- type Metadata = ModuleLlvm;
+ type Module = ModuleLlvm;
type OngoingCodegen = OngoingCodegen;
fn new_metadata(&self, sess: &Session, mod_name: &str) -> ModuleLlvm {
ModuleLlvm::new(sess, mod_name)
}
- fn write_metadata<'a, 'gcx>(
+ fn write_metadata<'b, 'gcx>(
&self,
- tcx: TyCtxt<'a, 'gcx, 'gcx>,
+ tcx: TyCtxt<'b, 'gcx, 'gcx>,
metadata: &ModuleLlvm
) -> EncodedMetadata {
base::write_metadata(tcx, metadata)
}
}
+impl<'a, 'tcx: 'a> BackendCodegenCxMethods<'a, 'tcx> for LlvmCodegenBackend {
+ type CodegenCx = CodegenCx<'a, 'tcx>;
+
+ fn new_codegen_context(
+ &self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ codegen_unit: Arc<CodegenUnit<'tcx>>,
+ llvm_module: &'a ModuleLlvm
+ ) -> CodegenCx<'a, 'tcx> {
+ CodegenCx::new(tcx, codegen_unit, llvm_module)
+ }
+}
+
impl !Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
impl !Sync for LlvmCodegenBackend {}
use rustc::ty::TypeFoldable;
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: 'a, Bx: BuilderMethods<'a, 'tcx>> :
- fmt::Debug + BaseMonoItemExt<'a, 'tcx>
-{
- fn define(&self, cx: &'a Bx::CodegenCx) {
+pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
+ fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) {
debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
self.to_string(cx.tcx()),
self.to_raw_string(),
cx.codegen_unit().name());
}
- fn predefine(&self,
- cx: &'a Bx::CodegenCx,
- linkage: Linkage,
- visibility: Visibility) {
+ fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
+ &self,
+ cx: &'a Bx::CodegenCx,
+ linkage: Linkage,
+ visibility: Visibility
+ ) {
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
self.to_string(cx.tcx()),
self.to_raw_string(),
}
}
-impl MonoItemExt<'a, 'tcx, Builder<'a, 'll, 'tcx>> for MonoItem<'tcx> {}
+impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {}
impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn predefine_static(&self,