Merge pull request #758 from bjorn3/object_write
Add object::write as alternative object file writer
This commit is contained in:
commit
75c24b9c96
10 changed files with 307 additions and 95 deletions
|
@ -21,3 +21,6 @@ env:
|
||||||
- RUST_BACKTRACE=1
|
- RUST_BACKTRACE=1
|
||||||
# Reduce amount of benchmark runs as they are slow.
|
# Reduce amount of benchmark runs as they are slow.
|
||||||
- COMPILE_RUNS=2 RUN_RUNS=2
|
- COMPILE_RUNS=2 RUN_RUNS=2
|
||||||
|
jobs:
|
||||||
|
- "CG_CLIF_COMPILE_FLAGS="
|
||||||
|
- "CG_CLIF_COMPILE_FLAGS='--features backend_object'"
|
||||||
|
|
15
Cargo.lock
generated
15
Cargo.lock
generated
|
@ -155,6 +155,17 @@ dependencies = [
|
||||||
"target-lexicon 0.8.1 (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-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]]
|
[[package]]
|
||||||
name = "cranelift-simplejit"
|
name = "cranelift-simplejit"
|
||||||
version = "0.46.1"
|
version = "0.46.1"
|
||||||
|
@ -332,8 +343,10 @@ name = "object"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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 0.46.1 (git+https://github.com/CraneStation/cranelift.git)",
|
||||||
"cranelift-faerie 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-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)",
|
"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)",
|
"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)",
|
"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)" = "<none>"
|
"checksum cranelift-frontend 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||||
"checksum cranelift-module 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
"checksum cranelift-module 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||||
"checksum cranelift-native 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
"checksum cranelift-native 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||||
|
"checksum cranelift-object 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||||
"checksum cranelift-simplejit 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
"checksum cranelift-simplejit 0.46.1 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||||
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
"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"
|
"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e"
|
||||||
|
|
|
@ -9,11 +9,15 @@ edition = "2018"
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["dylib"]
|
crate-type = ["dylib"]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
backend_object = ["object/write", "cranelift-object"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# These have to be in sync with each other
|
# These have to be in sync with each other
|
||||||
cranelift = { git = "https://github.com/CraneStation/cranelift.git" }
|
cranelift = { git = "https://github.com/CraneStation/cranelift.git" }
|
||||||
cranelift-module = { 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-faerie = { git = "https://github.com/CraneStation/cranelift.git" }
|
||||||
|
cranelift-object = { git = "https://github.com/CraneStation/cranelift.git", optional = true }
|
||||||
target-lexicon = "0.8.1"
|
target-lexicon = "0.8.1"
|
||||||
faerie = "0.11.0"
|
faerie = "0.11.0"
|
||||||
|
|
||||||
|
@ -36,6 +40,7 @@ features = ["compression", "read", "std"] # We don't need WASM support
|
||||||
#cranelift-module = { path = "../cranelift/cranelift-module" }
|
#cranelift-module = { path = "../cranelift/cranelift-module" }
|
||||||
#cranelift-simplejit = { path = "../cranelift/cranelift-simplejit" }
|
#cranelift-simplejit = { path = "../cranelift/cranelift-simplejit" }
|
||||||
#cranelift-faerie = { path = "../cranelift/cranelift-faerie" }
|
#cranelift-faerie = { path = "../cranelift/cranelift-faerie" }
|
||||||
|
#cranelift-object = { path = "../cranelift/cranelift-object" }
|
||||||
|
|
||||||
#[patch.crates-io]
|
#[patch.crates-io]
|
||||||
#gimli = { path = "../" }
|
#gimli = { path = "../" }
|
||||||
|
|
222
src/backend.rs
Normal file
222
src/backend.rs
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
use crate::debuginfo::{DebugReloc, DebugRelocName};
|
||||||
|
|
||||||
|
pub trait WriteMetadata {
|
||||||
|
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, is_like_osx: bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WriteMetadata for faerie::Artifact {
|
||||||
|
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "backend_object")]
|
||||||
|
impl WriteMetadata for object::write::Object {
|
||||||
|
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, _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);
|
||||||
|
// 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::Dynamic,
|
||||||
|
weak: false,
|
||||||
|
section: Some(section_id),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WriteDebugInfo {
|
||||||
|
type SectionId;
|
||||||
|
|
||||||
|
fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
|
||||||
|
fn add_debug_reloc(
|
||||||
|
&mut self,
|
||||||
|
section_map: &HashMap<SectionId, Self::SectionId>,
|
||||||
|
symbol_map: &indexmap::IndexMap<FuncId, String>,
|
||||||
|
from: &Self::SectionId,
|
||||||
|
reloc: &DebugReloc,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WriteDebugInfo for FaerieProduct {
|
||||||
|
type SectionId = SectionId;
|
||||||
|
|
||||||
|
fn add_debug_section(&mut self, id: SectionId, data: Vec<u8>) -> SectionId {
|
||||||
|
self.artifact.declare_with(id.name(), Decl::section(faerie::SectionKind::Debug), data).unwrap();
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_debug_reloc(
|
||||||
|
&mut self,
|
||||||
|
_section_map: &HashMap<SectionId, Self::SectionId>,
|
||||||
|
symbol_map: &indexmap::IndexMap<FuncId, String>,
|
||||||
|
from: &Self::SectionId,
|
||||||
|
reloc: &DebugReloc,
|
||||||
|
) {
|
||||||
|
self
|
||||||
|
.artifact
|
||||||
|
.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().1,
|
||||||
|
},
|
||||||
|
at: u64::from(reloc.offset),
|
||||||
|
},
|
||||||
|
faerie::Reloc::Debug {
|
||||||
|
size: reloc.size,
|
||||||
|
addend: reloc.addend as i32,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.expect("faerie relocation error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "backend_object")]
|
||||||
|
impl WriteDebugInfo for ObjectProduct {
|
||||||
|
type SectionId = (object::write::SectionId, object::write::SymbolId);
|
||||||
|
|
||||||
|
fn add_debug_section(
|
||||||
|
&mut self,
|
||||||
|
id: SectionId,
|
||||||
|
data: Vec<u8>,
|
||||||
|
) -> (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<SectionId, Self::SectionId>,
|
||||||
|
symbol_map: &indexmap::IndexMap<FuncId, String>,
|
||||||
|
from: &Self::SectionId,
|
||||||
|
reloc: &DebugReloc,
|
||||||
|
) {
|
||||||
|
let symbol = match reloc.name {
|
||||||
|
DebugRelocName::Section(id) => section_map.get(&id).unwrap().1,
|
||||||
|
DebugRelocName::Symbol(id) => {
|
||||||
|
self.function_symbol(*symbol_map.get_index(id).unwrap().0)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Emit {
|
||||||
|
fn emit(self) -> Vec<u8>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Emit for FaerieProduct {
|
||||||
|
fn emit(self) -> Vec<u8> {
|
||||||
|
self.artifact.emit().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "backend_object")]
|
||||||
|
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
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>(
|
||||||
let mut debug_context = cx
|
let mut debug_context = cx
|
||||||
.debug_context
|
.debug_context
|
||||||
.as_mut()
|
.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
|
// Make FunctionBuilder
|
||||||
let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
|
let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use crate::backend::WriteDebugInfo;
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use syntax::source_map::FileName;
|
use syntax::source_map::FileName;
|
||||||
|
@ -10,8 +12,6 @@ use gimli::write::{
|
||||||
};
|
};
|
||||||
use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, SectionId};
|
use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, SectionId};
|
||||||
|
|
||||||
use faerie::*;
|
|
||||||
|
|
||||||
fn target_endian(tcx: TyCtxt) -> RunTimeEndian {
|
fn target_endian(tcx: TyCtxt) -> RunTimeEndian {
|
||||||
use rustc::ty::layout::Endian;
|
use rustc::ty::layout::Endian;
|
||||||
|
|
||||||
|
@ -56,31 +56,22 @@ fn line_program_add_file(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct DebugReloc {
|
pub struct DebugReloc {
|
||||||
offset: u32,
|
pub offset: u32,
|
||||||
size: u8,
|
pub size: u8,
|
||||||
name: DebugRelocName,
|
pub name: DebugRelocName,
|
||||||
addend: i64,
|
pub addend: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum DebugRelocName {
|
pub enum DebugRelocName {
|
||||||
Section(SectionId),
|
Section(SectionId),
|
||||||
Symbol(usize),
|
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> {
|
pub struct DebugContext<'tcx> {
|
||||||
endian: RunTimeEndian,
|
endian: RunTimeEndian,
|
||||||
symbols: indexmap::IndexSet<String>,
|
symbols: indexmap::IndexMap<FuncId, String>,
|
||||||
|
|
||||||
dwarf: DwarfUnit,
|
dwarf: DwarfUnit,
|
||||||
unit_range_list: RangeList,
|
unit_range_list: RangeList,
|
||||||
|
@ -142,7 +133,7 @@ impl<'tcx> DebugContext<'tcx> {
|
||||||
|
|
||||||
DebugContext {
|
DebugContext {
|
||||||
endian: target_endian(tcx),
|
endian: target_endian(tcx),
|
||||||
symbols: indexmap::IndexSet::new(),
|
symbols: indexmap::IndexMap::new(),
|
||||||
|
|
||||||
dwarf,
|
dwarf,
|
||||||
unit_range_list: RangeList(Vec::new()),
|
unit_range_list: RangeList(Vec::new()),
|
||||||
|
@ -177,7 +168,7 @@ impl<'tcx> DebugContext<'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit(&mut self, artifact: &mut Artifact) {
|
pub fn emit<P: WriteDebugInfo>(&mut self, product: &mut P) {
|
||||||
let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone());
|
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.root();
|
||||||
let root = self.dwarf.unit.get_mut(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));
|
let mut sections = Sections::new(WriterRelocate::new(self));
|
||||||
self.dwarf.write(&mut sections).unwrap();
|
self.dwarf.write(&mut sections).unwrap();
|
||||||
|
|
||||||
|
let mut section_map = HashMap::new();
|
||||||
let _: Result<()> = sections.for_each_mut(|id, section| {
|
let _: Result<()> = sections.for_each_mut(|id, section| {
|
||||||
if !section.writer.slice().is_empty() {
|
if !section.writer.slice().is_empty() {
|
||||||
artifact
|
let section_id = product.add_debug_section(id, section.writer.take());
|
||||||
.declare_with(
|
section_map.insert(id, section_id);
|
||||||
id.name(),
|
|
||||||
Decl::section(SectionKind::Debug),
|
|
||||||
section.writer.take(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
let _: Result<()> = sections.for_each(|id, section| {
|
let _: Result<()> = sections.for_each(|id, section| {
|
||||||
for reloc in §ion.relocs {
|
if let Some(section_id) = section_map.get(&id) {
|
||||||
artifact
|
for reloc in §ion.relocs {
|
||||||
.link_with(
|
product.add_debug_reloc(§ion_map, &self.symbols, section_id, reloc);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
@ -235,10 +212,11 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
debug_context: &'a mut DebugContext<'tcx>,
|
debug_context: &'a mut DebugContext<'tcx>,
|
||||||
mir: &Body,
|
mir: &Body,
|
||||||
|
func_id: FuncId,
|
||||||
name: &str,
|
name: &str,
|
||||||
_sig: &Signature,
|
_sig: &Signature,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (symbol, _) = debug_context.symbols.insert_full(name.to_string());
|
let (symbol, _) = debug_context.symbols.insert_full(func_id, name.to_string());
|
||||||
|
|
||||||
// FIXME: add to appropriate scope intead of root
|
// FIXME: add to appropriate scope intead of root
|
||||||
let scope = debug_context.dwarf.unit.root();
|
let scope = debug_context.dwarf.unit.root();
|
||||||
|
|
|
@ -8,10 +8,10 @@ use rustc::session::config::{DebugInfo, OutputType};
|
||||||
use rustc_codegen_ssa::back::linker::LinkerInfo;
|
use rustc_codegen_ssa::back::linker::LinkerInfo;
|
||||||
use rustc_codegen_ssa::CrateInfo;
|
use rustc_codegen_ssa::CrateInfo;
|
||||||
|
|
||||||
use cranelift_faerie::*;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use crate::backend::{Emit, WriteDebugInfo};
|
||||||
|
|
||||||
pub fn codegen_crate(
|
pub fn codegen_crate(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
metadata: EncodedMetadata,
|
metadata: EncodedMetadata,
|
||||||
|
@ -147,36 +147,34 @@ fn run_aot(
|
||||||
need_metadata_module: bool,
|
need_metadata_module: bool,
|
||||||
) -> Box<CodegenResults> {
|
) -> Box<CodegenResults> {
|
||||||
let new_module = |name: String| {
|
let new_module = |name: String| {
|
||||||
let module: Module<FaerieBackend> = Module::new(
|
let module = crate::backend::make_module(tcx.sess, name);
|
||||||
FaerieBuilder::new(
|
|
||||||
crate::build_isa(tcx.sess, true),
|
|
||||||
name + ".o",
|
|
||||||
FaerieTrapCollection::Disabled,
|
|
||||||
cranelift_module::default_libcall_names(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
assert_eq!(pointer_ty(tcx), module.target_config().pointer_type());
|
assert_eq!(pointer_ty(tcx), module.target_config().pointer_type());
|
||||||
module
|
module
|
||||||
};
|
};
|
||||||
|
|
||||||
let emit_module = |kind: ModuleKind,
|
fn emit_module<B: Backend>(
|
||||||
mut module: Module<FaerieBackend>,
|
tcx: TyCtxt<'_>,
|
||||||
debug: Option<DebugContext>| {
|
name: String,
|
||||||
|
kind: ModuleKind,
|
||||||
|
mut module: Module<B>,
|
||||||
|
debug: Option<DebugContext>,
|
||||||
|
) -> CompiledModule
|
||||||
|
where B::Product: Emit + WriteDebugInfo,
|
||||||
|
{
|
||||||
module.finalize_definitions();
|
module.finalize_definitions();
|
||||||
let mut artifact = module.finish().artifact;
|
let mut product = module.finish();
|
||||||
|
|
||||||
if let Some(mut debug) = debug {
|
if let Some(mut debug) = debug {
|
||||||
debug.emit(&mut artifact);
|
debug.emit(&mut product);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tmp_file = tcx
|
let tmp_file = tcx
|
||||||
.output_filenames(LOCAL_CRATE)
|
.output_filenames(LOCAL_CRATE)
|
||||||
.temp_path(OutputType::Object, Some(&artifact.name));
|
.temp_path(OutputType::Object, Some(&name));
|
||||||
let obj = artifact.emit().unwrap();
|
let obj = product.emit();
|
||||||
std::fs::write(&tmp_file, obj).unwrap();
|
std::fs::write(&tmp_file, obj).unwrap();
|
||||||
CompiledModule {
|
CompiledModule {
|
||||||
name: artifact.name,
|
name,
|
||||||
kind,
|
kind,
|
||||||
object: Some(tmp_file),
|
object: Some(tmp_file),
|
||||||
bytecode: None,
|
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
|
let mut debug = if tcx.sess.opts.debuginfo != DebugInfo::None
|
||||||
// macOS debuginfo doesn't work yet (see #303)
|
// macOS debuginfo doesn't work yet (see #303)
|
||||||
|
@ -192,14 +190,14 @@ fn run_aot(
|
||||||
{
|
{
|
||||||
let debug = DebugContext::new(
|
let debug = DebugContext::new(
|
||||||
tcx,
|
tcx,
|
||||||
faerie_module.target_config().pointer_type().bytes() as u8,
|
module.target_config().pointer_type().bytes() as u8,
|
||||||
);
|
);
|
||||||
Some(debug)
|
Some(debug)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
codegen_cgus(tcx, &mut faerie_module, &mut debug);
|
codegen_cgus(tcx, &mut module, &mut debug);
|
||||||
|
|
||||||
tcx.sess.abort_if_errors();
|
tcx.sess.abort_if_errors();
|
||||||
|
|
||||||
|
@ -221,17 +219,14 @@ fn run_aot(
|
||||||
.as_str()
|
.as_str()
|
||||||
.to_string();
|
.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
|
let tmp_file = tcx
|
||||||
.output_filenames(LOCAL_CRATE)
|
.output_filenames(LOCAL_CRATE)
|
||||||
.temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
|
.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();
|
std::fs::write(&tmp_file, obj).unwrap();
|
||||||
|
|
||||||
(metadata_cgu_name, tmp_file)
|
(metadata_cgu_name, tmp_file)
|
||||||
|
@ -251,12 +246,16 @@ fn run_aot(
|
||||||
Box::new(CodegenResults {
|
Box::new(CodegenResults {
|
||||||
crate_name: tcx.crate_name(LOCAL_CRATE),
|
crate_name: tcx.crate_name(LOCAL_CRATE),
|
||||||
modules: vec![emit_module(
|
modules: vec![emit_module(
|
||||||
|
tcx,
|
||||||
|
"some_file".to_string(),
|
||||||
ModuleKind::Regular,
|
ModuleKind::Regular,
|
||||||
faerie_module,
|
module,
|
||||||
debug,
|
debug,
|
||||||
)],
|
)],
|
||||||
allocator_module: if created_alloc_shim {
|
allocator_module: if created_alloc_shim {
|
||||||
Some(emit_module(
|
Some(emit_module(
|
||||||
|
tcx,
|
||||||
|
"allocator_shim".to_string(),
|
||||||
ModuleKind::Allocator,
|
ModuleKind::Allocator,
|
||||||
allocator_module,
|
allocator_module,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -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)]
|
#![allow(intra_doc_link_resolution_failure)]
|
||||||
|
|
||||||
extern crate flate2;
|
extern crate flate2;
|
||||||
|
@ -35,6 +35,7 @@ mod allocator;
|
||||||
mod analyze;
|
mod analyze;
|
||||||
mod archive;
|
mod archive;
|
||||||
mod base;
|
mod base;
|
||||||
|
mod backend;
|
||||||
mod cast;
|
mod cast;
|
||||||
mod codegen_i128;
|
mod codegen_i128;
|
||||||
mod common;
|
mod common;
|
||||||
|
|
|
@ -9,6 +9,8 @@ use rustc_data_structures::owning_ref::{self, OwningRef};
|
||||||
use rustc_data_structures::rustc_erase_owner;
|
use rustc_data_structures::rustc_erase_owner;
|
||||||
use rustc_target::spec::Target;
|
use rustc_target::spec::Target;
|
||||||
|
|
||||||
|
use crate::backend::WriteMetadata;
|
||||||
|
|
||||||
pub struct CraneliftMetadataLoader;
|
pub struct CraneliftMetadataLoader;
|
||||||
|
|
||||||
impl MetadataLoader for 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
|
// 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<P: WriteMetadata>(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata {
|
||||||
use flate2::write::DeflateEncoder;
|
use flate2::write::DeflateEncoder;
|
||||||
use flate2::Compression;
|
use flate2::Compression;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
@ -95,24 +97,11 @@ pub fn write_metadata(tcx: TyCtxt<'_>, artifact: &mut faerie::Artifact) -> Encod
|
||||||
.write_all(&metadata.raw_data)
|
.write_all(&metadata.raw_data)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
artifact
|
product.add_rustc_section(
|
||||||
.declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data))
|
rustc::middle::exported_symbols::metadata_symbol_name(tcx),
|
||||||
.unwrap();
|
compressed,
|
||||||
artifact
|
tcx.sess.target.target.options.is_like_osx,
|
||||||
.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();
|
|
||||||
|
|
||||||
metadata
|
metadata
|
||||||
}
|
}
|
||||||
|
|
4
test.sh
4
test.sh
|
@ -4,10 +4,10 @@ set -e
|
||||||
|
|
||||||
if [[ "$1" == "--release" ]]; then
|
if [[ "$1" == "--release" ]]; then
|
||||||
export CHANNEL='release'
|
export CHANNEL='release'
|
||||||
cargo build --release
|
cargo build --release $CG_CLIF_COMPILE_FLAGS
|
||||||
else
|
else
|
||||||
export CHANNEL='debug'
|
export CHANNEL='debug'
|
||||||
cargo build
|
cargo build $CG_CLIF_COMPILE_FLAGS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source config.sh
|
source config.sh
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue