cranelift-object: move relocation processing to finish

This removes the need to call `finalize_definitions` for cranelift-object.
`finalize_definitions` is only intended for backends that produce
finalized functions and data objects, which cranelift-object does not.
This commit is contained in:
Philip Craig
2020-01-24 14:09:32 +10:00
committed by Benjamin Bouvier
parent 376654bdfc
commit 3c15f8f129
5 changed files with 72 additions and 87 deletions

View File

@@ -311,7 +311,7 @@ impl Backend for FaerieBackend {
// Nothing to do.
}
fn finish(self) -> FaerieProduct {
fn finish(self, _namespace: &ModuleNamespace<Self>) -> FaerieProduct {
FaerieProduct {
artifact: self.artifact,
trap_manifest: self.trap_manifest,

View File

@@ -146,7 +146,7 @@ where
/// Consume this `Backend` and return a result. Some implementations may
/// provide additional functionality through this result.
fn finish(self) -> Self::Product;
fn finish(self, namespace: &ModuleNamespace<Self>) -> Self::Product;
}
/// Default names for `ir::LibCall`s. A function by this name is imported into the object as

View File

@@ -714,8 +714,9 @@ where
/// Consume the module and return the resulting `Product`. Some `Backend`
/// implementations may provide additional functionality available after
/// a `Module` is complete.
pub fn finish(mut self) -> B::Product {
self.finalize_definitions();
self.backend.finish()
pub fn finish(self) -> B::Product {
self.backend.finish(&ModuleNamespace::<B> {
contents: &self.contents,
})
}
}

View File

@@ -16,6 +16,7 @@ use object::write::{
};
use object::{RelocationEncoding, RelocationKind, SymbolFlags, SymbolKind, SymbolScope};
use std::collections::HashMap;
use std::mem;
use target_lexicon::PointerWidth;
#[derive(Debug)]
@@ -79,6 +80,7 @@ pub struct ObjectBackend {
functions: SecondaryMap<FuncId, Option<SymbolId>>,
data_objects: SecondaryMap<DataId, Option<SymbolId>>,
traps: SecondaryMap<FuncId, Vec<ObjectTrapSite>>,
relocs: Vec<SymbolRelocs>,
libcalls: HashMap<ir::LibCall, SymbolId>,
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
collect_traps: ObjectTrapCollection,
@@ -109,6 +111,7 @@ impl Backend for ObjectBackend {
functions: SecondaryMap::new(),
data_objects: SecondaryMap::new(),
traps: SecondaryMap::new(),
relocs: Vec::new(),
libcalls: HashMap::new(),
libcall_names: builder.libcall_names,
collect_traps: builder.collect_traps,
@@ -212,13 +215,15 @@ impl Backend for ObjectBackend {
let offset = self
.object
.add_symbol_data(symbol, section, &code, self.function_alignment);
if !reloc_sink.relocs.is_empty() {
self.relocs.push(SymbolRelocs {
section,
offset,
relocs: reloc_sink.relocs,
});
}
self.traps[func_id] = trap_sink.sites;
Ok(ObjectCompiledFunction {
offset,
size: code_size,
section,
relocs: reloc_sink.relocs,
})
Ok(ObjectCompiledFunction)
}
fn define_data(
@@ -290,11 +295,14 @@ impl Backend for ObjectBackend {
let offset =
self.object
.add_symbol_data(symbol, section, &data, u64::from(align.unwrap_or(1)));
Ok(ObjectCompiledData {
offset,
section,
relocs,
})
if !relocs.is_empty() {
self.relocs.push(SymbolRelocs {
section,
offset,
relocs,
});
}
Ok(ObjectCompiledData)
}
fn write_data_funcaddr(
@@ -319,34 +327,10 @@ impl Backend for ObjectBackend {
fn finalize_function(
&mut self,
_id: FuncId,
func: &ObjectCompiledFunction,
namespace: &ModuleNamespace<Self>,
_func: &ObjectCompiledFunction,
_namespace: &ModuleNamespace<Self>,
) {
for &RelocRecord {
offset,
ref name,
kind,
encoding,
size,
addend,
} in &func.relocs
{
let offset = func.offset + u64::from(offset);
let symbol = self.get_symbol(namespace, name);
self.object
.add_relocation(
func.section,
Relocation {
offset,
size,
kind,
encoding,
symbol,
addend,
},
)
.unwrap();
}
// Nothing to do.
}
fn get_finalized_function(&self, _func: &ObjectCompiledFunction) {
@@ -356,34 +340,10 @@ impl Backend for ObjectBackend {
fn finalize_data(
&mut self,
_id: DataId,
data: &ObjectCompiledData,
namespace: &ModuleNamespace<Self>,
_data: &ObjectCompiledData,
_namespace: &ModuleNamespace<Self>,
) {
for &RelocRecord {
offset,
ref name,
kind,
encoding,
size,
addend,
} in &data.relocs
{
let offset = data.offset + u64::from(offset);
let symbol = self.get_symbol(namespace, name);
self.object
.add_relocation(
data.section,
Relocation {
offset,
size,
kind,
encoding,
symbol,
addend,
},
)
.unwrap();
}
// Nothing to do.
}
fn get_finalized_data(&self, _data: &ObjectCompiledData) {
@@ -394,7 +354,36 @@ impl Backend for ObjectBackend {
// Nothing to do.
}
fn finish(self) -> ObjectProduct {
fn finish(mut self, namespace: &ModuleNamespace<Self>) -> ObjectProduct {
let mut symbol_relocs = Vec::new();
mem::swap(&mut symbol_relocs, &mut self.relocs);
for symbol in symbol_relocs {
for &RelocRecord {
offset,
ref name,
kind,
encoding,
size,
addend,
} in &symbol.relocs
{
let target_symbol = self.get_symbol(namespace, name);
self.object
.add_relocation(
symbol.section,
Relocation {
offset: symbol.offset + u64::from(offset),
size,
kind,
encoding,
symbol: target_symbol,
addend,
},
)
.unwrap();
}
}
ObjectProduct {
object: self.object,
functions: self.functions,
@@ -405,7 +394,7 @@ impl Backend for ObjectBackend {
}
impl ObjectBackend {
// This should only be called during finalization because it creates
// This should only be called during finish because it creates
// symbols for missing libcalls.
fn get_symbol(
&mut self,
@@ -459,20 +448,8 @@ fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {
(scope, weak)
}
#[derive(Clone)]
pub struct ObjectCompiledFunction {
offset: u64,
size: u32,
section: SectionId,
relocs: Vec<RelocRecord>,
}
#[derive(Clone)]
pub struct ObjectCompiledData {
offset: u64,
section: SectionId,
relocs: Vec<RelocRecord>,
}
pub struct ObjectCompiledFunction;
pub struct ObjectCompiledData;
/// This is the output of `Module`'s
/// [`finish`](../cranelift_module/struct.Module.html#method.finish) function.
@@ -509,6 +486,13 @@ impl ObjectProduct {
}
}
#[derive(Clone)]
struct SymbolRelocs {
section: SectionId,
offset: u64,
relocs: Vec<RelocRecord>,
}
#[derive(Clone)]
struct RelocRecord {
offset: CodeOffset,

View File

@@ -507,7 +507,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
///
/// This method does not need to be called when access to the memory
/// handle is not required.
fn finish(self) -> Self::Product {
fn finish(self, _namespace: &ModuleNamespace<Self>) -> Self::Product {
self.memory
}
}