From 86e934a7557ef98975f77a9ca5f56b7a53cfd6a1 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 3 Sep 2020 17:45:27 -0700 Subject: [PATCH] Move header file generation logic WIP, still need to get the length of the metadat object, but otherwise everything should be working. --- Cargo.lock | 1 + lib/cli/Cargo.toml | 1 + lib/cli/src/commands/compile.rs | 55 ++- lib/cli/src/header_file_generation/mod.rs | 456 ++++++++++++++++++++++ lib/cli/src/lib.rs | 1 + lib/engine-jit/src/artifact.rs | 6 +- lib/engine-native/src/artifact.rs | 4 + lib/engine-object-file/src/artifact.rs | 172 +------- lib/engine-object-file/src/header.rs | 234 ----------- lib/engine-object-file/src/lib.rs | 1 - lib/engine/src/artifact.rs | 42 +- 11 files changed, 502 insertions(+), 471 deletions(-) create mode 100644 lib/cli/src/header_file_generation/mod.rs delete mode 100644 lib/engine-object-file/src/header.rs diff --git a/Cargo.lock b/Cargo.lock index d57b83d61..9601cfec7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2229,6 +2229,7 @@ dependencies = [ "wasmer-engine-native", "wasmer-engine-object-file", "wasmer-types", + "wasmer-vm", "wasmer-wasi", "wasmer-wasi-experimental-io-devices", "wasmer-wast", diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index c2543bae1..dd1eae600 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -35,6 +35,7 @@ wasmer-engine-object-file = { version = "1.0.0-alpha01.0", path = "../engine-obj wasmer-wasi = { version = "1.0.0-alpha01.0", path = "../wasi", optional = true } wasmer-wasi-experimental-io-devices = { version = "1.0.0-alpha01.0", path = "../wasi-experimental-io-devices", optional = true } wasmer-wast = { version = "1.0.0-alpha01.0", path = "../../tests/lib/wast", optional = true } +wasmer-vm = { version = "1.0.0-alpha01.0", path = "../vm" } wasmer-cache = { version = "1.0.0-alpha01.0", path = "../cache", optional = true } wasmer-types = { version = "1.0.0-alpha01.0", path = "../wasmer-types" } atty = "0.2" diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index a407eebf2..6cace1e96 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -106,37 +106,34 @@ impl Compile { #[cfg(feature = "object-file")] if engine_type == EngineType::ObjectFile { - use wasmer_engine_object_file::ObjectFileArtifact; + let symbol_registry = module.artifact().symbol_registry(); + let module_info = module.info(); + let header_file_src = + crate::header_file_generation::generate_header_file(module_info, symbol_registry); - if let Some(obj_file) = module.artifact().downcast_ref::() { - let header_file_src = obj_file.generate_header_file(); - let header_path = self.header_path.as_ref().cloned().unwrap_or_else(|| { - let mut hp = PathBuf::from( - self.path - .file_stem() - .map(|fs| fs.to_string_lossy().to_string()) - .unwrap_or_else(|| "wasm_out".to_string()), - ); - hp.set_extension("h"); - hp - }); - // for C code - let mut header = std::fs::OpenOptions::new() - .create(true) - .truncate(true) - .write(true) - .open(&header_path)?; - - use std::io::Write; - header.write(header_file_src.as_bytes())?; - eprintln!( - "✔ Header file generated successfully at `{}`.", - header_path.display(), + let header_path = self.header_path.as_ref().cloned().unwrap_or_else(|| { + let mut hp = PathBuf::from( + self.path + .file_stem() + .map(|fs| fs.to_string_lossy().to_string()) + .unwrap_or_else(|| "wasm_out".to_string()), ); - } else { - // TODO: handle error - panic!("Downcast failed!") - } + hp.set_extension("h"); + hp + }); + // for C code + let mut header = std::fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(&header_path)?; + + use std::io::Write; + header.write(header_file_src.as_bytes())?; + eprintln!( + "✔ Header file generated successfully at `{}`.", + header_path.display(), + ); } Ok(()) } diff --git a/lib/cli/src/header_file_generation/mod.rs b/lib/cli/src/header_file_generation/mod.rs new file mode 100644 index 000000000..14870cf70 --- /dev/null +++ b/lib/cli/src/header_file_generation/mod.rs @@ -0,0 +1,456 @@ +//! A convenient little abstraction for building up C expressions and generating +//! simple C code. + +/// A Type in the C language. +#[derive(Debug, Clone)] +pub enum CType { + /// C `void` type. + Void, + /// A pointer to some other type. + PointerTo { + /// Whether the pointer is `const`. + is_const: bool, + /// The type that the pointer points to. + inner: Box, + }, + /// C 8 bit unsigned integer type. + U8, + /// C 16 bit unsigned integer type. + U16, + /// C 32 bit unsigned integer type. + U32, + /// C 64 bit unsigned integer type. + U64, + /// C pointer sized unsigned integer type. + USize, + /// C 8 bit signed integer type. + I8, + /// C 16 bit signed integer type. + I16, + /// C 32 bit signed integer type. + I32, + /// C 64 bit signed integer type. + I64, + /// C pointer sized signed integer type. + ISize, + /// A function or function pointer. + Function { + /// The arguments the function takes. + arguments: Vec, + /// The return value if it has one + /// + /// None is equivalent to Some(Box(Ctype::Void)). + return_value: Option>, + }, +} + +impl CType { + /// Convenience function to get a mutable void pointer type. + pub fn void_ptr() -> Self { + CType::PointerTo { + is_const: false, + inner: Box::new(CType::Void), + } + } + + /// Convenience function to get a const void pointer type. + #[allow(dead_code)] + pub fn const_void_ptr() -> Self { + CType::PointerTo { + is_const: false, + inner: Box::new(CType::Void), + } + } + + /// Generate the C source code for a type into the given `String`. + fn generate_c(&self, w: &mut String) { + match &self { + Self::Void => { + w.push_str("void"); + } + Self::PointerTo { is_const, inner } => { + if *is_const { + w.push_str("const "); + } + inner.generate_c(w); + w.push_str("*"); + } + Self::U8 => { + w.push_str("unsigned char"); + } + Self::U16 => { + w.push_str("unsigned short"); + } + Self::U32 => { + w.push_str("unsigned int"); + } + Self::U64 => { + w.push_str("unsigned long long"); + } + Self::USize => { + w.push_str("unsigned size_t"); + } + Self::I8 => { + w.push_str("char"); + } + Self::I16 => { + w.push_str("short"); + } + Self::I32 => { + w.push_str("int"); + } + Self::I64 => { + w.push_str("long long"); + } + Self::ISize => { + w.push_str("size_t"); + } + Self::Function { + arguments, + return_value, + } => { + // function with no, name, assume it's a function pointer + let ret: CType = return_value + .as_ref() + .map(|i: &Box| (&**i).clone()) + .unwrap_or_default(); + ret.generate_c(w); + w.push(' '); + w.push_str("(*)"); + w.push('('); + if arguments.len() > 1 { + for arg in &arguments[..arguments.len() - 1] { + arg.generate_c(w); + w.push_str(", "); + } + arguments.last().unwrap().generate_c(w); + } else if arguments.len() == 1 { + arguments[0].generate_c(w); + } + w.push(')'); + } + } + } + + /// Generate the C source code for a type with a nameinto the given `String`. + fn generate_c_with_name(&self, name: &String, w: &mut String) { + match &self { + Self::PointerTo { .. } + | Self::Void + | Self::U8 + | Self::U16 + | Self::U32 + | Self::U64 + | Self::USize + | Self::I8 + | Self::I16 + | Self::I32 + | Self::I64 + | Self::ISize => { + self.generate_c(w); + w.push(' '); + w.push_str(name); + } + Self::Function { + arguments, + return_value, + } => { + let ret: CType = return_value + .as_ref() + .map(|i: &Box| (&**i).clone()) + .unwrap_or_default(); + ret.generate_c(w); + w.push(' '); + w.push_str(&name); + w.push('('); + if arguments.len() > 1 { + for arg in &arguments[..arguments.len() - 1] { + arg.generate_c(w); + w.push_str(", "); + } + arguments.last().unwrap().generate_c(w); + } else if arguments.len() == 1 { + arguments[0].generate_c(w); + } + w.push(')'); + } + } + } +} + +impl Default for CType { + fn default() -> CType { + CType::Void + } +} + +/// A statement in the C programming language. This may not be exact to what an +/// AST would look like or what the C standard says about the C language, it's +/// simply a structed way to organize data for generating C code. +#[derive(Debug, Clone)] +pub enum CStatement { + /// A declaration of some kind. + Declaration { + /// The name of the thing being declared. + name: String, + /// Whether the thing being declared is an array. + // TODO: probably make this part of CType + array: bool, + /// Whether the thing being declared is `extern`. + is_extern: bool, + /// Whether the thing being declared is `const`. + is_const: bool, + /// The type of the thing being declared. + ctype: CType, + /// The definition of the thing being declared. + /// + /// This is useful for initializing constant arrays, for example. + definition: Option>, + }, + /// A literal array of CStatements. + LiteralArray { + /// The contents of the array. + items: Vec, + }, + + /// A literal constant value, passed through directly as a string. + LiteralConstant { + /// The raw value acting as a constant. + value: String, + }, +} + +impl CStatement { + /// Generate C source code for the given CStatement. + fn generate_c(&self, w: &mut String) { + match &self { + Self::Declaration { + name, + array, + is_extern, + is_const, + ctype, + definition, + } => { + if *is_const { + w.push_str("const "); + } + if *is_extern { + w.push_str("extern "); + } + ctype.generate_c_with_name(name, w); + // TODO: array should be part of the type + if *array { + w.push_str("[]"); + } + if let Some(def) = definition { + w.push_str(" = "); + def.generate_c(w); + } + w.push(';'); + w.push('\n'); + } + Self::LiteralArray { items } => { + w.push('{'); + if !items.is_empty() { + w.push('\n'); + } + for item in items { + w.push('\t'); + item.generate_c(w); + w.push(','); + w.push('\n'); + } + w.push('}'); + } + Self::LiteralConstant { value } => { + w.push_str(&value); + } + } + } +} + +/// Generate C source code from some `CStatements` into a String. +// TODO: add config section +pub fn generate_c(statements: &[CStatement]) -> String { + let mut out = String::new(); + for statement in statements { + statement.generate_c(&mut out); + } + out +} + +// TODO: split the bottom part into its own file + +use wasmer_compiler::{Symbol, SymbolRegistry}; +use wasmer_vm::ModuleInfo; + +/// Generate the header file that goes with the generated object file. +pub fn generate_header_file( + module_info: &ModuleInfo, + symbol_registry: &dyn SymbolRegistry, +) -> String { + let mut c_statements = vec![]; + c_statements.push(CStatement::Declaration { + name: "module_bytes_len".to_string(), + array: false, + is_extern: false, + is_const: true, + ctype: CType::U32, + definition: Some(Box::new(CStatement::LiteralConstant { + value: "0".to_string(), //todo!("get the metadata length from somewhere"), //format!("{}", self.metadata_length), + })), + }); + c_statements.push(CStatement::Declaration { + name: "WASMER_METADATA".to_string(), + array: true, + is_extern: true, + is_const: true, + ctype: CType::U8, + definition: None, + }); + for (function_local_index, _sig_index) in + module_info + .functions + .iter() + .filter_map(|(f_index, sig_index)| { + Some((module_info.local_func_index(f_index)?, sig_index)) + }) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signature here too + c_statements.push(CStatement::Declaration { + name: function_name.clone(), + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::Void], + return_value: None, + }, + definition: None, + }); + } + + // function pointer array + { + let mut function_pointer_array_statements = vec![]; + for (function_local_index, _sig_index) in + module_info + .functions + .iter() + .filter_map(|(f_index, sig_index)| { + Some((module_info.local_func_index(f_index)?, sig_index)) + }) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signature here too + + function_pointer_array_statements.push(CStatement::LiteralConstant { + value: function_name.clone(), + }); + } + + c_statements.push(CStatement::Declaration { + name: "function_pointers".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: function_pointer_array_statements, + })), + }); + } + + for (sig_index, _func_type) in module_info.signatures.iter() { + let function_name = + symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + + c_statements.push(CStatement::Declaration { + name: function_name.clone(), + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + }); + } + + // function trampolines + { + let mut function_trampoline_statements = vec![]; + for (sig_index, _vm_shared_index) in module_info.signatures.iter() { + let function_name = + symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + function_trampoline_statements.push(CStatement::LiteralConstant { + value: function_name, + }); + } + + c_statements.push(CStatement::Declaration { + name: "function_trampolines".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: function_trampoline_statements, + })), + }); + } + + for func_index in module_info + .functions + .keys() + .take(module_info.num_imported_functions) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + // TODO: figure out the signature here + c_statements.push(CStatement::Declaration { + name: function_name, + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + }); + } + + // dynamic function trampoline pointer array + { + let mut dynamic_function_trampoline_statements = vec![]; + for func_index in module_info + .functions + .keys() + .take(module_info.num_imported_functions) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + dynamic_function_trampoline_statements.push(CStatement::LiteralConstant { + value: function_name, + }); + } + c_statements.push(CStatement::Declaration { + name: "dynamic_function_trampoline_pointers".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: dynamic_function_trampoline_statements, + })), + }); + } + + generate_c(&c_statements) +} diff --git a/lib/cli/src/lib.rs b/lib/cli/src/lib.rs index ce0d42754..9a08d404a 100644 --- a/lib/cli/src/lib.rs +++ b/lib/cli/src/lib.rs @@ -20,6 +20,7 @@ pub mod commands; pub mod common; #[macro_use] pub mod error; +pub mod header_file_generation; #[cfg(feature = "debug")] pub mod logging; pub mod store; diff --git a/lib/engine-jit/src/artifact.rs b/lib/engine-jit/src/artifact.rs index 767b7f55a..3cfa34ec7 100644 --- a/lib/engine-jit/src/artifact.rs +++ b/lib/engine-jit/src/artifact.rs @@ -8,7 +8,7 @@ use crate::serialize::SerializableCompilation; use crate::serialize::SerializableModule; use crate::unwind::UnwindRegistry; use std::sync::{Arc, Mutex}; -use wasmer_compiler::{CompileError, Features, Triple}; +use wasmer_compiler::{CompileError, Features, SymbolRegistry, Triple}; #[cfg(feature = "compiler")] use wasmer_compiler::{CompileModuleInfo, ModuleEnvironment}; use wasmer_engine::{ @@ -303,4 +303,8 @@ impl Artifact for JITArtifact { serialized.extend(bytes); Ok(serialized) } + + fn symbol_registry(&self) -> &dyn SymbolRegistry { + unimplemented!("TODO: figure out why engine JIT doesn't have a SymbolRegistry") + } } diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index 237e6b2d7..1470e7684 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -598,4 +598,8 @@ impl Artifact for NativeArtifact { fn serialize(&self) -> Result, SerializeError> { Ok(std::fs::read(&self.sharedobject_path)?) } + + fn symbol_registry(&self) -> &dyn SymbolRegistry { + &self.metadata + } } diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index f78d67e0f..8cb4ca0d7 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -237,174 +237,6 @@ impl ObjectFileArtifact { Self::from_parts_crosscompiled(&mut *engine_inner, metadata, obj_bytes, metadata_length) } - /// Generate the header file that goes with the generated object file. - pub fn generate_header_file(&self) -> String { - use crate::header::*; - let mut c_statements = vec![]; - c_statements.push(CStatement::Declaration { - name: "module_bytes_len".to_string(), - array: false, - is_extern: false, - is_const: true, - ctype: CType::U32, - definition: Some(Box::new(CStatement::LiteralConstant { - value: format!("{}", self.metadata_length), - })), - }); - c_statements.push(CStatement::Declaration { - name: "WASMER_METADATA".to_string(), - array: true, - is_extern: true, - is_const: true, - ctype: CType::U8, - definition: None, - }); - for (function_local_index, _function_len) in self.metadata.function_body_lengths.iter() { - let function_name = self - .metadata - .symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signature here too - c_statements.push(CStatement::Declaration { - name: function_name.clone(), - array: false, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::Void], - return_value: None, - }, - definition: None, - }); - } - - // function pointer array - { - let mut function_pointer_array_statements = vec![]; - for (function_local_index, _function_len) in self.metadata.function_body_lengths.iter() - { - let function_name = self - .metadata - .symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signature here too - - function_pointer_array_statements.push(CStatement::LiteralConstant { - value: function_name.clone(), - }); - } - - c_statements.push(CStatement::Declaration { - name: "function_pointers".to_string(), - array: true, - is_extern: false, - is_const: true, - ctype: CType::void_ptr(), - definition: Some(Box::new(CStatement::LiteralArray { - items: function_pointer_array_statements, - })), - }); - } - - for (sig_index, _func_type) in self.metadata.compile_info.module.signatures.iter() { - let function_name = self - .metadata - .symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - - c_statements.push(CStatement::Declaration { - name: function_name.clone(), - array: false, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], - return_value: None, - }, - definition: None, - }); - } - - // function trampolines - { - let mut function_trampoline_statements = vec![]; - for (sig_index, _vm_shared_index) in self.metadata.compile_info.module.signatures.iter() - { - let function_name = self - .metadata - .symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - function_trampoline_statements.push(CStatement::LiteralConstant { - value: function_name, - }); - } - - c_statements.push(CStatement::Declaration { - name: "function_trampolines".to_string(), - array: true, - is_extern: false, - is_const: true, - ctype: CType::void_ptr(), - definition: Some(Box::new(CStatement::LiteralArray { - items: function_trampoline_statements, - })), - }); - } - - for func_index in self - .metadata - .compile_info - .module - .functions - .keys() - .take(self.metadata.compile_info.module.num_imported_functions) - { - let function_name = self - .metadata - .symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - // TODO: figure out the signature here - c_statements.push(CStatement::Declaration { - name: function_name, - array: false, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], - return_value: None, - }, - definition: None, - }); - } - - // dynamic function trampoline pointer array - { - let mut dynamic_function_trampoline_statements = vec![]; - for func_index in self - .metadata - .compile_info - .module - .functions - .keys() - .take(self.metadata.compile_info.module.num_imported_functions) - { - let function_name = self - .metadata - .symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - dynamic_function_trampoline_statements.push(CStatement::LiteralConstant { - value: function_name, - }); - } - c_statements.push(CStatement::Declaration { - name: "dynamic_function_trampoline_pointers".to_string(), - array: true, - is_extern: false, - is_const: true, - ctype: CType::void_ptr(), - definition: Some(Box::new(CStatement::LiteralArray { - items: dynamic_function_trampoline_statements, - })), - }); - } - - generate_c(&c_statements) - } - /// Get the default extension when serializing this artifact pub fn get_default_extension(triple: &Triple) -> &'static str { match triple.operating_system { @@ -640,4 +472,8 @@ impl Artifact for ObjectFileArtifact { fn serialize(&self) -> Result, SerializeError> { Ok(self.module_bytes.clone()) } + + fn symbol_registry(&self) -> &dyn SymbolRegistry { + &self.metadata + } } diff --git a/lib/engine-object-file/src/header.rs b/lib/engine-object-file/src/header.rs deleted file mode 100644 index ad5ee20c1..000000000 --- a/lib/engine-object-file/src/header.rs +++ /dev/null @@ -1,234 +0,0 @@ -#[derive(Debug, Clone)] -pub enum CType { - Void, - PointerTo { - is_const: bool, - inner: Box, - }, - U8, - U16, - U32, - U64, - USize, - I8, - I16, - I32, - I64, - ISize, - Function { - arguments: Vec, - return_value: Option>, - }, -} - -impl CType { - pub fn void_ptr() -> Self { - CType::PointerTo { - is_const: false, - inner: Box::new(CType::Void), - } - } - - #[allow(dead_code)] - pub fn const_void_ptr() -> Self { - CType::PointerTo { - is_const: false, - inner: Box::new(CType::Void), - } - } - - fn generate_c(&self, w: &mut String) { - match &self { - Self::Void => { - w.push_str("void"); - } - Self::PointerTo { is_const, inner } => { - if *is_const { - w.push_str("const "); - } - inner.generate_c(w); - w.push_str("*"); - } - Self::U8 => { - w.push_str("unsigned char"); - } - Self::U16 => { - w.push_str("unsigned short"); - } - Self::U32 => { - w.push_str("unsigned int"); - } - Self::U64 => { - w.push_str("unsigned long long"); - } - Self::USize => { - w.push_str("unsigned size_t"); - } - Self::I8 => { - w.push_str("char"); - } - Self::I16 => { - w.push_str("short"); - } - Self::I32 => { - w.push_str("int"); - } - Self::I64 => { - w.push_str("long long"); - } - Self::ISize => { - w.push_str("size_t"); - } - Self::Function { - arguments, - return_value, - } => { - // function with no, name, assume it's a function pointer - let ret: CType = return_value - .as_ref() - .map(|i: &Box| (&**i).clone()) - .unwrap_or_default(); - ret.generate_c(w); - w.push(' '); - w.push_str("(*)"); - w.push('('); - if arguments.len() > 1 { - for arg in &arguments[..arguments.len() - 1] { - arg.generate_c(w); - w.push_str(", "); - } - arguments.last().unwrap().generate_c(w); - } else if arguments.len() == 1 { - arguments[0].generate_c(w); - } - w.push(')'); - } - } - } - - fn generate_c_with_name(&self, name: &String, w: &mut String) { - match &self { - Self::PointerTo { .. } - | Self::Void - | Self::U8 - | Self::U16 - | Self::U32 - | Self::U64 - | Self::USize - | Self::I8 - | Self::I16 - | Self::I32 - | Self::I64 - | Self::ISize => { - self.generate_c(w); - w.push(' '); - w.push_str(name); - } - Self::Function { - arguments, - return_value, - } => { - let ret: CType = return_value - .as_ref() - .map(|i: &Box| (&**i).clone()) - .unwrap_or_default(); - ret.generate_c(w); - w.push(' '); - w.push_str(&name); - w.push('('); - if arguments.len() > 1 { - for arg in &arguments[..arguments.len() - 1] { - arg.generate_c(w); - w.push_str(", "); - } - arguments.last().unwrap().generate_c(w); - } else if arguments.len() == 1 { - arguments[0].generate_c(w); - } - w.push(')'); - } - } - } -} - -impl Default for CType { - fn default() -> CType { - CType::Void - } -} - -#[derive(Debug, Clone)] -pub enum CStatement { - Declaration { - name: String, - array: bool, - is_extern: bool, - is_const: bool, - ctype: CType, - definition: Option>, - }, - LiteralArray { - items: Vec, - }, - LiteralConstant { - value: String, - }, -} - -impl CStatement { - fn generate_c(&self, w: &mut String) { - match &self { - Self::Declaration { - name, - array, - is_extern, - is_const, - ctype, - definition, - } => { - if *is_const { - w.push_str("const "); - } - if *is_extern { - w.push_str("extern "); - } - ctype.generate_c_with_name(name, w); - // TODO: array should be part of the type - if *array { - w.push_str("[]"); - } - if let Some(def) = definition { - w.push_str(" = "); - def.generate_c(w); - } - w.push(';'); - w.push('\n'); - } - Self::LiteralArray { items } => { - w.push('{'); - if !items.is_empty() { - w.push('\n'); - } - for item in items { - w.push('\t'); - item.generate_c(w); - w.push(','); - w.push('\n'); - } - w.push('}'); - } - Self::LiteralConstant { value } => { - w.push_str(&value); - } - } - } -} - -// TODO: add config section -pub fn generate_c(statements: &[CStatement]) -> String { - let mut out = String::new(); - for statement in statements { - statement.generate_c(&mut out); - } - out -} diff --git a/lib/engine-object-file/src/lib.rs b/lib/engine-object-file/src/lib.rs index f8b5ee86e..e3f607811 100644 --- a/lib/engine-object-file/src/lib.rs +++ b/lib/engine-object-file/src/lib.rs @@ -24,7 +24,6 @@ mod artifact; mod builder; mod engine; -pub(crate) mod header; mod serialize; pub use crate::artifact::ObjectFileArtifact; diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index b7fef4c3b..da8a93eaa 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -5,7 +5,7 @@ use std::any::Any; use std::fs; use std::path::Path; use std::sync::Arc; -use wasmer_compiler::Features; +use wasmer_compiler::{Features, SymbolRegistry}; use wasmer_types::entity::{BoxedSlice, PrimaryMap}; use wasmer_types::{ DataInitializer, FunctionIndex, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer, @@ -21,7 +21,7 @@ use wasmer_vm::{ /// The `Artifact` contains the compiled data for a given /// module as well as extra information needed to run the /// module at runtime, such as [`ModuleInfo`] and [`Features`]. -pub trait Artifact: Send + Sync + 'static + Upcastable { +pub trait Artifact: Send + Sync { /// Return a reference-counted pointer to the module fn module(&self) -> Arc; @@ -148,41 +148,7 @@ pub trait Artifact: Send + Sync + 'static + Upcastable { .finish_instantiation(is_bulk_memory, &data_initializers) .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap))) } -} -// Implementation of `Upcastable` taken from https://users.rust-lang.org/t/why-does-downcasting-not-work-for-subtraits/33286/7 . -/// Trait needed to get downcasting from `Artifact` to work. -pub trait Upcastable { - fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any; - fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any; - fn upcast_any_box(self: Box) -> Box; -} - -impl Upcastable for T { - #[inline] - fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any { - self - } - #[inline] - fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any { - self - } - #[inline] - fn upcast_any_box(self: Box) -> Box { - self - } -} - -impl dyn Artifact + 'static { - /// Downcast a reference to an `Artifact` into a specific implementor. - #[inline] - pub fn downcast_ref(self: &'_ Self) -> Option<&'_ T> { - self.upcast_any_ref().downcast_ref::() - } - - /// Downcast a mutable reference to an `Artifact` into a specific implementor. - #[inline] - pub fn downcast_mut(self: &'_ mut Self) -> Option<&'_ mut T> { - self.upcast_any_mut().downcast_mut::() - } + /// Get the `SymbolRegistry` used to generate the names used in the Artifact. + fn symbol_registry(&self) -> &dyn SymbolRegistry; }