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:
committed by
Benjamin Bouvier
parent
376654bdfc
commit
3c15f8f129
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
self.traps[func_id] = trap_sink.sites;
|
||||
Ok(ObjectCompiledFunction {
|
||||
offset,
|
||||
size: code_size,
|
||||
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)
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user