Allow serializing all cranelift-module data structures (#6172)
* Remove ModuleCompiledFunction The same information can be retrieved using ctx.compiled_code().unwrap().code_info().total_size In addition for Module implementations that don't immediately compile the given function there is no correct value that can be returned. * Don't give anonymous functions and data objects an internal name This internal name can conflict if a module is serialized and then deserialized into another module. It also wasn't used by any of the Module implementations anyway. * Allow serializing all cranelift-module data structures This allows a Module implementation to serialize it's internal state and deserialize it in another compilation session. For example to implement LTO or to load the module into cranelift-interpreter. * Use expect
This commit is contained in:
@@ -1,17 +1,14 @@
|
||||
//! Defines `ObjectModule`.
|
||||
|
||||
use anyhow::anyhow;
|
||||
use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};
|
||||
use cranelift_codegen::entity::SecondaryMap;
|
||||
use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
|
||||
use cranelift_codegen::{self, ir, MachReloc};
|
||||
use cranelift_codegen::{
|
||||
binemit::{Addend, CodeOffset, Reloc},
|
||||
CodegenError,
|
||||
};
|
||||
use cranelift_control::ControlPlane;
|
||||
use cranelift_module::{
|
||||
DataDescription, DataId, FuncId, Init, Linkage, Module, ModuleCompiledFunction,
|
||||
ModuleDeclarations, ModuleError, ModuleExtName, ModuleReloc, ModuleResult,
|
||||
DataDescription, DataId, FuncId, Init, Linkage, Module, ModuleDeclarations, ModuleError,
|
||||
ModuleExtName, ModuleReloc, ModuleResult,
|
||||
};
|
||||
use log::info;
|
||||
use object::write::{
|
||||
@@ -21,7 +18,6 @@ use object::{
|
||||
RelocationEncoding, RelocationKind, SectionKind, SymbolFlags, SymbolKind, SymbolScope,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::mem;
|
||||
use target_lexicon::PointerWidth;
|
||||
|
||||
@@ -135,8 +131,6 @@ pub struct ObjectModule {
|
||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
|
||||
known_symbols: HashMap<ir::KnownSymbol, SymbolId>,
|
||||
per_function_section: bool,
|
||||
anon_func_number: u64,
|
||||
anon_data_number: u64,
|
||||
}
|
||||
|
||||
impl ObjectModule {
|
||||
@@ -156,8 +150,6 @@ impl ObjectModule {
|
||||
libcall_names: builder.libcall_names,
|
||||
known_symbols: HashMap::new(),
|
||||
per_function_section: builder.per_function_section,
|
||||
anon_func_number: 0,
|
||||
anon_data_number: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,16 +211,15 @@ impl Module for ObjectModule {
|
||||
}
|
||||
|
||||
fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {
|
||||
// Symbols starting with .L are completely omitted from the symbol table after linking.
|
||||
// Using hexadecimal instead of decimal for slightly smaller symbol names and often slightly
|
||||
// faster linking.
|
||||
let name = format!(".Lfn{:x}", self.anon_func_number);
|
||||
self.anon_func_number += 1;
|
||||
|
||||
let id = self.declarations.declare_anonymous_function(signature)?;
|
||||
|
||||
let symbol_id = self.object.add_symbol(Symbol {
|
||||
name: name.as_bytes().to_vec(),
|
||||
name: self
|
||||
.declarations
|
||||
.get_function_decl(id)
|
||||
.linkage_name(id)
|
||||
.into_owned()
|
||||
.into_bytes(),
|
||||
value: 0,
|
||||
size: 0,
|
||||
kind: SymbolKind::Text,
|
||||
@@ -287,12 +278,6 @@ impl Module for ObjectModule {
|
||||
}
|
||||
|
||||
fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
|
||||
// Symbols starting with .L are completely omitted from the symbol table after linking.
|
||||
// Using hexadecimal instead of decimal for slightly smaller symbol names and often slightly
|
||||
// faster linking.
|
||||
let name = format!(".Ldata{:x}", self.anon_data_number);
|
||||
self.anon_data_number += 1;
|
||||
|
||||
let id = self.declarations.declare_anonymous_data(writable, tls)?;
|
||||
|
||||
let kind = if tls {
|
||||
@@ -302,7 +287,12 @@ impl Module for ObjectModule {
|
||||
};
|
||||
|
||||
let symbol_id = self.object.add_symbol(Symbol {
|
||||
name: name.as_bytes().to_vec(),
|
||||
name: self
|
||||
.declarations
|
||||
.get_data_decl(id)
|
||||
.linkage_name(id)
|
||||
.into_owned()
|
||||
.into_bytes(),
|
||||
value: 0,
|
||||
size: 0,
|
||||
kind,
|
||||
@@ -321,7 +311,7 @@ impl Module for ObjectModule {
|
||||
func_id: FuncId,
|
||||
ctx: &mut cranelift_codegen::Context,
|
||||
ctrl_plane: &mut ControlPlane,
|
||||
) -> ModuleResult<ModuleCompiledFunction> {
|
||||
) -> ModuleResult<()> {
|
||||
info!("defining function {}: {}", func_id, ctx.func.display());
|
||||
let mut code: Vec<u8> = Vec::new();
|
||||
|
||||
@@ -344,21 +334,20 @@ impl Module for ObjectModule {
|
||||
alignment: u64,
|
||||
bytes: &[u8],
|
||||
relocs: &[MachReloc],
|
||||
) -> ModuleResult<ModuleCompiledFunction> {
|
||||
) -> ModuleResult<()> {
|
||||
info!("defining function {} with bytes", func_id);
|
||||
let total_size: u32 = match bytes.len().try_into() {
|
||||
Ok(total_size) => total_size,
|
||||
_ => Err(CodegenError::CodeTooLarge)?,
|
||||
};
|
||||
|
||||
let decl = self.declarations.get_function_decl(func_id);
|
||||
if !decl.linkage.is_definable() {
|
||||
return Err(ModuleError::InvalidImportDefinition(decl.name.clone()));
|
||||
return Err(ModuleError::InvalidImportDefinition(
|
||||
decl.linkage_name(func_id).into_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
let &mut (symbol, ref mut defined) = self.functions[func_id].as_mut().unwrap();
|
||||
if *defined {
|
||||
return Err(ModuleError::DuplicateDefinition(decl.name.clone()));
|
||||
return Err(ModuleError::DuplicateDefinition(
|
||||
decl.linkage_name(func_id).into_owned(),
|
||||
));
|
||||
}
|
||||
*defined = true;
|
||||
|
||||
@@ -391,18 +380,22 @@ impl Module for ObjectModule {
|
||||
});
|
||||
}
|
||||
|
||||
Ok(ModuleCompiledFunction { size: total_size })
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {
|
||||
let decl = self.declarations.get_data_decl(data_id);
|
||||
if !decl.linkage.is_definable() {
|
||||
return Err(ModuleError::InvalidImportDefinition(decl.name.clone()));
|
||||
return Err(ModuleError::InvalidImportDefinition(
|
||||
decl.linkage_name(data_id).into_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
let &mut (symbol, ref mut defined) = self.data_objects[data_id].as_mut().unwrap();
|
||||
if *defined {
|
||||
return Err(ModuleError::DuplicateDefinition(decl.name.clone()));
|
||||
return Err(ModuleError::DuplicateDefinition(
|
||||
decl.linkage_name(data_id).into_owned(),
|
||||
));
|
||||
}
|
||||
*defined = true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user