1 use std::collections::HashMap;
3 use rustc::session::Session;
5 use cranelift_module::{FuncId, Module};
8 #[cfg(feature = "backend_object")]
9 use object::{SectionKind, RelocationKind, RelocationEncoding};
10 #[cfg(feature = "backend_object")]
12 use cranelift_faerie::{FaerieBackend, FaerieBuilder, FaerieProduct, FaerieTrapCollection};
14 #[cfg(feature = "backend_object")]
15 use cranelift_object::*;
19 use crate::debuginfo::{DebugReloc, DebugRelocName};
21 pub trait WriteMetadata {
22 fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, is_like_osx: bool);
25 impl WriteMetadata for faerie::Artifact {
26 fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, is_like_osx: bool) {
28 .declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data))
31 .define_with_symbols(".rustc", data, {
32 let mut map = std::collections::BTreeMap::new();
33 // FIXME implement faerie elf backend section custom symbols
34 // For MachO this is necessary to prevent the linker from throwing away the .rustc section,
35 // but for ELF it isn't.
48 #[cfg(feature = "backend_object")]
49 impl WriteMetadata for object::write::Object {
50 fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, _is_like_osx: bool) {
51 let segment = self.segment_name(object::write::StandardSegment::Data).to_vec();
52 let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data);
53 let offset = self.append_section_data(section_id, &data, 1);
54 // For MachO and probably PE this is necessary to prevent the linker from throwing away the
55 // .rustc section. For ELF this isn't necessary, but it also doesn't harm.
56 self.add_symbol(object::write::Symbol {
57 name: symbol_name.into_bytes(),
59 size: data.len() as u64,
60 kind: object::SymbolKind::Data,
61 scope: object::SymbolScope::Dynamic,
63 section: Some(section_id),
68 pub trait WriteDebugInfo {
71 fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
74 section_map: &HashMap<SectionId, Self::SectionId>,
75 symbol_map: &indexmap::IndexMap<FuncId, String>,
76 from: &Self::SectionId,
81 impl WriteDebugInfo for FaerieProduct {
82 type SectionId = SectionId;
84 fn add_debug_section(&mut self, id: SectionId, data: Vec<u8>) -> SectionId {
85 self.artifact.declare_with(id.name(), Decl::section(faerie::SectionKind::Debug), data).unwrap();
91 _section_map: &HashMap<SectionId, Self::SectionId>,
92 symbol_map: &indexmap::IndexMap<FuncId, String>,
93 from: &Self::SectionId,
101 to: match reloc.name {
102 DebugRelocName::Section(id) => id.name(),
103 DebugRelocName::Symbol(index) => &symbol_map.get_index(index).unwrap().1,
105 at: u64::from(reloc.offset),
107 faerie::Reloc::Debug {
109 addend: reloc.addend as i32,
112 .expect("faerie relocation error");
116 #[cfg(feature = "backend_object")]
117 impl WriteDebugInfo for ObjectProduct {
118 type SectionId = (object::write::SectionId, object::write::SymbolId);
120 fn add_debug_section(
124 ) -> (object::write::SectionId, object::write::SymbolId) {
125 let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
126 let name = id.name().as_bytes().to_vec();
127 let section_id = self.object.add_section(segment, name, SectionKind::Debug);
128 self.object.section_mut(section_id).set_data(data, 1);
129 let symbol_id = self.object.section_symbol(section_id);
130 (section_id, symbol_id)
135 section_map: &HashMap<SectionId, Self::SectionId>,
136 symbol_map: &indexmap::IndexMap<FuncId, String>,
137 from: &Self::SectionId,
140 let symbol = match reloc.name {
141 DebugRelocName::Section(id) => section_map.get(&id).unwrap().1,
142 DebugRelocName::Symbol(id) => {
143 self.function_symbol(*symbol_map.get_index(id).unwrap().0)
146 self.object.add_relocation(from.0, Relocation {
147 offset: u64::from(reloc.offset),
149 kind: RelocationKind::Absolute,
150 encoding: RelocationEncoding::Generic,
151 size: reloc.size * 8,
152 addend: reloc.addend,
158 fn emit(self) -> Vec<u8>;
161 impl Emit for FaerieProduct {
162 fn emit(self) -> Vec<u8> {
163 self.artifact.emit().unwrap()
167 #[cfg(feature = "backend_object")]
168 impl Emit for ObjectProduct {
169 fn emit(self) -> Vec<u8> {
170 self.object.write().unwrap()
174 #[cfg(not(feature = "backend_object"))]
175 pub fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Artifact)) -> Vec<u8> {
176 let mut metadata_artifact = faerie::Artifact::new(
177 crate::build_isa(sess, true).triple().clone(),
180 f(&mut metadata_artifact);
181 metadata_artifact.emit().unwrap()
184 #[cfg(feature = "backend_object")]
185 pub fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Object)) -> Vec<u8> {
186 let triple = crate::build_isa(sess, true).triple().clone();
187 let mut metadata_object =
188 object::write::Object::new(triple.binary_format, triple.architecture);
189 metadata_object.add_file_symbol(name.as_bytes().to_vec());
190 f(&mut metadata_object);
191 metadata_object.write().unwrap()
194 pub type Backend = impl cranelift_module::Backend<Product: Emit + WriteDebugInfo>;
196 #[cfg(not(feature = "backend_object"))]
197 pub fn make_module(sess: &Session, name: String) -> Module<Backend> {
198 let module: Module<FaerieBackend> = Module::new(
200 crate::build_isa(sess, true),
202 FaerieTrapCollection::Disabled,
203 cranelift_module::default_libcall_names(),
210 #[cfg(feature = "backend_object")]
211 pub fn make_module(sess: &Session, name: String) -> Module<Backend> {
212 let module: Module<ObjectBackend> = Module::new(
214 crate::build_isa(sess, true),
216 ObjectTrapCollection::Disabled,
217 cranelift_module::default_libcall_names(),