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.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(self) -> FaerieProduct {
|
fn finish(self, _namespace: &ModuleNamespace<Self>) -> FaerieProduct {
|
||||||
FaerieProduct {
|
FaerieProduct {
|
||||||
artifact: self.artifact,
|
artifact: self.artifact,
|
||||||
trap_manifest: self.trap_manifest,
|
trap_manifest: self.trap_manifest,
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ where
|
|||||||
|
|
||||||
/// Consume this `Backend` and return a result. Some implementations may
|
/// Consume this `Backend` and return a result. Some implementations may
|
||||||
/// provide additional functionality through this result.
|
/// 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
|
/// 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`
|
/// Consume the module and return the resulting `Product`. Some `Backend`
|
||||||
/// implementations may provide additional functionality available after
|
/// implementations may provide additional functionality available after
|
||||||
/// a `Module` is complete.
|
/// a `Module` is complete.
|
||||||
pub fn finish(mut self) -> B::Product {
|
pub fn finish(self) -> B::Product {
|
||||||
self.finalize_definitions();
|
self.backend.finish(&ModuleNamespace::<B> {
|
||||||
self.backend.finish()
|
contents: &self.contents,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use object::write::{
|
|||||||
};
|
};
|
||||||
use object::{RelocationEncoding, RelocationKind, SymbolFlags, SymbolKind, SymbolScope};
|
use object::{RelocationEncoding, RelocationKind, SymbolFlags, SymbolKind, SymbolScope};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::mem;
|
||||||
use target_lexicon::PointerWidth;
|
use target_lexicon::PointerWidth;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -79,6 +80,7 @@ pub struct ObjectBackend {
|
|||||||
functions: SecondaryMap<FuncId, Option<SymbolId>>,
|
functions: SecondaryMap<FuncId, Option<SymbolId>>,
|
||||||
data_objects: SecondaryMap<DataId, Option<SymbolId>>,
|
data_objects: SecondaryMap<DataId, Option<SymbolId>>,
|
||||||
traps: SecondaryMap<FuncId, Vec<ObjectTrapSite>>,
|
traps: SecondaryMap<FuncId, Vec<ObjectTrapSite>>,
|
||||||
|
relocs: Vec<SymbolRelocs>,
|
||||||
libcalls: HashMap<ir::LibCall, SymbolId>,
|
libcalls: HashMap<ir::LibCall, SymbolId>,
|
||||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
||||||
collect_traps: ObjectTrapCollection,
|
collect_traps: ObjectTrapCollection,
|
||||||
@@ -109,6 +111,7 @@ impl Backend for ObjectBackend {
|
|||||||
functions: SecondaryMap::new(),
|
functions: SecondaryMap::new(),
|
||||||
data_objects: SecondaryMap::new(),
|
data_objects: SecondaryMap::new(),
|
||||||
traps: SecondaryMap::new(),
|
traps: SecondaryMap::new(),
|
||||||
|
relocs: Vec::new(),
|
||||||
libcalls: HashMap::new(),
|
libcalls: HashMap::new(),
|
||||||
libcall_names: builder.libcall_names,
|
libcall_names: builder.libcall_names,
|
||||||
collect_traps: builder.collect_traps,
|
collect_traps: builder.collect_traps,
|
||||||
@@ -212,13 +215,15 @@ impl Backend for ObjectBackend {
|
|||||||
let offset = self
|
let offset = self
|
||||||
.object
|
.object
|
||||||
.add_symbol_data(symbol, section, &code, self.function_alignment);
|
.add_symbol_data(symbol, section, &code, self.function_alignment);
|
||||||
self.traps[func_id] = trap_sink.sites;
|
if !reloc_sink.relocs.is_empty() {
|
||||||
Ok(ObjectCompiledFunction {
|
self.relocs.push(SymbolRelocs {
|
||||||
offset,
|
|
||||||
size: code_size,
|
|
||||||
section,
|
section,
|
||||||
|
offset,
|
||||||
relocs: reloc_sink.relocs,
|
relocs: reloc_sink.relocs,
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
self.traps[func_id] = trap_sink.sites;
|
||||||
|
Ok(ObjectCompiledFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn define_data(
|
fn define_data(
|
||||||
@@ -290,11 +295,14 @@ impl Backend for ObjectBackend {
|
|||||||
let offset =
|
let offset =
|
||||||
self.object
|
self.object
|
||||||
.add_symbol_data(symbol, section, &data, u64::from(align.unwrap_or(1)));
|
.add_symbol_data(symbol, section, &data, u64::from(align.unwrap_or(1)));
|
||||||
Ok(ObjectCompiledData {
|
if !relocs.is_empty() {
|
||||||
offset,
|
self.relocs.push(SymbolRelocs {
|
||||||
section,
|
section,
|
||||||
|
offset,
|
||||||
relocs,
|
relocs,
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
Ok(ObjectCompiledData)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_data_funcaddr(
|
fn write_data_funcaddr(
|
||||||
@@ -319,34 +327,10 @@ impl Backend for ObjectBackend {
|
|||||||
fn finalize_function(
|
fn finalize_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: FuncId,
|
_id: FuncId,
|
||||||
func: &ObjectCompiledFunction,
|
_func: &ObjectCompiledFunction,
|
||||||
namespace: &ModuleNamespace<Self>,
|
_namespace: &ModuleNamespace<Self>,
|
||||||
) {
|
) {
|
||||||
for &RelocRecord {
|
// Nothing to do.
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_finalized_function(&self, _func: &ObjectCompiledFunction) {
|
fn get_finalized_function(&self, _func: &ObjectCompiledFunction) {
|
||||||
@@ -356,34 +340,10 @@ impl Backend for ObjectBackend {
|
|||||||
fn finalize_data(
|
fn finalize_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
_id: DataId,
|
_id: DataId,
|
||||||
data: &ObjectCompiledData,
|
_data: &ObjectCompiledData,
|
||||||
namespace: &ModuleNamespace<Self>,
|
_namespace: &ModuleNamespace<Self>,
|
||||||
) {
|
) {
|
||||||
for &RelocRecord {
|
// Nothing to do.
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_finalized_data(&self, _data: &ObjectCompiledData) {
|
fn get_finalized_data(&self, _data: &ObjectCompiledData) {
|
||||||
@@ -394,7 +354,36 @@ impl Backend for ObjectBackend {
|
|||||||
// Nothing to do.
|
// 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 {
|
ObjectProduct {
|
||||||
object: self.object,
|
object: self.object,
|
||||||
functions: self.functions,
|
functions: self.functions,
|
||||||
@@ -405,7 +394,7 @@ impl Backend for ObjectBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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.
|
// symbols for missing libcalls.
|
||||||
fn get_symbol(
|
fn get_symbol(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -459,20 +448,8 @@ fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {
|
|||||||
(scope, weak)
|
(scope, weak)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
pub struct ObjectCompiledFunction;
|
||||||
pub struct ObjectCompiledFunction {
|
pub struct ObjectCompiledData;
|
||||||
offset: u64,
|
|
||||||
size: u32,
|
|
||||||
section: SectionId,
|
|
||||||
relocs: Vec<RelocRecord>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ObjectCompiledData {
|
|
||||||
offset: u64,
|
|
||||||
section: SectionId,
|
|
||||||
relocs: Vec<RelocRecord>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is the output of `Module`'s
|
/// This is the output of `Module`'s
|
||||||
/// [`finish`](../cranelift_module/struct.Module.html#method.finish) function.
|
/// [`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)]
|
#[derive(Clone)]
|
||||||
struct RelocRecord {
|
struct RelocRecord {
|
||||||
offset: CodeOffset,
|
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
|
/// This method does not need to be called when access to the memory
|
||||||
/// handle is not required.
|
/// handle is not required.
|
||||||
fn finish(self) -> Self::Product {
|
fn finish(self, _namespace: &ModuleNamespace<Self>) -> Self::Product {
|
||||||
self.memory
|
self.memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user