diff --git a/Cargo.toml b/Cargo.toml index f3b9e843788..0da280f24e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,9 @@ edition = "2018" [lib] crate-type = ["dylib"] +[features] +backend_object = ["object/write"] + [dependencies] # These have to be in sync with each other cranelift = { git = "https://github.com/CraneStation/cranelift.git" } @@ -29,7 +32,7 @@ libloading = "0.5.1" [dependencies.object] version = "0.14.0" default-features = false -features = ["compression", "read", "std", "write"] # We don't need WASM support +features = ["compression", "read", "std"] # We don't need WASM support # Uncomment to use local checkout of cranelift #[patch."https://github.com/CraneStation/cranelift.git"] diff --git a/src/backend.rs b/src/backend.rs index 429c48ba0e3..449e2a5cc26 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,10 +1,13 @@ use std::collections::HashMap; -use cranelift_module::FuncId; +use rustc::session::Session; + +use cranelift_module::{FuncId, Module}; use faerie::*; use object::{SectionKind, RelocationKind, RelocationEncoding}; use object::write::*; +use cranelift_faerie::{FaerieBackend, FaerieBuilder, FaerieProduct, FaerieTrapCollection}; use cranelift_object::*; use gimli::SectionId; @@ -73,11 +76,11 @@ pub trait WriteDebugInfo { ); } -impl WriteDebugInfo for Artifact { +impl WriteDebugInfo for FaerieProduct { type SectionId = SectionId; fn add_debug_section(&mut self, id: SectionId, data: Vec<u8>) -> SectionId { - self.declare_with(id.name(), Decl::section(faerie::SectionKind::Debug), data).unwrap(); + self.artifact.declare_with(id.name(), Decl::section(faerie::SectionKind::Debug), data).unwrap(); id } @@ -89,6 +92,7 @@ impl WriteDebugInfo for Artifact { reloc: &DebugReloc, ) { self + .artifact .link_with( faerie::Link { from: from.name(), @@ -147,3 +151,69 @@ impl WriteDebugInfo for ObjectProduct { }).unwrap(); } } + +pub trait Emit { + fn emit(self) -> Vec<u8>; +} + +impl Emit for FaerieProduct { + fn emit(self) -> Vec<u8> { + self.artifact.emit().unwrap() + } +} + +impl Emit for ObjectProduct { + fn emit(self) -> Vec<u8> { + self.object.write().unwrap() + } +} + +#[cfg(not(feature = "backend_object"))] +pub fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Artifact)) -> Vec<u8> { + let mut metadata_artifact = faerie::Artifact::new( + crate::build_isa(sess, true).triple().clone(), + name.to_string(), + ); + f(&mut metadata_artifact); + metadata_artifact.emit().unwrap() +} + +#[cfg(feature = "backend_object")] +pub fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Object)) -> Vec<u8> { + let triple = crate::build_isa(sess, true).triple().clone(); + let mut metadata_object = + object::write::Object::new(triple.binary_format, triple.architecture); + metadata_object.add_file_symbol(name.as_bytes().to_vec()); + f(&mut metadata_object); + metadata_object.write().unwrap() +} + +pub type Backend = impl cranelift_module::Backend<Product: Emit + WriteDebugInfo>; + +#[cfg(not(feature = "backend_object"))] +pub fn make_module(sess: &Session, name: String) -> Module<Backend> { + let module: Module<FaerieBackend> = Module::new( + FaerieBuilder::new( + crate::build_isa(sess, true), + name + ".o", + FaerieTrapCollection::Disabled, + cranelift_module::default_libcall_names(), + ) + .unwrap(), + ); + module +} + +#[cfg(feature = "backend_object")] +pub fn make_module(sess: &Session, name: String) -> Module<Backend> { + let module: Module<ObjectBackend> = Module::new( + ObjectBuilder::new( + crate::build_isa(sess, true), + name + ".o", + ObjectTrapCollection::Disabled, + cranelift_module::default_libcall_names(), + ) + .unwrap(), + ); + module +} diff --git a/src/driver.rs b/src/driver.rs index 19f53ebda13..b26da23da90 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -8,10 +8,10 @@ use rustc::session::config::{DebugInfo, OutputType}; use rustc_codegen_ssa::back::linker::LinkerInfo; use rustc_codegen_ssa::CrateInfo; -use cranelift_faerie::*; - use crate::prelude::*; +use crate::backend::{Emit, WriteDebugInfo}; + pub fn codegen_crate( tcx: TyCtxt<'_>, metadata: EncodedMetadata, @@ -147,36 +147,34 @@ fn run_aot( need_metadata_module: bool, ) -> Box<CodegenResults> { let new_module = |name: String| { - let module: Module<FaerieBackend> = Module::new( - FaerieBuilder::new( - crate::build_isa(tcx.sess, true), - name + ".o", - FaerieTrapCollection::Disabled, - cranelift_module::default_libcall_names(), - ) - .unwrap(), - ); + let module = crate::backend::make_module(tcx.sess, name); assert_eq!(pointer_ty(tcx), module.target_config().pointer_type()); module }; - let emit_module = |kind: ModuleKind, - mut module: Module<FaerieBackend>, - debug: Option<DebugContext>| { + fn emit_module<B: Backend>( + tcx: TyCtxt<'_>, + name: String, + kind: ModuleKind, + mut module: Module<B>, + debug: Option<DebugContext>, + ) -> CompiledModule + where B::Product: Emit + WriteDebugInfo, + { module.finalize_definitions(); - let mut artifact = module.finish().artifact; + let mut product = module.finish(); if let Some(mut debug) = debug { - debug.emit(&mut artifact); + debug.emit(&mut product); } let tmp_file = tcx .output_filenames(LOCAL_CRATE) - .temp_path(OutputType::Object, Some(&artifact.name)); - let obj = artifact.emit().unwrap(); + .temp_path(OutputType::Object, Some(&name)); + let obj = product.emit(); std::fs::write(&tmp_file, obj).unwrap(); CompiledModule { - name: artifact.name, + name: name, kind, object: Some(tmp_file), bytecode: None, @@ -184,7 +182,7 @@ fn run_aot( } }; - let mut faerie_module = new_module("some_file".to_string()); + let mut module = new_module("some_file".to_string()); let mut debug = if tcx.sess.opts.debuginfo != DebugInfo::None // macOS debuginfo doesn't work yet (see #303) @@ -192,14 +190,14 @@ fn run_aot( { let debug = DebugContext::new( tcx, - faerie_module.target_config().pointer_type().bytes() as u8, + module.target_config().pointer_type().bytes() as u8, ); Some(debug) } else { None }; - codegen_cgus(tcx, &mut faerie_module, &mut debug); + codegen_cgus(tcx, &mut module, &mut debug); tcx.sess.abort_if_errors(); @@ -221,17 +219,14 @@ fn run_aot( .as_str() .to_string(); - let mut metadata_artifact = faerie::Artifact::new( - crate::build_isa(tcx.sess, true).triple().clone(), - metadata_cgu_name.clone(), - ); - crate::metadata::write_metadata(tcx, &mut metadata_artifact); - let tmp_file = tcx .output_filenames(LOCAL_CRATE) .temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); - let obj = metadata_artifact.emit().unwrap(); + let obj = crate::backend::with_object(tcx.sess, &metadata_cgu_name, |object| { + crate::metadata::write_metadata(tcx, object); + }); + std::fs::write(&tmp_file, obj).unwrap(); (metadata_cgu_name, tmp_file) @@ -251,12 +246,16 @@ fn run_aot( Box::new(CodegenResults { crate_name: tcx.crate_name(LOCAL_CRATE), modules: vec![emit_module( + tcx, + "some_file".to_string(), ModuleKind::Regular, - faerie_module, + module, debug, )], allocator_module: if created_alloc_shim { Some(emit_module( + tcx, + "allocator_shim".to_string(), ModuleKind::Allocator, allocator_module, None, diff --git a/src/lib.rs b/src/lib.rs index 7e68f10ede0..169397f14a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(rustc_private, never_type, decl_macro)] +#![feature(rustc_private, never_type, decl_macro, type_alias_impl_trait, associated_type_bounds)] #![allow(intra_doc_link_resolution_failure)] extern crate flate2;