mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-14 14:45:40 +00:00
Remove previous LLVM parser code
This commit is contained in:
parent
87a94657d0
commit
9c0cbc9775
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,5 @@
|
|||||||
#![cfg_attr(nightly, feature(unwind_attributes))]
|
#![cfg_attr(nightly, feature(unwind_attributes))]
|
||||||
|
|
||||||
use wasmer_runtime_core::{
|
|
||||||
backend::{Compiler, CompilerConfig, Token},
|
|
||||||
cache::{Artifact, Error as CacheError},
|
|
||||||
error::CompileError,
|
|
||||||
module::ModuleInner,
|
|
||||||
};
|
|
||||||
use wasmparser::{self, WasmDecoder};
|
|
||||||
|
|
||||||
mod backend;
|
mod backend;
|
||||||
mod code;
|
mod code;
|
||||||
mod intrinsics;
|
mod intrinsics;
|
||||||
@ -16,119 +8,11 @@ mod read_info;
|
|||||||
mod state;
|
mod state;
|
||||||
mod trampolines;
|
mod trampolines;
|
||||||
|
|
||||||
pub struct LLVMOldCompiler {
|
|
||||||
_private: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LLVMOldCompiler {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self { _private: () }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen;
|
use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen;
|
||||||
|
|
||||||
pub type LLVMCompiler = SimpleStreamingCompilerGen<
|
pub type LLVMCompiler = SimpleStreamingCompilerGen<
|
||||||
code::LLVMModuleCodeGenerator,
|
code::LLVMModuleCodeGenerator,
|
||||||
code::LLVMFunctionCodeGenerator,
|
code::LLVMFunctionCodeGenerator,
|
||||||
backend::LLVMBackend,
|
backend::LLVMBackend,
|
||||||
code::CodegenError,
|
code::CodegenError,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
impl Compiler for LLVMOldCompiler {
|
|
||||||
fn compile(
|
|
||||||
&self,
|
|
||||||
wasm: &[u8],
|
|
||||||
compiler_config: CompilerConfig,
|
|
||||||
_: Token,
|
|
||||||
) -> Result<ModuleInner, CompileError> {
|
|
||||||
validate(wasm)?;
|
|
||||||
|
|
||||||
let (info, code_reader) = read_info::read_module(wasm, compiler_config).unwrap();
|
|
||||||
let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap();
|
|
||||||
|
|
||||||
let (backend, cache_gen) = backend::LLVMBackend::new(module, intrinsics);
|
|
||||||
|
|
||||||
Ok(ModuleInner {
|
|
||||||
runnable_module: Box::new(backend),
|
|
||||||
cache_gen: Box::new(cache_gen),
|
|
||||||
|
|
||||||
info,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn from_cache(&self, artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
|
||||||
let (info, _, memory) = artifact.consume();
|
|
||||||
let (backend, cache_gen) =
|
|
||||||
backend::LLVMBackend::from_buffer(memory).map_err(CacheError::DeserializeError)?;
|
|
||||||
|
|
||||||
Ok(ModuleInner {
|
|
||||||
runnable_module: Box::new(backend),
|
|
||||||
cache_gen: Box::new(cache_gen),
|
|
||||||
|
|
||||||
info,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate(bytes: &[u8]) -> Result<(), CompileError> {
|
|
||||||
let mut parser = wasmparser::ValidatingParser::new(
|
|
||||||
bytes,
|
|
||||||
Some(wasmparser::ValidatingParserConfig {
|
|
||||||
operator_config: wasmparser::OperatorValidatorConfig {
|
|
||||||
enable_threads: false,
|
|
||||||
enable_reference_types: false,
|
|
||||||
enable_simd: false,
|
|
||||||
enable_bulk_memory: false,
|
|
||||||
},
|
|
||||||
mutable_global_imports: false,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let state = parser.read();
|
|
||||||
match *state {
|
|
||||||
wasmparser::ParserState::EndWasm => break Ok(()),
|
|
||||||
wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError {
|
|
||||||
msg: err.message.to_string(),
|
|
||||||
})?,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_read_module() {
|
|
||||||
use std::mem::transmute;
|
|
||||||
use wabt::wat2wasm;
|
|
||||||
use wasmer_runtime_core::{
|
|
||||||
backend::RunnableModule, structures::TypedIndex, types::LocalFuncIndex, vm,
|
|
||||||
};
|
|
||||||
// let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8];
|
|
||||||
let wat = r#"
|
|
||||||
(module
|
|
||||||
(type $t0 (func (param i32) (result i32)))
|
|
||||||
(type $t1 (func (result i32)))
|
|
||||||
(memory 1)
|
|
||||||
(global $g0 (mut i32) (i32.const 0))
|
|
||||||
(func $foo (type $t0) (param i32) (result i32)
|
|
||||||
get_local 0
|
|
||||||
))
|
|
||||||
"#;
|
|
||||||
let wasm = wat2wasm(wat).unwrap();
|
|
||||||
|
|
||||||
let (info, code_reader) = read_info::read_module(&wasm, Default::default()).unwrap();
|
|
||||||
|
|
||||||
let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap();
|
|
||||||
|
|
||||||
let (backend, _) = backend::LLVMBackend::new(module, intrinsics);
|
|
||||||
|
|
||||||
let func_ptr = backend.get_func(&info, LocalFuncIndex::new(0)).unwrap();
|
|
||||||
|
|
||||||
println!("func_ptr: {:p}", func_ptr.as_ptr());
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let func: unsafe extern "C" fn(*mut vm::Ctx, i32) -> i32 = transmute(func_ptr);
|
|
||||||
let result = func(0 as _, 42);
|
|
||||||
println!("result: {}", result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,289 +1,5 @@
|
|||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::types::Type;
|
||||||
backend::{Backend, CompilerConfig},
|
use wasmparser::{BinaryReaderError, Type as WpType};
|
||||||
module::{
|
|
||||||
DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder,
|
|
||||||
TableInitializer,
|
|
||||||
},
|
|
||||||
structures::{Map, TypedIndex},
|
|
||||||
types::{
|
|
||||||
ElementType, FuncIndex, FuncSig, GlobalDescriptor, GlobalIndex, GlobalInit,
|
|
||||||
ImportedGlobalIndex, Initializer, MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor,
|
|
||||||
TableIndex, Type, Value,
|
|
||||||
},
|
|
||||||
units::Pages,
|
|
||||||
};
|
|
||||||
use wasmparser::{
|
|
||||||
BinaryReaderError, CodeSectionReader, Data, DataKind, Element, ElementKind, Export,
|
|
||||||
ExternalKind, FuncType, Import, ImportSectionEntryType, InitExpr, ModuleReader, Operator,
|
|
||||||
SectionCode, Type as WpType,
|
|
||||||
};
|
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
|
||||||
|
|
||||||
pub fn read_module(
|
|
||||||
wasm: &[u8],
|
|
||||||
compiler_config: CompilerConfig,
|
|
||||||
) -> Result<(ModuleInfo, CodeSectionReader), BinaryReaderError> {
|
|
||||||
let mut info = ModuleInfo {
|
|
||||||
memories: Map::new(),
|
|
||||||
globals: Map::new(),
|
|
||||||
tables: Map::new(),
|
|
||||||
|
|
||||||
imported_functions: Map::new(),
|
|
||||||
imported_memories: Map::new(),
|
|
||||||
imported_tables: Map::new(),
|
|
||||||
imported_globals: Map::new(),
|
|
||||||
|
|
||||||
exports: Default::default(),
|
|
||||||
|
|
||||||
data_initializers: Vec::new(),
|
|
||||||
elem_initializers: Vec::new(),
|
|
||||||
|
|
||||||
start_func: None,
|
|
||||||
|
|
||||||
func_assoc: Map::new(),
|
|
||||||
signatures: Map::new(),
|
|
||||||
backend: Backend::LLVM,
|
|
||||||
|
|
||||||
namespace_table: StringTable::new(),
|
|
||||||
name_table: StringTable::new(),
|
|
||||||
|
|
||||||
em_symbol_map: compiler_config.symbol_map.clone(),
|
|
||||||
|
|
||||||
custom_sections: HashMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut reader = ModuleReader::new(wasm)?;
|
|
||||||
let mut code_reader = None;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if reader.eof() {
|
|
||||||
return Ok((info, code_reader.unwrap()));
|
|
||||||
}
|
|
||||||
|
|
||||||
let section = reader.read()?;
|
|
||||||
|
|
||||||
match section.code {
|
|
||||||
SectionCode::Type => {
|
|
||||||
let type_reader = section.get_type_section_reader()?;
|
|
||||||
|
|
||||||
for ty in type_reader {
|
|
||||||
let ty = ty?;
|
|
||||||
info.signatures.push(func_type_to_func_sig(ty)?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Import => {
|
|
||||||
let import_reader = section.get_import_section_reader()?;
|
|
||||||
let mut namespace_builder = StringTableBuilder::new();
|
|
||||||
let mut name_builder = StringTableBuilder::new();
|
|
||||||
|
|
||||||
for import in import_reader {
|
|
||||||
let Import { module, field, ty } = import?;
|
|
||||||
|
|
||||||
let namespace_index = namespace_builder.register(module);
|
|
||||||
let name_index = name_builder.register(field);
|
|
||||||
let import_name = ImportName {
|
|
||||||
namespace_index,
|
|
||||||
name_index,
|
|
||||||
};
|
|
||||||
|
|
||||||
match ty {
|
|
||||||
ImportSectionEntryType::Function(sigindex) => {
|
|
||||||
let sigindex = SigIndex::new(sigindex as usize);
|
|
||||||
info.imported_functions.push(import_name);
|
|
||||||
info.func_assoc.push(sigindex);
|
|
||||||
}
|
|
||||||
ImportSectionEntryType::Table(table_ty) => {
|
|
||||||
assert_eq!(table_ty.element_type, WpType::AnyFunc);
|
|
||||||
let table_desc = TableDescriptor {
|
|
||||||
element: ElementType::Anyfunc,
|
|
||||||
minimum: table_ty.limits.initial,
|
|
||||||
maximum: table_ty.limits.maximum,
|
|
||||||
};
|
|
||||||
|
|
||||||
info.imported_tables.push((import_name, table_desc));
|
|
||||||
}
|
|
||||||
ImportSectionEntryType::Memory(memory_ty) => {
|
|
||||||
let mem_desc = MemoryDescriptor {
|
|
||||||
minimum: Pages(memory_ty.limits.initial),
|
|
||||||
maximum: memory_ty.limits.maximum.map(|max| Pages(max)),
|
|
||||||
shared: memory_ty.shared,
|
|
||||||
};
|
|
||||||
info.imported_memories.push((import_name, mem_desc));
|
|
||||||
}
|
|
||||||
ImportSectionEntryType::Global(global_ty) => {
|
|
||||||
let global_desc = GlobalDescriptor {
|
|
||||||
mutable: global_ty.mutable,
|
|
||||||
ty: type_to_type(global_ty.content_type)?,
|
|
||||||
};
|
|
||||||
info.imported_globals.push((import_name, global_desc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
info.namespace_table = namespace_builder.finish();
|
|
||||||
info.name_table = name_builder.finish();
|
|
||||||
}
|
|
||||||
SectionCode::Function => {
|
|
||||||
let func_decl_reader = section.get_function_section_reader()?;
|
|
||||||
|
|
||||||
for sigindex in func_decl_reader {
|
|
||||||
let sigindex = sigindex?;
|
|
||||||
|
|
||||||
let sigindex = SigIndex::new(sigindex as usize);
|
|
||||||
info.func_assoc.push(sigindex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Table => {
|
|
||||||
let table_decl_reader = section.get_table_section_reader()?;
|
|
||||||
|
|
||||||
for table_ty in table_decl_reader {
|
|
||||||
let table_ty = table_ty?;
|
|
||||||
|
|
||||||
let table_desc = TableDescriptor {
|
|
||||||
element: ElementType::Anyfunc,
|
|
||||||
minimum: table_ty.limits.initial,
|
|
||||||
maximum: table_ty.limits.maximum,
|
|
||||||
};
|
|
||||||
|
|
||||||
info.tables.push(table_desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Memory => {
|
|
||||||
let mem_decl_reader = section.get_memory_section_reader()?;
|
|
||||||
|
|
||||||
for memory_ty in mem_decl_reader {
|
|
||||||
let memory_ty = memory_ty?;
|
|
||||||
|
|
||||||
let mem_desc = MemoryDescriptor {
|
|
||||||
minimum: Pages(memory_ty.limits.initial),
|
|
||||||
maximum: memory_ty.limits.maximum.map(|max| Pages(max)),
|
|
||||||
shared: memory_ty.shared,
|
|
||||||
};
|
|
||||||
|
|
||||||
info.memories.push(mem_desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Global => {
|
|
||||||
let global_decl_reader = section.get_global_section_reader()?;
|
|
||||||
|
|
||||||
for global in global_decl_reader {
|
|
||||||
let global = global?;
|
|
||||||
|
|
||||||
let desc = GlobalDescriptor {
|
|
||||||
mutable: global.ty.mutable,
|
|
||||||
ty: type_to_type(global.ty.content_type)?,
|
|
||||||
};
|
|
||||||
|
|
||||||
let global_init = GlobalInit {
|
|
||||||
desc,
|
|
||||||
init: eval_init_expr(&global.init_expr)?,
|
|
||||||
};
|
|
||||||
|
|
||||||
info.globals.push(global_init);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Export => {
|
|
||||||
let export_reader = section.get_export_section_reader()?;
|
|
||||||
|
|
||||||
for export in export_reader {
|
|
||||||
let Export { field, kind, index } = export?;
|
|
||||||
|
|
||||||
let export_index = match kind {
|
|
||||||
ExternalKind::Function => ExportIndex::Func(FuncIndex::new(index as usize)),
|
|
||||||
ExternalKind::Table => ExportIndex::Table(TableIndex::new(index as usize)),
|
|
||||||
ExternalKind::Memory => {
|
|
||||||
ExportIndex::Memory(MemoryIndex::new(index as usize))
|
|
||||||
}
|
|
||||||
ExternalKind::Global => {
|
|
||||||
ExportIndex::Global(GlobalIndex::new(index as usize))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
info.exports.insert(field.to_string(), export_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Start => {
|
|
||||||
let start_index = section.get_start_section_content()?;
|
|
||||||
|
|
||||||
info.start_func = Some(FuncIndex::new(start_index as usize));
|
|
||||||
}
|
|
||||||
SectionCode::Element => {
|
|
||||||
let element_reader = section.get_element_section_reader()?;
|
|
||||||
|
|
||||||
for element in element_reader {
|
|
||||||
let Element { kind, items } = element?;
|
|
||||||
|
|
||||||
match kind {
|
|
||||||
ElementKind::Active {
|
|
||||||
table_index,
|
|
||||||
init_expr,
|
|
||||||
} => {
|
|
||||||
let table_index = TableIndex::new(table_index as usize);
|
|
||||||
let base = eval_init_expr(&init_expr)?;
|
|
||||||
let items_reader = items.get_items_reader()?;
|
|
||||||
|
|
||||||
let elements: Vec<_> = items_reader
|
|
||||||
.into_iter()
|
|
||||||
.map(|res| res.map(|index| FuncIndex::new(index as usize)))
|
|
||||||
.collect::<Result<_, _>>()?;
|
|
||||||
|
|
||||||
let table_init = TableInitializer {
|
|
||||||
table_index,
|
|
||||||
base,
|
|
||||||
elements,
|
|
||||||
};
|
|
||||||
|
|
||||||
info.elem_initializers.push(table_init);
|
|
||||||
}
|
|
||||||
ElementKind::Passive(_ty) => {
|
|
||||||
return Err(BinaryReaderError {
|
|
||||||
message: "passive tables are not yet supported",
|
|
||||||
offset: -1isize as usize,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Code => {
|
|
||||||
code_reader = Some(section.get_code_section_reader()?);
|
|
||||||
}
|
|
||||||
SectionCode::Data => {
|
|
||||||
let data_reader = section.get_data_section_reader()?;
|
|
||||||
|
|
||||||
for data in data_reader {
|
|
||||||
let Data { kind, data } = data?;
|
|
||||||
|
|
||||||
match kind {
|
|
||||||
DataKind::Active {
|
|
||||||
memory_index,
|
|
||||||
init_expr,
|
|
||||||
} => {
|
|
||||||
let memory_index = MemoryIndex::new(memory_index as usize);
|
|
||||||
let base = eval_init_expr(&init_expr)?;
|
|
||||||
|
|
||||||
let data_init = DataInitializer {
|
|
||||||
memory_index,
|
|
||||||
base,
|
|
||||||
data: data.to_vec(),
|
|
||||||
};
|
|
||||||
|
|
||||||
info.data_initializers.push(data_init);
|
|
||||||
}
|
|
||||||
DataKind::Passive => {
|
|
||||||
return Err(BinaryReaderError {
|
|
||||||
message: "passive memories are not yet supported",
|
|
||||||
offset: -1isize as usize,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::DataCount => {}
|
|
||||||
SectionCode::Custom { .. } => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_to_type(ty: WpType) -> Result<Type, BinaryReaderError> {
|
pub fn type_to_type(ty: WpType) -> Result<Type, BinaryReaderError> {
|
||||||
Ok(match ty {
|
Ok(match ty {
|
||||||
@ -305,46 +21,3 @@ pub fn type_to_type(ty: WpType) -> Result<Type, BinaryReaderError> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func_type_to_func_sig(func_ty: FuncType) -> Result<FuncSig, BinaryReaderError> {
|
|
||||||
assert_eq!(func_ty.form, WpType::Func);
|
|
||||||
|
|
||||||
Ok(FuncSig::new(
|
|
||||||
func_ty
|
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.map(type_to_type)
|
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
|
||||||
func_ty
|
|
||||||
.returns
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.map(type_to_type)
|
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eval_init_expr(expr: &InitExpr) -> Result<Initializer, BinaryReaderError> {
|
|
||||||
let mut reader = expr.get_operators_reader();
|
|
||||||
let (op, offset) = reader.read_with_offset()?;
|
|
||||||
Ok(match op {
|
|
||||||
Operator::GetGlobal { global_index } => {
|
|
||||||
Initializer::GetGlobal(ImportedGlobalIndex::new(global_index as usize))
|
|
||||||
}
|
|
||||||
Operator::I32Const { value } => Initializer::Const(Value::I32(value)),
|
|
||||||
Operator::I64Const { value } => Initializer::Const(Value::I64(value)),
|
|
||||||
Operator::F32Const { value } => {
|
|
||||||
Initializer::Const(Value::F32(f32::from_bits(value.bits())))
|
|
||||||
}
|
|
||||||
Operator::F64Const { value } => {
|
|
||||||
Initializer::Const(Value::F64(f64::from_bits(value.bits())))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(BinaryReaderError {
|
|
||||||
message: "init expr evaluation failed: unsupported opcode",
|
|
||||||
offset,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user