From f9ff604d966ff9fa180ac171b27ef5bd7db43eb1 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 16 Oct 2019 20:48:09 +0200 Subject: [PATCH 1/7] Make dylib metadata write backend agnostic --- Cargo.lock | 15 +++++++++++++++ Cargo.toml | 4 +++- src/backend.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/metadata.rs | 27 ++++++++------------------- 5 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 src/backend.rs diff --git a/Cargo.lock b/Cargo.lock index dab1e3f38..d67181bd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,6 +155,17 @@ dependencies = [ "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cranelift-object" +version = "0.46.1" +source = "git+https://github.com/CraneStation/cranelift.git#387593d6c94d291e614c08d7a03f77b40efa451d" +dependencies = [ + "cranelift-codegen 0.46.1 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-module 0.46.1 (git+https://github.com/CraneStation/cranelift.git)", + "object 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cranelift-simplejit" version = "0.46.1" @@ -332,8 +343,10 @@ name = "object" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -411,6 +424,7 @@ dependencies = [ "cranelift 0.46.1 (git+https://github.com/CraneStation/cranelift.git)", "cranelift-faerie 0.46.1 (git+https://github.com/CraneStation/cranelift.git)", "cranelift-module 0.46.1 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-object 0.46.1 (git+https://github.com/CraneStation/cranelift.git)", "cranelift-simplejit 0.46.1 (git+https://github.com/CraneStation/cranelift.git)", "faerie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -594,6 +608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cranelift-frontend 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "" "checksum cranelift-module 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "" "checksum cranelift-native 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "" +"checksum cranelift-object 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "" "checksum cranelift-simplejit 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" diff --git a/Cargo.toml b/Cargo.toml index 66256cd68..f3b9e8437 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ crate-type = ["dylib"] cranelift = { git = "https://github.com/CraneStation/cranelift.git" } cranelift-module = { git = "https://github.com/CraneStation/cranelift.git" } cranelift-faerie = { git = "https://github.com/CraneStation/cranelift.git" } +cranelift-object = { git = "https://github.com/CraneStation/cranelift.git" } target-lexicon = "0.8.1" faerie = "0.11.0" @@ -28,7 +29,7 @@ libloading = "0.5.1" [dependencies.object] version = "0.14.0" default-features = false -features = ["compression", "read", "std"] # We don't need WASM support +features = ["compression", "read", "std", "write"] # We don't need WASM support # Uncomment to use local checkout of cranelift #[patch."https://github.com/CraneStation/cranelift.git"] @@ -36,6 +37,7 @@ features = ["compression", "read", "std"] # We don't need WASM support #cranelift-module = { path = "../cranelift/cranelift-module" } #cranelift-simplejit = { path = "../cranelift/cranelift-simplejit" } #cranelift-faerie = { path = "../cranelift/cranelift-faerie" } +#cranelift-object = { path = "../cranelift/cranelift-object" } #[patch.crates-io] #gimli = { path = "../" } diff --git a/src/backend.rs b/src/backend.rs new file mode 100644 index 000000000..f070e95f5 --- /dev/null +++ b/src/backend.rs @@ -0,0 +1,48 @@ +pub trait Product { + fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool); +} + +impl Product for faerie::Artifact { + fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool) { + self + .declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data)) + .unwrap(); + self + .define_with_symbols(".rustc", data, { + let mut map = std::collections::BTreeMap::new(); + // FIXME implement faerie elf backend section custom symbols + // For MachO this is necessary to prevent the linker from throwing away the .rustc section, + // but for ELF it isn't. + if is_like_osx { + map.insert( + symbol_name, + 0, + ); + } + map + }) + .unwrap(); + } +} + +impl Product for object::write::Object { + fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool) { + let segment = self.segment_name(object::write::StandardSegment::Data).to_vec(); + let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data); + let offset = self.append_section_data(section_id, &data, 1); + // FIXME implement faerie elf backend section custom symbols + // For MachO this is necessary to prevent the linker from throwing away the .rustc section, + // but for ELF it isn't. + if is_like_osx { + self.add_symbol(object::write::Symbol { + name: symbol_name.into_bytes(), + value: offset, + size: data.len() as u64, + kind: object::SymbolKind::Data, + scope: object::SymbolScope::Compilation, + weak: false, + section: Some(section_id), + }); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 866a3d311..7e68f10ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ mod allocator; mod analyze; mod archive; mod base; +mod backend; mod cast; mod codegen_i128; mod common; diff --git a/src/metadata.rs b/src/metadata.rs index 8d1792272..76c86e738 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -9,6 +9,8 @@ use rustc_data_structures::owning_ref::{self, OwningRef}; use rustc_data_structures::rustc_erase_owner; use rustc_target::spec::Target; +use crate::backend::Product; + pub struct CraneliftMetadataLoader; impl MetadataLoader for CraneliftMetadataLoader { @@ -51,7 +53,7 @@ impl MetadataLoader for CraneliftMetadataLoader { } // Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112 -pub fn write_metadata(tcx: TyCtxt<'_>, artifact: &mut faerie::Artifact) -> EncodedMetadata { +pub fn write_metadata(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata { use flate2::write::DeflateEncoder; use flate2::Compression; use std::io::Write; @@ -95,24 +97,11 @@ pub fn write_metadata(tcx: TyCtxt<'_>, artifact: &mut faerie::Artifact) -> Encod .write_all(&metadata.raw_data) .unwrap(); - artifact - .declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data)) - .unwrap(); - artifact - .define_with_symbols(".rustc", compressed, { - let mut map = std::collections::BTreeMap::new(); - // FIXME implement faerie elf backend section custom symbols - // For MachO this is necessary to prevent the linker from throwing away the .rustc section, - // but for ELF it isn't. - if tcx.sess.target.target.options.is_like_osx { - map.insert( - rustc::middle::exported_symbols::metadata_symbol_name(tcx), - 0, - ); - } - map - }) - .unwrap(); + product.add_rustc_section( + rustc::middle::exported_symbols::metadata_symbol_name(tcx), + compressed, + tcx.sess.target.target.options.is_like_osx, + ); metadata } From 5873127ec2b1d748bb673c0193682a563fcb6fe0 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 16 Oct 2019 21:21:20 +0200 Subject: [PATCH 2/7] Make debuginfo writing backend agnostic --- src/backend.rs | 107 +++++++++++++++++++++++++++++++++++++++++++++-- src/base.rs | 2 +- src/debuginfo.rs | 60 +++++++++----------------- src/metadata.rs | 4 +- 4 files changed, 126 insertions(+), 47 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index f070e95f5..429c48ba0 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,8 +1,21 @@ -pub trait Product { +use std::collections::HashMap; + +use cranelift_module::FuncId; + +use faerie::*; +use object::{SectionKind, RelocationKind, RelocationEncoding}; +use object::write::*; +use cranelift_object::*; + +use gimli::SectionId; + +use crate::debuginfo::{DebugReloc, DebugRelocName}; + +pub trait WriteMetadata { fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool); } -impl Product for faerie::Artifact { +impl WriteMetadata for faerie::Artifact { fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool) { self .declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data)) @@ -25,7 +38,7 @@ impl Product for faerie::Artifact { } } -impl Product for object::write::Object { +impl WriteMetadata for object::write::Object { fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool) { let segment = self.segment_name(object::write::StandardSegment::Data).to_vec(); let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data); @@ -46,3 +59,91 @@ impl Product for object::write::Object { } } } + +pub trait WriteDebugInfo { + type SectionId; + + fn add_debug_section(&mut self, name: SectionId, data: Vec) -> Self::SectionId; + fn add_debug_reloc( + &mut self, + section_map: &HashMap, + symbol_map: &indexmap::IndexSet<(String, FuncId)>, + from: &Self::SectionId, + reloc: &DebugReloc, + ); +} + +impl WriteDebugInfo for Artifact { + type SectionId = SectionId; + + fn add_debug_section(&mut self, id: SectionId, data: Vec) -> SectionId { + self.declare_with(id.name(), Decl::section(faerie::SectionKind::Debug), data).unwrap(); + id + } + + fn add_debug_reloc( + &mut self, + _section_map: &HashMap, + symbol_map: &indexmap::IndexSet<(String, FuncId)>, + from: &Self::SectionId, + reloc: &DebugReloc, + ) { + self + .link_with( + faerie::Link { + from: from.name(), + to: match reloc.name { + DebugRelocName::Section(id) => id.name(), + DebugRelocName::Symbol(index) => &symbol_map.get_index(index).unwrap().0, + }, + at: u64::from(reloc.offset), + }, + faerie::Reloc::Debug { + size: reloc.size, + addend: reloc.addend as i32, + }, + ) + .expect("faerie relocation error"); + } +} + +impl WriteDebugInfo for ObjectProduct { + type SectionId = (object::write::SectionId, object::write::SymbolId); + + fn add_debug_section( + &mut self, + id: SectionId, + data: Vec, + ) -> (object::write::SectionId, object::write::SymbolId) { + let segment = self.object.segment_name(StandardSegment::Debug).to_vec(); + let name = id.name().as_bytes().to_vec(); + let section_id = self.object.add_section(segment, name, SectionKind::Debug); + self.object.section_mut(section_id).set_data(data, 1); + let symbol_id = self.object.section_symbol(section_id); + (section_id, symbol_id) + } + + fn add_debug_reloc( + &mut self, + section_map: &HashMap, + symbol_map: &indexmap::IndexSet<(String, FuncId)>, + from: &Self::SectionId, + reloc: &DebugReloc, + ) { + let symbol = match reloc.name { + DebugRelocName::Section(id) => section_map.get(&id).unwrap().1, + DebugRelocName::Symbol(id) => { + let (_func_name, func_id) = symbol_map.get_index(id).unwrap(); + self.function_symbol(*func_id) + } + }; + self.object.add_relocation(from.0, Relocation { + offset: u64::from(reloc.offset), + symbol, + kind: RelocationKind::Absolute, + encoding: RelocationEncoding::Generic, + size: reloc.size * 8, + addend: reloc.addend, + }).unwrap(); + } +} diff --git a/src/base.rs b/src/base.rs index 81750efd1..ef32dafb2 100644 --- a/src/base.rs +++ b/src/base.rs @@ -17,7 +17,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( let mut debug_context = cx .debug_context .as_mut() - .map(|debug_context| FunctionDebugContext::new(tcx, debug_context, mir, &name, &sig)); + .map(|debug_context| FunctionDebugContext::new(tcx, debug_context, mir, func_id, &name, &sig)); // Make FunctionBuilder let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 0ded96cec..d2705c6a2 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +use crate::backend::WriteDebugInfo; + use std::marker::PhantomData; use syntax::source_map::FileName; @@ -10,8 +12,6 @@ use gimli::write::{ }; use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, SectionId}; -use faerie::*; - fn target_endian(tcx: TyCtxt) -> RunTimeEndian { use rustc::ty::layout::Endian; @@ -56,31 +56,22 @@ fn line_program_add_file( } #[derive(Clone)] -struct DebugReloc { - offset: u32, - size: u8, - name: DebugRelocName, - addend: i64, +pub struct DebugReloc { + pub offset: u32, + pub size: u8, + pub name: DebugRelocName, + pub addend: i64, } #[derive(Clone)] -enum DebugRelocName { +pub enum DebugRelocName { Section(SectionId), Symbol(usize), } -impl DebugReloc { - fn name<'a>(&self, ctx: &'a DebugContext) -> &'a str { - match self.name { - DebugRelocName::Section(id) => id.name(), - DebugRelocName::Symbol(index) => ctx.symbols.get_index(index).unwrap(), - } - } -} - pub struct DebugContext<'tcx> { endian: RunTimeEndian, - symbols: indexmap::IndexSet, + symbols: indexmap::IndexSet<(String, FuncId)>, dwarf: DwarfUnit, unit_range_list: RangeList, @@ -177,7 +168,7 @@ impl<'tcx> DebugContext<'tcx> { ); } - pub fn emit(&mut self, artifact: &mut Artifact) { + pub fn emit(&mut self, product: &mut P) { let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone()); let root = self.dwarf.unit.root(); let root = self.dwarf.unit.get_mut(root); @@ -189,34 +180,20 @@ impl<'tcx> DebugContext<'tcx> { let mut sections = Sections::new(WriterRelocate::new(self)); self.dwarf.write(&mut sections).unwrap(); + let mut section_map = HashMap::new(); let _: Result<()> = sections.for_each_mut(|id, section| { if !section.writer.slice().is_empty() { - artifact - .declare_with( - id.name(), - Decl::section(SectionKind::Debug), - section.writer.take(), - ) - .unwrap(); + let section_id = product.add_debug_section(id, section.writer.take()); + section_map.insert(id, section_id); } Ok(()) }); let _: Result<()> = sections.for_each(|id, section| { - for reloc in §ion.relocs { - artifact - .link_with( - faerie::Link { - from: id.name(), - to: reloc.name(self), - at: u64::from(reloc.offset), - }, - faerie::Reloc::Debug { - size: reloc.size, - addend: reloc.addend as i32, - }, - ) - .expect("faerie relocation error"); + if let Some(section_id) = section_map.get(&id) { + for reloc in §ion.relocs { + product.add_debug_reloc(§ion_map, &self.symbols, section_id, reloc); + } } Ok(()) }); @@ -235,10 +212,11 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, debug_context: &'a mut DebugContext<'tcx>, mir: &Body, + func_id: FuncId, name: &str, _sig: &Signature, ) -> Self { - let (symbol, _) = debug_context.symbols.insert_full(name.to_string()); + let (symbol, _) = debug_context.symbols.insert_full((name.to_string(), func_id)); // FIXME: add to appropriate scope intead of root let scope = debug_context.dwarf.unit.root(); diff --git a/src/metadata.rs b/src/metadata.rs index 76c86e738..f15e1682d 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -9,7 +9,7 @@ use rustc_data_structures::owning_ref::{self, OwningRef}; use rustc_data_structures::rustc_erase_owner; use rustc_target::spec::Target; -use crate::backend::Product; +use crate::backend::WriteMetadata; pub struct CraneliftMetadataLoader; @@ -53,7 +53,7 @@ impl MetadataLoader for CraneliftMetadataLoader { } // Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112 -pub fn write_metadata(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata { +pub fn write_metadata(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata { use flate2::write::DeflateEncoder; use flate2::Compression; use std::io::Write; From 0471ed27766724e0bed9d96d4f107f3c12280828 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 18 Oct 2019 17:19:13 +0200 Subject: [PATCH 3/7] Add support for object::write --- Cargo.toml | 5 +++- src/backend.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/driver.rs | 59 +++++++++++++++++++-------------------- src/lib.rs | 2 +- 4 files changed, 107 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f3b9e8437..0da280f24 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 429c48ba0..449e2a5cc 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) -> 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; +} + +impl Emit for FaerieProduct { + fn emit(self) -> Vec { + self.artifact.emit().unwrap() + } +} + +impl Emit for ObjectProduct { + fn emit(self) -> Vec { + self.object.write().unwrap() + } +} + +#[cfg(not(feature = "backend_object"))] +pub fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Artifact)) -> Vec { + 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 { + 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; + +#[cfg(not(feature = "backend_object"))] +pub fn make_module(sess: &Session, name: String) -> Module { + let module: Module = 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 { + let module: Module = 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 19f53ebda..b26da23da 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 { let new_module = |name: String| { - let module: Module = 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, - debug: Option| { + fn emit_module( + tcx: TyCtxt<'_>, + name: String, + kind: ModuleKind, + mut module: Module, + debug: Option, + ) -> 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 7e68f10ed..169397f14 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; From ecd9c4f2e32e88ec7fc06eaf85f758917494e632 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 19 Oct 2019 10:52:56 +0200 Subject: [PATCH 4/7] FIx review comments --- src/backend.rs | 38 +++++++++++++++++--------------------- src/debuginfo.rs | 6 +++--- src/driver.rs | 2 +- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index 449e2a5cc..60cf43da1 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -42,24 +42,21 @@ impl WriteMetadata for faerie::Artifact { } impl WriteMetadata for object::write::Object { - fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool) { + fn add_rustc_section(&mut self, symbol_name: String, data: Vec, _is_like_osx: bool) { let segment = self.segment_name(object::write::StandardSegment::Data).to_vec(); let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data); let offset = self.append_section_data(section_id, &data, 1); - // FIXME implement faerie elf backend section custom symbols - // For MachO this is necessary to prevent the linker from throwing away the .rustc section, - // but for ELF it isn't. - if is_like_osx { - self.add_symbol(object::write::Symbol { - name: symbol_name.into_bytes(), - value: offset, - size: data.len() as u64, - kind: object::SymbolKind::Data, - scope: object::SymbolScope::Compilation, - weak: false, - section: Some(section_id), - }); - } + // For MachO and probably PE this is necessary to prevent the linker from throwing away the + // .rustc section. For ELF this isn't necessary, but it also doesn't harm. + self.add_symbol(object::write::Symbol { + name: symbol_name.into_bytes(), + value: offset, + size: data.len() as u64, + kind: object::SymbolKind::Data, + scope: object::SymbolScope::Compilation, + weak: false, + section: Some(section_id), + }); } } @@ -70,7 +67,7 @@ pub trait WriteDebugInfo { fn add_debug_reloc( &mut self, section_map: &HashMap, - symbol_map: &indexmap::IndexSet<(String, FuncId)>, + symbol_map: &indexmap::IndexMap, from: &Self::SectionId, reloc: &DebugReloc, ); @@ -87,7 +84,7 @@ impl WriteDebugInfo for FaerieProduct { fn add_debug_reloc( &mut self, _section_map: &HashMap, - symbol_map: &indexmap::IndexSet<(String, FuncId)>, + symbol_map: &indexmap::IndexMap, from: &Self::SectionId, reloc: &DebugReloc, ) { @@ -98,7 +95,7 @@ impl WriteDebugInfo for FaerieProduct { from: from.name(), to: match reloc.name { DebugRelocName::Section(id) => id.name(), - DebugRelocName::Symbol(index) => &symbol_map.get_index(index).unwrap().0, + DebugRelocName::Symbol(index) => &symbol_map.get_index(index).unwrap().1, }, at: u64::from(reloc.offset), }, @@ -130,15 +127,14 @@ impl WriteDebugInfo for ObjectProduct { fn add_debug_reloc( &mut self, section_map: &HashMap, - symbol_map: &indexmap::IndexSet<(String, FuncId)>, + symbol_map: &indexmap::IndexMap, from: &Self::SectionId, reloc: &DebugReloc, ) { let symbol = match reloc.name { DebugRelocName::Section(id) => section_map.get(&id).unwrap().1, DebugRelocName::Symbol(id) => { - let (_func_name, func_id) = symbol_map.get_index(id).unwrap(); - self.function_symbol(*func_id) + self.function_symbol(*symbol_map.get_index(id).unwrap().0) } }; self.object.add_relocation(from.0, Relocation { diff --git a/src/debuginfo.rs b/src/debuginfo.rs index d2705c6a2..762fa8668 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -71,7 +71,7 @@ pub enum DebugRelocName { pub struct DebugContext<'tcx> { endian: RunTimeEndian, - symbols: indexmap::IndexSet<(String, FuncId)>, + symbols: indexmap::IndexMap, dwarf: DwarfUnit, unit_range_list: RangeList, @@ -133,7 +133,7 @@ impl<'tcx> DebugContext<'tcx> { DebugContext { endian: target_endian(tcx), - symbols: indexmap::IndexSet::new(), + symbols: indexmap::IndexMap::new(), dwarf, unit_range_list: RangeList(Vec::new()), @@ -216,7 +216,7 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { name: &str, _sig: &Signature, ) -> Self { - let (symbol, _) = debug_context.symbols.insert_full((name.to_string(), func_id)); + let (symbol, _) = debug_context.symbols.insert_full(func_id, name.to_string()); // FIXME: add to appropriate scope intead of root let scope = debug_context.dwarf.unit.root(); diff --git a/src/driver.rs b/src/driver.rs index b26da23da..215ae071c 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -174,7 +174,7 @@ fn run_aot( let obj = product.emit(); std::fs::write(&tmp_file, obj).unwrap(); CompiledModule { - name: name, + name, kind, object: Some(tmp_file), bytecode: None, From bb5cefe83806b66838cf4ec5c9ea54919c7708b9 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 19 Oct 2019 10:56:35 +0200 Subject: [PATCH 5/7] Test object::write backend on travis --- .travis.yml | 3 +++ Cargo.toml | 4 ++-- src/backend.rs | 7 +++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e73e99339..548230651 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,3 +21,6 @@ env: - RUST_BACKTRACE=1 # Reduce amount of benchmark runs as they are slow. - COMPILE_RUNS=2 RUN_RUNS=2 + CG_CLIF_COMPILE_FLAGS: + - "" + - "--features backend_object" diff --git a/Cargo.toml b/Cargo.toml index 0da280f24..86347a006 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,14 +10,14 @@ edition = "2018" crate-type = ["dylib"] [features] -backend_object = ["object/write"] +backend_object = ["object/write", "cranelift-object"] [dependencies] # These have to be in sync with each other cranelift = { git = "https://github.com/CraneStation/cranelift.git" } cranelift-module = { git = "https://github.com/CraneStation/cranelift.git" } cranelift-faerie = { git = "https://github.com/CraneStation/cranelift.git" } -cranelift-object = { git = "https://github.com/CraneStation/cranelift.git" } +cranelift-object = { git = "https://github.com/CraneStation/cranelift.git", optional = true } target-lexicon = "0.8.1" faerie = "0.11.0" diff --git a/src/backend.rs b/src/backend.rs index 60cf43da1..94b1cd7d5 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -5,9 +5,13 @@ use rustc::session::Session; use cranelift_module::{FuncId, Module}; use faerie::*; +#[cfg(feature = "backend_object")] use object::{SectionKind, RelocationKind, RelocationEncoding}; +#[cfg(feature = "backend_object")] use object::write::*; use cranelift_faerie::{FaerieBackend, FaerieBuilder, FaerieProduct, FaerieTrapCollection}; + +#[cfg(feature = "backend_object")] use cranelift_object::*; use gimli::SectionId; @@ -41,6 +45,7 @@ impl WriteMetadata for faerie::Artifact { } } +#[cfg(feature = "backend_object")] impl WriteMetadata for object::write::Object { fn add_rustc_section(&mut self, symbol_name: String, data: Vec, _is_like_osx: bool) { let segment = self.segment_name(object::write::StandardSegment::Data).to_vec(); @@ -108,6 +113,7 @@ impl WriteDebugInfo for FaerieProduct { } } +#[cfg(feature = "backend_object")] impl WriteDebugInfo for ObjectProduct { type SectionId = (object::write::SectionId, object::write::SymbolId); @@ -158,6 +164,7 @@ impl Emit for FaerieProduct { } } +#[cfg(feature = "backend_object")] impl Emit for ObjectProduct { fn emit(self) -> Vec { self.object.write().unwrap() From 4d7f70318a3e1729a1fa9e1884c719676c0d885a Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 19 Oct 2019 11:08:16 +0200 Subject: [PATCH 6/7] Fix metadata symbol scope It should be exported from the generated dylib --- src/backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend.rs b/src/backend.rs index 94b1cd7d5..ccb95624b 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -58,7 +58,7 @@ impl WriteMetadata for object::write::Object { value: offset, size: data.len() as u64, kind: object::SymbolKind::Data, - scope: object::SymbolScope::Compilation, + scope: object::SymbolScope::Dynamic, weak: false, section: Some(section_id), }); From 1901571d864941ca42cdb62165a4cb0c58afe5ec Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 19 Oct 2019 11:10:34 +0200 Subject: [PATCH 7/7] Fix travis ci config --- .travis.yml | 6 +++--- test.sh | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 548230651..765739785 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,6 @@ env: - RUST_BACKTRACE=1 # Reduce amount of benchmark runs as they are slow. - COMPILE_RUNS=2 RUN_RUNS=2 - CG_CLIF_COMPILE_FLAGS: - - "" - - "--features backend_object" + jobs: + - "CG_CLIF_COMPILE_FLAGS=" + - "CG_CLIF_COMPILE_FLAGS='--features backend_object'" diff --git a/test.sh b/test.sh index f32ec1026..773b7c296 100755 --- a/test.sh +++ b/test.sh @@ -4,10 +4,10 @@ set -e if [[ "$1" == "--release" ]]; then export CHANNEL='release' - cargo build --release + cargo build --release $CG_CLIF_COMPILE_FLAGS else export CHANNEL='debug' - cargo build + cargo build $CG_CLIF_COMPILE_FLAGS fi source config.sh