mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 14:48:27 +00:00
First version of Wasmer Reborn
This commit is contained in:
@@ -1,411 +0,0 @@
|
||||
#![deny(
|
||||
dead_code,
|
||||
// missing_docs,
|
||||
nonstandard_style,
|
||||
unused_imports,
|
||||
unused_mut,
|
||||
unused_variables,
|
||||
unused_unsafe,
|
||||
unreachable_patterns
|
||||
)]
|
||||
// Aspirational. I hope to have no unsafe code in this crate.
|
||||
#![forbid(unsafe_code)]
|
||||
#![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")]
|
||||
#![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")]
|
||||
|
||||
//! TODO: Write high value, high-level API intro docs here
|
||||
//! Intro/background information
|
||||
//!
|
||||
//! quick links to places in this document/other crates/standards etc.
|
||||
//!
|
||||
//! example code, link to projects using it
|
||||
//!
|
||||
//! more info, what to do if you run into problems
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
pub use crate::module::*;
|
||||
pub use wasmer_runtime_core::instance::{DynFunc, Instance};
|
||||
pub use wasmer_runtime_core::memory::Memory;
|
||||
pub use wasmer_runtime_core::table::Table;
|
||||
pub use wasmer_runtime_core::typed_func::DynamicFunc;
|
||||
pub use wasmer_runtime_core::Func;
|
||||
pub use wasmer_runtime_core::{func, imports};
|
||||
|
||||
pub mod module {
|
||||
//! Types and functions for WebAssembly modules.
|
||||
//!
|
||||
//! # Usage
|
||||
//! ## Create a Module
|
||||
//!
|
||||
//! ```
|
||||
//! ```
|
||||
//!
|
||||
//! ## Get the exports from a Module
|
||||
//! ```
|
||||
//! # use wasmer::*;
|
||||
//! # fn get_exports(module: &Module) {
|
||||
//! let exports: Vec<ExportDescriptor> = module.exports().collect();
|
||||
//! # }
|
||||
//! ```
|
||||
// TODO: verify that this is the type we want to export, with extra methods on it
|
||||
pub use wasmer_runtime_core::module::Module;
|
||||
// should this be in here?
|
||||
pub use wasmer_runtime_core::types::{ExportDescriptor, ExternDescriptor, ImportDescriptor};
|
||||
// TODO: implement abstract module API
|
||||
}
|
||||
|
||||
pub mod memory {
|
||||
//! Types and functions for Wasm linear memory.
|
||||
pub use wasmer_runtime_core::memory::{Atomically, Memory, MemoryView};
|
||||
}
|
||||
|
||||
pub mod wasm {
|
||||
//! Various types exposed by the Wasmer Runtime relating to Wasm.
|
||||
//!
|
||||
//! TODO: Add index with links to sub sections
|
||||
//
|
||||
//! # Globals
|
||||
//!
|
||||
//! # Tables
|
||||
pub use wasmer_runtime_core::backend::Features;
|
||||
pub use wasmer_runtime_core::export::Export;
|
||||
pub use wasmer_runtime_core::global::Global;
|
||||
pub use wasmer_runtime_core::instance::{DynFunc, Instance};
|
||||
pub use wasmer_runtime_core::memory::Memory;
|
||||
pub use wasmer_runtime_core::module::Module;
|
||||
pub use wasmer_runtime_core::table::Table;
|
||||
pub use wasmer_runtime_core::types::{ExportDescriptor, ExternDescriptor, ImportDescriptor};
|
||||
pub use wasmer_runtime_core::types::{
|
||||
FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type, Value,
|
||||
};
|
||||
pub use wasmer_runtime_core::Func;
|
||||
}
|
||||
|
||||
pub mod vm {
|
||||
//! Various types exposed by the Wasmer Runtime relating to the VM.
|
||||
pub use wasmer_runtime_core::vm::Ctx;
|
||||
}
|
||||
|
||||
pub mod compiler {
|
||||
//! Types and functions for compiling wasm;
|
||||
use crate::module::Module;
|
||||
pub use wasmer_runtime_core::backend::{
|
||||
BackendCompilerConfig, Compiler, CompilerConfig, Features,
|
||||
};
|
||||
pub use wasmer_runtime_core::compile_with;
|
||||
#[cfg(unix)]
|
||||
pub use wasmer_runtime_core::fault::{pop_code_version, push_code_version};
|
||||
pub use wasmer_runtime_core::state::CodeVersion;
|
||||
|
||||
/// Enum used to select which compiler should be used to generate code.
|
||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Backend {
|
||||
#[cfg(feature = "singlepass")]
|
||||
/// Singlepass backend
|
||||
Singlepass,
|
||||
#[cfg(feature = "cranelift")]
|
||||
/// Cranelift backend
|
||||
Cranelift,
|
||||
#[cfg(feature = "llvm")]
|
||||
/// LLVM backend
|
||||
LLVM,
|
||||
/// Auto backend
|
||||
Auto,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
/// Get a list of the currently enabled (via feature flag) backends.
|
||||
pub fn variants() -> &'static [&'static str] {
|
||||
&[
|
||||
#[cfg(feature = "singlepass")]
|
||||
"singlepass",
|
||||
#[cfg(feature = "cranelift")]
|
||||
"cranelift",
|
||||
#[cfg(feature = "llvm")]
|
||||
"llvm",
|
||||
"auto",
|
||||
]
|
||||
}
|
||||
|
||||
/// Stable string representation of the backend.
|
||||
/// It can be used as part of a cache key, for example.
|
||||
pub fn to_string(&self) -> &'static str {
|
||||
match self {
|
||||
#[cfg(feature = "singlepass")]
|
||||
Backend::Singlepass => "singlepass",
|
||||
#[cfg(feature = "cranelift")]
|
||||
Backend::Cranelift => "cranelift",
|
||||
#[cfg(feature = "llvm")]
|
||||
Backend::LLVM => "llvm",
|
||||
Backend::Auto => "auto",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Backend {
|
||||
fn default() -> Self {
|
||||
#[cfg(all(feature = "default-backend-singlepass", not(feature = "docs")))]
|
||||
return Backend::Singlepass;
|
||||
|
||||
#[cfg(any(feature = "default-backend-cranelift", feature = "docs"))]
|
||||
return Backend::Cranelift;
|
||||
|
||||
#[cfg(all(feature = "default-backend-llvm", not(feature = "docs")))]
|
||||
return Backend::LLVM;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Backend {
|
||||
type Err = String;
|
||||
fn from_str(s: &str) -> Result<Backend, String> {
|
||||
match s.to_lowercase().as_str() {
|
||||
#[cfg(feature = "singlepass")]
|
||||
"singlepass" => Ok(Backend::Singlepass),
|
||||
#[cfg(feature = "cranelift")]
|
||||
"cranelift" => Ok(Backend::Cranelift),
|
||||
#[cfg(feature = "llvm")]
|
||||
"llvm" => Ok(Backend::LLVM),
|
||||
"auto" => Ok(Backend::Auto),
|
||||
_ => Err(format!("The backend {} doesn't exist", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compile WebAssembly binary code into a [`Module`].
|
||||
/// This function is useful if it is necessary to
|
||||
/// compile a module before it can be instantiated
|
||||
/// (otherwise, the [`instantiate`] function should be used).
|
||||
///
|
||||
/// [`Module`]: struct.Module.html
|
||||
/// [`instantiate`]: fn.instantiate.html
|
||||
///
|
||||
/// # Params:
|
||||
/// * `wasm`: A `&[u8]` containing the
|
||||
/// binary code of the wasm module you want to compile.
|
||||
/// # Errors:
|
||||
/// If the operation fails, the function returns `Err(error::CompileError::...)`.
|
||||
pub fn compile(wasm: &[u8]) -> crate::error::CompileResult<Module> {
|
||||
wasmer_runtime_core::compile_with(&wasm[..], &default_compiler())
|
||||
}
|
||||
|
||||
/// The same as `compile` but takes a `CompilerConfig` for the purpose of
|
||||
/// changing the compiler's behavior
|
||||
pub fn compile_with_config(
|
||||
wasm: &[u8],
|
||||
compiler_config: CompilerConfig,
|
||||
) -> crate::error::CompileResult<Module> {
|
||||
wasmer_runtime_core::compile_with_config(&wasm[..], &default_compiler(), compiler_config)
|
||||
}
|
||||
|
||||
/// The same as `compile_with_config` but takes a `Compiler` for the purpose of
|
||||
/// changing the backend.
|
||||
pub fn compile_with_config_with(
|
||||
wasm: &[u8],
|
||||
compiler_config: CompilerConfig,
|
||||
compiler: &dyn Compiler,
|
||||
) -> crate::error::CompileResult<Module> {
|
||||
wasmer_runtime_core::compile_with_config(&wasm[..], compiler, compiler_config)
|
||||
}
|
||||
|
||||
/// Copied from runtime core; TODO: figure out what we want to do here
|
||||
pub fn default_compiler() -> impl Compiler {
|
||||
#[cfg(any(
|
||||
all(
|
||||
feature = "default-backend-llvm",
|
||||
not(feature = "docs"),
|
||||
any(
|
||||
feature = "default-backend-cranelift",
|
||||
feature = "default-backend-singlepass"
|
||||
)
|
||||
),
|
||||
all(
|
||||
not(feature = "docs"),
|
||||
feature = "default-backend-cranelift",
|
||||
feature = "default-backend-singlepass"
|
||||
)
|
||||
))]
|
||||
compile_error!(
|
||||
"The `default-backend-X` features are mutually exclusive. Please choose just one"
|
||||
);
|
||||
|
||||
#[cfg(all(feature = "default-backend-llvm", not(feature = "docs")))]
|
||||
use wasmer_llvm_backend::LLVMCompiler as DefaultCompiler;
|
||||
|
||||
#[cfg(all(feature = "default-backend-singlepass", not(feature = "docs")))]
|
||||
use wasmer_singlepass_backend::SinglePassCompiler as DefaultCompiler;
|
||||
|
||||
#[cfg(any(feature = "default-backend-cranelift", feature = "docs"))]
|
||||
use wasmer_clif_backend::CraneliftCompiler as DefaultCompiler;
|
||||
|
||||
DefaultCompiler::new()
|
||||
}
|
||||
|
||||
/// Get the `Compiler` as a trait object for the given `Backend`.
|
||||
/// Returns `Option` because support for the requested `Compiler` may
|
||||
/// not be enabled by feature flags.
|
||||
///
|
||||
/// To get a list of the enabled backends as strings, call `Backend::variants()`.
|
||||
pub fn compiler_for_backend(backend: Backend) -> Option<Box<dyn Compiler>> {
|
||||
match backend {
|
||||
#[cfg(feature = "cranelift")]
|
||||
Backend::Cranelift => Some(Box::new(wasmer_clif_backend::CraneliftCompiler::new())),
|
||||
|
||||
#[cfg(any(feature = "singlepass"))]
|
||||
Backend::Singlepass => Some(Box::new(
|
||||
wasmer_singlepass_backend::SinglePassCompiler::new(),
|
||||
)),
|
||||
|
||||
#[cfg(feature = "llvm")]
|
||||
Backend::LLVM => Some(Box::new(wasmer_llvm_backend::LLVMCompiler::new())),
|
||||
|
||||
Backend::Auto => {
|
||||
#[cfg(feature = "default-backend-singlepass")]
|
||||
return Some(Box::new(
|
||||
wasmer_singlepass_backend::SinglePassCompiler::new(),
|
||||
));
|
||||
#[cfg(feature = "default-backend-cranelift")]
|
||||
return Some(Box::new(wasmer_clif_backend::CraneliftCompiler::new()));
|
||||
#[cfg(feature = "default-backend-llvm")]
|
||||
return Some(Box::new(wasmer_llvm_backend::LLVMCompiler::new()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod codegen {
|
||||
//! Types and functions for generating native code.
|
||||
pub use wasmer_runtime_core::codegen::ModuleCodeGenerator;
|
||||
}
|
||||
|
||||
// TODO: `import` or `imports`?
|
||||
pub mod import {
|
||||
//! Types and functions for Wasm imports.
|
||||
pub use wasmer_runtime_core::import::{
|
||||
ImportObject, ImportObjectIterator, LikeNamespace, Namespace,
|
||||
};
|
||||
pub use wasmer_runtime_core::types::{ExternDescriptor, ImportDescriptor};
|
||||
pub use wasmer_runtime_core::{func, imports};
|
||||
}
|
||||
|
||||
pub mod export {
|
||||
//! Types and functions for Wasm exports.
|
||||
pub use wasmer_runtime_core::export::Export;
|
||||
pub use wasmer_runtime_core::types::{ExportDescriptor, ExternDescriptor};
|
||||
}
|
||||
|
||||
pub mod units {
|
||||
//! Various unit types.
|
||||
pub use wasmer_runtime_core::units::{Bytes, Pages};
|
||||
}
|
||||
|
||||
pub mod types {
|
||||
//! Types used in the Wasm runtime and conversion functions.
|
||||
pub use wasmer_runtime_core::types::{
|
||||
ElementType, FuncDescriptor, FuncSig, GlobalDescriptor, GlobalInit, MemoryDescriptor,
|
||||
TableDescriptor, Type, Value, ValueType,
|
||||
};
|
||||
}
|
||||
|
||||
pub mod error {
|
||||
//! Various error types returned by Wasmer APIs.
|
||||
pub use wasmer_runtime_core::backend::ExceptionCode;
|
||||
pub use wasmer_runtime_core::error::{
|
||||
CallError, CompileError, CompileResult, CreationError, Error, InvokeError, LinkError,
|
||||
ResolveError, RuntimeError,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CompileFromFileError {
|
||||
CompileError(CompileError),
|
||||
IoError(std::io::Error),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for CompileFromFileError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
CompileFromFileError::CompileError(ce) => write!(f, "{}", ce),
|
||||
CompileFromFileError::IoError(ie) => write!(f, "{}", ie),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for CompileFromFileError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
CompileFromFileError::CompileError(ce) => Some(ce),
|
||||
CompileFromFileError::IoError(ie) => Some(ie),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CompileError> for CompileFromFileError {
|
||||
fn from(other: CompileError) -> Self {
|
||||
CompileFromFileError::CompileError(other)
|
||||
}
|
||||
}
|
||||
impl From<std::io::Error> for CompileFromFileError {
|
||||
fn from(other: std::io::Error) -> Self {
|
||||
CompileFromFileError::IoError(other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Idea for generic trait; consider rename; it will need to be moved somewhere else
|
||||
pub trait CompiledModule {
|
||||
fn new(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module>;
|
||||
fn new_with_compiler(
|
||||
bytes: impl AsRef<[u8]>,
|
||||
compiler: Box<dyn compiler::Compiler>,
|
||||
) -> error::CompileResult<Module>;
|
||||
fn from_binary(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module>;
|
||||
fn from_binary_unchecked(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module>;
|
||||
fn from_file(file: impl AsRef<std::path::Path>) -> Result<Module, error::CompileFromFileError>;
|
||||
|
||||
fn validate(bytes: impl AsRef<[u8]>) -> error::CompileResult<()>;
|
||||
}
|
||||
|
||||
// this implementation should be moved
|
||||
impl CompiledModule for Module {
|
||||
fn new(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module> {
|
||||
let bytes = bytes.as_ref();
|
||||
wasmer_runtime_core::compile_with(bytes, &compiler::default_compiler())
|
||||
}
|
||||
|
||||
fn new_with_compiler(
|
||||
bytes: impl AsRef<[u8]>,
|
||||
compiler: Box<dyn compiler::Compiler>,
|
||||
) -> error::CompileResult<Module> {
|
||||
let bytes = bytes.as_ref();
|
||||
wasmer_runtime_core::compile_with(bytes, &*compiler)
|
||||
}
|
||||
|
||||
fn from_binary(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module> {
|
||||
let bytes = bytes.as_ref();
|
||||
wasmer_runtime_core::compile_with(bytes, &compiler::default_compiler())
|
||||
}
|
||||
|
||||
fn from_binary_unchecked(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module> {
|
||||
// TODO: optimize this
|
||||
Self::from_binary(bytes)
|
||||
}
|
||||
|
||||
fn from_file(file: impl AsRef<std::path::Path>) -> Result<Module, error::CompileFromFileError> {
|
||||
use std::fs;
|
||||
use std::io::Read;
|
||||
let path = file.as_ref();
|
||||
let mut f = fs::File::open(path)?;
|
||||
// TODO: ideally we can support a streaming compilation API and not have to read in the entire file
|
||||
let mut bytes = vec![];
|
||||
f.read_to_end(&mut bytes)?;
|
||||
|
||||
Ok(Module::from_binary(bytes.as_slice())?)
|
||||
}
|
||||
|
||||
fn validate(bytes: impl AsRef<[u8]>) -> error::CompileResult<()> {
|
||||
// TODO: optimize this
|
||||
let _ = Self::from_binary(bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user