Remove get_finalized_*

This commit is contained in:
bjorn3
2020-09-30 13:53:01 +02:00
parent 7dcfb1b47b
commit 4483c3740a
5 changed files with 84 additions and 113 deletions

View File

@@ -1,6 +1,6 @@
//! Defines the `Backend` trait. //! Defines the `Backend` trait.
use crate::DataContext; use crate::{DataContext, FuncOrDataId};
use crate::DataId; use crate::DataId;
use crate::FuncId; use crate::FuncId;
use crate::Linkage; use crate::Linkage;
@@ -11,7 +11,7 @@ use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::Context; use cranelift_codegen::Context;
use cranelift_codegen::{binemit, ir}; use cranelift_codegen::{binemit, ir};
use std::borrow::ToOwned; use std::{borrow::ToOwned, collections::HashMap};
use std::boxed::Box; use std::boxed::Box;
use std::string::String; use std::string::String;
@@ -38,14 +38,6 @@ where
/// The results of "compiling" a data object. /// The results of "compiling" a data object.
type CompiledData; type CompiledData;
/// The completed output artifact for a function, if this is meaningful for
/// the `Backend`.
type FinalizedFunction;
/// The completed output artifact for a data object, if this is meaningful for
/// the `Backend`.
type FinalizedData;
/// This is an object returned by `Module`'s /// This is an object returned by `Module`'s
/// [`finish`](struct.Module.html#method.finish) function, /// [`finish`](struct.Module.html#method.finish) function,
/// if the `Backend` has a purpose for this. /// if the `Backend` has a purpose for this.
@@ -140,10 +132,7 @@ where
id: FuncId, id: FuncId,
func: &Self::CompiledFunction, func: &Self::CompiledFunction,
contents: &ModuleContents<Self>, contents: &ModuleContents<Self>,
) -> Self::FinalizedFunction; );
/// Return the finalized artifact from the backend, if relevant.
fn get_finalized_function(&self, func: &Self::CompiledFunction) -> Self::FinalizedFunction;
/// Perform all outstanding relocations on the given data object. This requires all /// Perform all outstanding relocations on the given data object. This requires all
/// `Local` and `Export` entities referenced to be defined. /// `Local` and `Export` entities referenced to be defined.
@@ -155,10 +144,7 @@ where
id: DataId, id: DataId,
data: &Self::CompiledData, data: &Self::CompiledData,
contents: &ModuleContents<Self>, contents: &ModuleContents<Self>,
) -> Self::FinalizedData; );
/// Return the finalized artifact from the backend, if relevant.
fn get_finalized_data(&self, data: &Self::CompiledData) -> Self::FinalizedData;
/// "Publish" all finalized functions and data objects to their ultimate destinations. /// "Publish" all finalized functions and data objects to their ultimate destinations.
/// ///
@@ -168,7 +154,11 @@ 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, contents: &ModuleContents<Self>) -> Self::Product; fn finish(
self,
names: HashMap<String, FuncOrDataId>,
contents: ModuleContents<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

View File

@@ -717,34 +717,6 @@ where
self.backend.publish(); self.backend.publish();
} }
/// Return the finalized artifact from the backend, if it provides one.
pub fn get_finalized_function(&mut self, func: FuncId) -> B::FinalizedFunction {
let info = &self.contents.functions[func];
debug_assert!(
!self.functions_to_finalize.iter().any(|x| *x == func),
"function not yet finalized"
);
self.backend.get_finalized_function(
info.compiled
.as_ref()
.expect("function must be compiled before it can be finalized"),
)
}
/// Return the finalized artifact from the backend, if it provides one.
pub fn get_finalized_data(&mut self, data: DataId) -> B::FinalizedData {
let info = &self.contents.data_objects[data];
debug_assert!(
!self.data_objects_to_finalize.iter().any(|x| *x == data),
"data object not yet finalized"
);
self.backend.get_finalized_data(
info.compiled
.as_ref()
.expect("data object must be compiled before it can be finalized"),
)
}
/// Return the target isa /// Return the target isa
pub fn isa(&self) -> &dyn isa::TargetIsa { pub fn isa(&self) -> &dyn isa::TargetIsa {
self.backend.isa() self.backend.isa()
@@ -754,6 +726,6 @@ where
/// 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(self) -> B::Product { pub fn finish(self) -> B::Product {
self.backend.finish(&self.contents) self.backend.finish(self.names, self.contents)
} }
} }

View File

@@ -8,8 +8,8 @@ use cranelift_codegen::entity::SecondaryMap;
use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::{self, binemit, ir}; use cranelift_codegen::{self, binemit, ir};
use cranelift_module::{ use cranelift_module::{
Backend, DataContext, DataDescription, DataId, FuncId, Init, Linkage, ModuleError, Backend, DataContext, DataDescription, DataId, FuncId, FuncOrDataId, Init, Linkage,
ModuleContents, ModuleResult, ModuleContents, ModuleError, ModuleResult,
}; };
use object::write::{ use object::write::{
Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection, Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,
@@ -127,11 +127,6 @@ impl Backend for ObjectBackend {
type CompiledFunction = ObjectCompiledFunction; type CompiledFunction = ObjectCompiledFunction;
type CompiledData = ObjectCompiledData; type CompiledData = ObjectCompiledData;
// There's no need to return individual artifacts; we're writing them into
// the output file instead.
type FinalizedFunction = ();
type FinalizedData = ();
type Product = ObjectProduct; type Product = ObjectProduct;
/// Create a new `ObjectBackend` using the given Cranelift target. /// Create a new `ObjectBackend` using the given Cranelift target.
@@ -433,10 +428,6 @@ impl Backend for ObjectBackend {
// Nothing to do. // Nothing to do.
} }
fn get_finalized_function(&self, _func: &ObjectCompiledFunction) {
// Nothing to do.
}
fn finalize_data( fn finalize_data(
&mut self, &mut self,
_id: DataId, _id: DataId,
@@ -446,15 +437,15 @@ impl Backend for ObjectBackend {
// Nothing to do. // Nothing to do.
} }
fn get_finalized_data(&self, _data: &ObjectCompiledData) {
// Nothing to do.
}
fn publish(&mut self) { fn publish(&mut self) {
// Nothing to do. // Nothing to do.
} }
fn finish(mut self, contents: &ModuleContents<Self>) -> ObjectProduct { fn finish(
mut self,
_names: HashMap<String, FuncOrDataId>,
contents: ModuleContents<Self>,
) -> ObjectProduct {
let symbol_relocs = mem::take(&mut self.relocs); let symbol_relocs = mem::take(&mut self.relocs);
for symbol in symbol_relocs { for symbol in symbol_relocs {
for &RelocRecord { for &RelocRecord {
@@ -466,7 +457,7 @@ impl Backend for ObjectBackend {
addend, addend,
} in &symbol.relocs } in &symbol.relocs
{ {
let target_symbol = self.get_symbol(contents, name); let target_symbol = self.get_symbol(&contents, name);
self.object self.object
.add_relocation( .add_relocation(
symbol.section, symbol.section,
@@ -503,11 +494,7 @@ impl Backend for ObjectBackend {
impl ObjectBackend { impl ObjectBackend {
// This should only be called during finish 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, contents: &ModuleContents<Self>, name: &ir::ExternalName) -> SymbolId {
&mut self,
contents: &ModuleContents<Self>,
name: &ir::ExternalName,
) -> SymbolId {
match *name { match *name {
ir::ExternalName::User { .. } => { ir::ExternalName::User { .. } => {
if contents.is_function(name) { if contents.is_function(name) {

View File

@@ -8,8 +8,8 @@ use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::settings::Configurable; use cranelift_codegen::settings::Configurable;
use cranelift_codegen::{self, ir, settings}; use cranelift_codegen::{self, ir, settings};
use cranelift_module::{ use cranelift_module::{
Backend, DataContext, DataDescription, DataId, FuncId, Init, Linkage, ModuleContents, Backend, DataContext, DataDescription, DataId, FuncId, FuncOrDataId, Init, Linkage,
ModuleResult, ModuleContents, ModuleResult,
}; };
use cranelift_native; use cranelift_native;
#[cfg(not(windows))] #[cfg(not(windows))]
@@ -154,12 +154,60 @@ pub struct SimpleJITCompiledData {
} }
/// A handle to allow freeing memory allocated by the `Backend`. /// A handle to allow freeing memory allocated by the `Backend`.
pub struct SimpleJITMemoryHandle { struct SimpleJITMemoryHandle {
code: Memory, code: Memory,
readonly: Memory, readonly: Memory,
writable: Memory, writable: Memory,
} }
/// A `SimpleJITProduct` allows looking up the addresses of all functions and data objects
/// defined in the original module.
pub struct SimpleJITProduct {
memory: SimpleJITMemoryHandle,
names: HashMap<String, FuncOrDataId>,
contents: ModuleContents<SimpleJITBackend>,
}
impl SimpleJITProduct {
/// Free memory allocated for code and data segments of compiled functions.
///
/// # Safety
///
/// Because this function invalidates any pointers retrived from the
/// corresponding module, it should only be used when none of the functions
/// from that module are currently executing and none of the `fn` pointers
/// are called afterwards.
pub unsafe fn free_memory(&mut self) {
self.memory.code.free_memory();
self.memory.readonly.free_memory();
self.memory.writable.free_memory();
}
/// Get the `FuncOrDataId` associated with the given name.
pub fn func_or_data_for_func(&self, name: &str) -> Option<FuncOrDataId> {
self.names.get(name).copied()
}
/// Return the address of a function.
pub fn lookup_func(&self, func_id: FuncId) -> *const u8 {
self.contents
.get_function_definition(&func_id.into())
.0
.unwrap_or_else(|| panic!("{} is not defined", func_id))
.code
}
/// Return the address and size of a data object.
pub fn lookup_data(&self, data_id: DataId) -> (*const u8, usize) {
let data = self
.contents
.get_data_definition(&data_id.into())
.0
.unwrap_or_else(|| panic!("{} is not defined", data_id));
(data.storage, data.size)
}
}
impl SimpleJITBackend { impl SimpleJITBackend {
fn lookup_symbol(&self, name: &str) -> *const u8 { fn lookup_symbol(&self, name: &str) -> *const u8 {
match self.symbols.get(name) { match self.symbols.get(name) {
@@ -225,19 +273,11 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
type CompiledFunction = SimpleJITCompiledFunction; type CompiledFunction = SimpleJITCompiledFunction;
type CompiledData = SimpleJITCompiledData; type CompiledData = SimpleJITCompiledData;
/// SimpleJIT emits code and data into memory, and provides raw pointers
/// to them. They are valid for the remainder of the program's life, unless
/// [`free_memory`] is used.
///
/// [`free_memory`]: #method.free_memory
type FinalizedFunction = *const u8;
type FinalizedData = (*mut u8, usize);
/// SimpleJIT emits code and data into memory as it processes them, so it /// SimpleJIT emits code and data into memory as it processes them, so it
/// doesn't need to provide anything after the `Module` is complete. /// doesn't need to provide anything after the `Module` is complete.
/// The handle object that is returned can optionally be used to free /// The handle object that is returned can optionally be used to free
/// allocated memory if required. /// allocated memory if required.
type Product = SimpleJITMemoryHandle; type Product = SimpleJITProduct;
/// Create a new `SimpleJITBackend`. /// Create a new `SimpleJITBackend`.
fn new(builder: SimpleJITBuilder) -> Self { fn new(builder: SimpleJITBuilder) -> Self {
@@ -444,7 +484,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
_id: FuncId, _id: FuncId,
func: &Self::CompiledFunction, func: &Self::CompiledFunction,
contents: &ModuleContents<Self>, contents: &ModuleContents<Self>,
) -> Self::FinalizedFunction { ) {
use std::ptr::write_unaligned; use std::ptr::write_unaligned;
for &RelocRecord { for &RelocRecord {
@@ -486,11 +526,6 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
func.code
}
fn get_finalized_function(&self, func: &Self::CompiledFunction) -> Self::FinalizedFunction {
func.code
} }
fn finalize_data( fn finalize_data(
@@ -498,7 +533,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
_id: DataId, _id: DataId,
data: &Self::CompiledData, data: &Self::CompiledData,
contents: &ModuleContents<Self>, contents: &ModuleContents<Self>,
) -> Self::FinalizedData { ) {
use std::ptr::write_unaligned; use std::ptr::write_unaligned;
for &RelocRecord { for &RelocRecord {
@@ -535,11 +570,6 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
(data.storage, data.size)
}
fn get_finalized_data(&self, data: &Self::CompiledData) -> Self::FinalizedData {
(data.storage, data.size)
} }
fn publish(&mut self) { fn publish(&mut self) {
@@ -555,8 +585,16 @@ 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, _contents: &ModuleContents<Self>) -> Self::Product { fn finish(
self.memory self,
names: HashMap<String, FuncOrDataId>,
contents: ModuleContents<Self>,
) -> Self::Product {
SimpleJITProduct {
memory: self.memory,
names,
contents,
}
} }
} }
@@ -603,22 +641,6 @@ fn lookup_with_dlsym(name: &str) -> *const u8 {
} }
} }
impl SimpleJITMemoryHandle {
/// Free memory allocated for code and data segments of compiled functions.
///
/// # Safety
///
/// Because this function invalidates any pointers retrived from the
/// corresponding module, it should only be used when none of the functions
/// from that module are currently executing and none of the`fn` pointers
/// are called afterwards.
pub unsafe fn free_memory(&mut self) {
self.code.free_memory();
self.readonly.free_memory();
self.writable.free_memory();
}
}
struct SimpleJITRelocSink { struct SimpleJITRelocSink {
pub relocs: Vec<RelocRecord>, pub relocs: Vec<RelocRecord>,
} }

View File

@@ -26,7 +26,7 @@
mod backend; mod backend;
mod memory; mod memory;
pub use crate::backend::{SimpleJITBackend, SimpleJITBuilder}; pub use crate::backend::{SimpleJITBackend, SimpleJITBuilder, SimpleJITProduct};
/// Version number of this crate. /// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const VERSION: &str = env!("CARGO_PKG_VERSION");