mirror of
https://github.com/mii443/wasmer.git
synced 2025-08-30 20:29:31 +00:00
Refactor cranelift a bit for code clarity
This commit is contained in:
@ -3,16 +3,17 @@
|
||||
use crate::address_map::get_function_address_map;
|
||||
use crate::config::CraneliftConfig;
|
||||
use crate::func_environ::{get_func_name, FuncEnvironment};
|
||||
use crate::sink::{RelocSink, TrapSink};
|
||||
use crate::trampoline::{make_wasm_trampoline, FunctionBuilderContext};
|
||||
use crate::translator::{
|
||||
irlibcall_to_libcall, irreloc_to_relocationkind, signature_to_cranelift_ir, FuncTranslator,
|
||||
compiled_function_unwind_info, irlibcall_to_libcall, irreloc_to_relocationkind,
|
||||
signature_to_cranelift_ir, transform_jump_table, FuncTranslator,
|
||||
};
|
||||
use crate::unwind::compiled_function_unwind_info;
|
||||
use cranelift_codegen::ir::{self, ExternalName};
|
||||
use cranelift_codegen::print_errors::pretty_error;
|
||||
use cranelift_codegen::{binemit, isa, Context};
|
||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||
use wasm_common::entity::{EntityRef, PrimaryMap, SecondaryMap};
|
||||
use wasm_common::entity::{EntityRef, PrimaryMap};
|
||||
use wasm_common::{
|
||||
Features, FunctionIndex, FunctionType, LocalFunctionIndex, MemoryIndex, SignatureIndex,
|
||||
TableIndex,
|
||||
@ -20,142 +21,13 @@ use wasm_common::{
|
||||
use wasmer_compiler::CompileError;
|
||||
use wasmer_compiler::{
|
||||
Compilation, CompiledFunction, CompiledFunctionFrameInfo, Compiler, FunctionBody,
|
||||
FunctionBodyData, JumpTable, SourceLoc, TrapInformation,
|
||||
FunctionBodyData, SourceLoc, TrapInformation,
|
||||
};
|
||||
use wasmer_compiler::{CompilerConfig, ModuleTranslationState, Target};
|
||||
use wasmer_compiler::{Relocation, RelocationTarget};
|
||||
use wasmer_runtime::TrapCode;
|
||||
use wasmer_runtime::{MemoryPlan, Module, TablePlan};
|
||||
|
||||
/// Implementation of a relocation sink that just saves all the information for later
|
||||
pub struct RelocSink<'a> {
|
||||
module: &'a Module,
|
||||
|
||||
/// Current function index.
|
||||
local_func_index: LocalFunctionIndex,
|
||||
|
||||
/// Relocations recorded for the function.
|
||||
pub func_relocs: Vec<Relocation>,
|
||||
}
|
||||
|
||||
impl<'a> binemit::RelocSink for RelocSink<'a> {
|
||||
fn reloc_block(
|
||||
&mut self,
|
||||
_offset: binemit::CodeOffset,
|
||||
_reloc: binemit::Reloc,
|
||||
_block_offset: binemit::CodeOffset,
|
||||
) {
|
||||
// This should use the `offsets` field of `ir::Function`.
|
||||
panic!("block headers not yet implemented");
|
||||
}
|
||||
fn reloc_external(
|
||||
&mut self,
|
||||
offset: binemit::CodeOffset,
|
||||
reloc: binemit::Reloc,
|
||||
name: &ExternalName,
|
||||
addend: binemit::Addend,
|
||||
) {
|
||||
let reloc_target = if let ExternalName::User { namespace, index } = *name {
|
||||
debug_assert_eq!(namespace, 0);
|
||||
RelocationTarget::LocalFunc(
|
||||
self.module
|
||||
.local_func_index(FunctionIndex::from_u32(index))
|
||||
.expect("The provided function should be local"),
|
||||
)
|
||||
} else if let ExternalName::LibCall(libcall) = *name {
|
||||
RelocationTarget::LibCall(irlibcall_to_libcall(libcall))
|
||||
} else {
|
||||
panic!("unrecognized external name")
|
||||
};
|
||||
self.func_relocs.push(Relocation {
|
||||
kind: irreloc_to_relocationkind(reloc),
|
||||
reloc_target,
|
||||
offset,
|
||||
addend,
|
||||
});
|
||||
}
|
||||
|
||||
fn reloc_constant(
|
||||
&mut self,
|
||||
_code_offset: binemit::CodeOffset,
|
||||
_reloc: binemit::Reloc,
|
||||
_constant_offset: ir::ConstantOffset,
|
||||
) {
|
||||
// Do nothing for now: cranelift emits constant data after the function code and also emits
|
||||
// function code with correct relative offsets to the constant data.
|
||||
}
|
||||
|
||||
fn reloc_jt(&mut self, offset: binemit::CodeOffset, reloc: binemit::Reloc, jt: ir::JumpTable) {
|
||||
self.func_relocs.push(Relocation {
|
||||
kind: irreloc_to_relocationkind(reloc),
|
||||
reloc_target: RelocationTarget::JumpTable(
|
||||
self.local_func_index,
|
||||
JumpTable::new(jt.index()),
|
||||
),
|
||||
offset,
|
||||
addend: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RelocSink<'a> {
|
||||
/// Return a new `RelocSink` instance.
|
||||
pub fn new(module: &'a Module, func_index: FunctionIndex) -> Self {
|
||||
let local_func_index = module
|
||||
.local_func_index(func_index)
|
||||
.expect("The provided function should be local");
|
||||
Self {
|
||||
module,
|
||||
local_func_index,
|
||||
func_relocs: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TrapSink {
|
||||
pub traps: Vec<TrapInformation>,
|
||||
}
|
||||
|
||||
impl TrapSink {
|
||||
fn new() -> Self {
|
||||
Self { traps: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
impl binemit::TrapSink for TrapSink {
|
||||
fn trap(
|
||||
&mut self,
|
||||
code_offset: binemit::CodeOffset,
|
||||
source_loc: ir::SourceLoc,
|
||||
trap_code: ir::TrapCode,
|
||||
) {
|
||||
self.traps.push(TrapInformation {
|
||||
code_offset,
|
||||
source_loc: SourceLoc::new(source_loc.bits()),
|
||||
// TODO: Translate properly environment Trapcode into cranelift IR
|
||||
trap_code: translate_ir_trapcode(trap_code),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Translates the Cranelift IR TrapCode into generic Trap Code
|
||||
fn translate_ir_trapcode(trap: ir::TrapCode) -> TrapCode {
|
||||
match trap {
|
||||
ir::TrapCode::StackOverflow => TrapCode::StackOverflow,
|
||||
ir::TrapCode::HeapOutOfBounds => TrapCode::HeapAccessOutOfBounds,
|
||||
ir::TrapCode::TableOutOfBounds => TrapCode::TableAccessOutOfBounds,
|
||||
ir::TrapCode::OutOfBounds => TrapCode::OutOfBounds,
|
||||
ir::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull,
|
||||
ir::TrapCode::BadSignature => TrapCode::BadSignature,
|
||||
ir::TrapCode::IntegerOverflow => TrapCode::IntegerOverflow,
|
||||
ir::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero,
|
||||
ir::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger,
|
||||
ir::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached,
|
||||
ir::TrapCode::Interrupt => TrapCode::Interrupt,
|
||||
ir::TrapCode::User(user_code) => TrapCode::User(user_code),
|
||||
}
|
||||
}
|
||||
|
||||
/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR,
|
||||
/// optimizing it and then translating to assembly.
|
||||
pub struct CraneliftCompiler {
|
||||
@ -299,16 +171,3 @@ impl Compiler for CraneliftCompiler {
|
||||
.collect::<Result<Vec<_>, CompileError>>()
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms Cranelift JumpTable's into runtime JumpTables
|
||||
pub fn transform_jump_table(
|
||||
jt_offsets: SecondaryMap<ir::JumpTable, u32>,
|
||||
) -> SecondaryMap<JumpTable, u32> {
|
||||
let mut func_jt_offsets = SecondaryMap::with_capacity(jt_offsets.capacity());
|
||||
|
||||
for (key, value) in jt_offsets.iter() {
|
||||
let new_key = JumpTable::new(key.index());
|
||||
func_jt_offsets[new_key] = *value;
|
||||
}
|
||||
func_jt_offsets
|
||||
}
|
||||
|
Reference in New Issue
Block a user