Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add no_std support #122

Merged
merged 18 commits into from Oct 29, 2018
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,18 @@ description = "WebAssembly interpreter"
keywords = ["wasm", "webassembly", "bytecode", "interpreter"]
exclude = [ "/res/*", "/tests/*", "/fuzz/*", "/benches/*" ]

[features]
default = ["std"]
# Disable for no_std support
std = ["parity-wasm/std"]
# Enable for no_std support
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are those comments outdated?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. They match the readme section about no_std.

# hashmap_core only works on no_std
core = ["hashmap_core"]

[dependencies]
parity-wasm = "0.31"
parity-wasm = { version = "0.31", default-features = false }
byteorder = "1.0"
hashmap_core = { version = "0.1.9", optional = true }
memory_units = "0.3.0"
nan-preserving-float = "0.1.0"

Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,21 @@ cargo build
cargo test
```

# `no_std` support
This crate supports `no_std` environments.
Enable the `core` feature and disable default features:
```toml
[dependencies]
parity-wasm = {
version = "0.31",
default-features = false,
features = "core"
}
```

The `core` feature requires the `core` and `alloc` libraries and a nightly compiler.
Also, code related to `std::error` is disabled.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
Expand Down
6 changes: 5 additions & 1 deletion src/common/stack.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#[allow(unused_imports)]
use alloc::prelude::*;

#[cfg(feature = "std")]
use std::error;
use std::fmt;
use core::fmt;

#[derive(Debug)]
pub struct Error(String);
Expand All @@ -11,6 +14,7 @@ impl fmt::Display for Error {
}
}

#[cfg(feature = "std")]
impl error::Error for Error {
fn description(&self) -> &str {
&self.0
Expand Down
8 changes: 5 additions & 3 deletions src/func.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::rc::{Rc, Weak};
use std::fmt;
#[allow(unused_imports)]
use alloc::prelude::*;
use alloc::rc::{Rc, Weak};
use core::fmt;
use parity_wasm::elements::Local;
use {Trap, TrapKind, Signature};
use host::Externals;
Expand All @@ -17,7 +19,7 @@ use isa;
#[derive(Clone, Debug)]
pub struct FuncRef(Rc<FuncInstance>);

impl ::std::ops::Deref for FuncRef {
impl ::core::ops::Deref for FuncRef {
type Target = FuncInstance;
fn deref(&self) -> &FuncInstance {
&self.0
Expand Down
6 changes: 3 additions & 3 deletions src/global.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::rc::Rc;
use std::cell::Cell;
use alloc::rc::Rc;
use core::cell::Cell;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing we do in Cranelift is to remap core to std in the top-level lib.rs here so that most files can just use std::. This obviously isn't necessary, but since we have some crates that support no_std and some that don't, it's nice to the code more consistent between the two.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would have made rebasing a lot nicer, too 🙃

use value::RuntimeValue;
use Error;
use types::ValueType;
Expand All @@ -13,7 +13,7 @@ use parity_wasm::elements::{ValueType as EValueType};
#[derive(Clone, Debug)]
pub struct GlobalRef(Rc<GlobalInstance>);

impl ::std::ops::Deref for GlobalRef {
impl ::core::ops::Deref for GlobalRef {
type Target = GlobalInstance;
fn deref(&self) -> &GlobalInstance {
&self.0
Expand Down
4 changes: 2 additions & 2 deletions src/host.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::any::TypeId;
use core::any::TypeId;
use value::{RuntimeValue, FromRuntimeValue};
use {TrapKind, Trap};

Expand Down Expand Up @@ -98,7 +98,7 @@ impl<'a> RuntimeArgs<'a> {
/// _ => panic!(),
/// }
/// ```
pub trait HostError: 'static + ::std::fmt::Display + ::std::fmt::Debug + Send + Sync {
pub trait HostError: 'static + ::core::fmt::Display + ::core::fmt::Debug + Send + Sync {
#[doc(hidden)]
fn __private_get_type_id__(&self) -> TypeId {
TypeId::of::<Self>()
Expand Down
7 changes: 7 additions & 0 deletions src/imports.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
#[allow(unused_imports)]
use alloc::prelude::*;

#[cfg(feature = "std")]
use std::collections::HashMap;
#[cfg(not(feature = "std"))]
use hashmap_core::HashMap;

use global::GlobalRef;
use memory::MemoryRef;
use func::FuncRef;
Expand Down
3 changes: 3 additions & 0 deletions src/isa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@
//! - Reserved immediates are ignored for `call_indirect`, `current_memory`, `grow_memory`.
//!

#[allow(unused_imports)]
use alloc::prelude::*;

/// Should we keep a value before "discarding" a stack frame?
///
/// Note that this is a `enum` since Wasm doesn't support multiple return
Expand Down
24 changes: 23 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,21 @@

#![warn(missing_docs)]

#![cfg_attr(not(feature = "std"), no_std)]

//// alloc is required in no_std
#![cfg_attr(not(feature = "std"), feature(alloc))]

#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std as alloc;

#[cfg(feature = "std")]
#[macro_use]
extern crate core;

#[cfg(test)]
extern crate wabt;
#[cfg(test)]
Expand All @@ -104,11 +119,16 @@ extern crate assert_matches;

extern crate parity_wasm;
extern crate byteorder;
#[cfg(not(feature = "std"))]
extern crate hashmap_core;
extern crate memory_units as memory_units_crate;

pub extern crate nan_preserving_float;

use std::fmt;
#[allow(unused_imports)]
use alloc::prelude::*;
use core::fmt;
#[cfg(feature = "std")]
use std::error;

/// Error type which can be thrown by wasm code or by host environment.
Expand Down Expand Up @@ -138,6 +158,7 @@ impl fmt::Display for Trap {
}
}

#[cfg(feature = "std")]
impl error::Error for Trap {
fn description(&self) -> &str {
"runtime trap"
Expand Down Expand Up @@ -308,6 +329,7 @@ impl fmt::Display for Error {
}
}

#[cfg(feature = "std")]
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Expand Down
28 changes: 15 additions & 13 deletions src/memory.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::u32;
use std::ops::Range;
use std::cmp;
use std::fmt;
use std::rc::Rc;
use std::cell::{Cell, RefCell};
#[allow(unused_imports)]
use alloc::prelude::*;
use alloc::rc::Rc;
use core::u32;
use core::ops::Range;
use core::cmp;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

core imports might be grouped

use core::fmt;
use core::cell::{Cell, RefCell};
use parity_wasm::elements::ResizableLimits;
use Error;
use memory_units::{RoundUpTo, Pages, Bytes};
Expand All @@ -28,7 +30,7 @@ const LINEAR_MEMORY_MAX_PAGES: Pages = Pages(65536);
#[derive(Clone, Debug)]
pub struct MemoryRef(Rc<MemoryInstance>);

impl ::std::ops::Deref for MemoryRef {
impl ::core::ops::Deref for MemoryRef {
type Target = MemoryInstance;
fn deref(&self) -> &MemoryInstance {
&self.0
Expand Down Expand Up @@ -172,7 +174,7 @@ impl MemoryInstance {
/// Get value from memory at given offset.
pub fn get_value<T: LittleEndianConvert>(&self, offset: u32) -> Result<T, Error> {
let mut buffer = self.buffer.borrow_mut();
let region = self.checked_region(&mut buffer, offset as usize, ::std::mem::size_of::<T>())?;
let region = self.checked_region(&mut buffer, offset as usize, ::core::mem::size_of::<T>())?;
Ok(T::from_little_endian(&buffer[region.range()]).expect("Slice size is checked"))
}

Expand Down Expand Up @@ -216,7 +218,7 @@ impl MemoryInstance {
/// Copy value in the memory at given offset.
pub fn set_value<T: LittleEndianConvert>(&self, offset: u32, value: T) -> Result<(), Error> {
let mut buffer = self.buffer.borrow_mut();
let range = self.checked_region(&mut buffer, offset as usize, ::std::mem::size_of::<T>())?.range();
let range = self.checked_region(&mut buffer, offset as usize, ::core::mem::size_of::<T>())?.range();
value.into_little_endian(&mut buffer[range]);
Ok(())
}
Expand Down Expand Up @@ -254,7 +256,7 @@ impl MemoryInstance {
}

fn checked_region<B>(&self, buffer: &mut B, offset: usize, size: usize) -> Result<CheckedRegion, Error>
where B: ::std::ops::DerefMut<Target=Vec<u8>>
where B: ::core::ops::DerefMut<Target=Vec<u8>>
{
let end = offset.checked_add(size)
.ok_or_else(|| Error::Memory(format!("trying to access memory block of size {} from offset {}", size, offset)))?;
Expand All @@ -275,7 +277,7 @@ impl MemoryInstance {

fn checked_region_pair<B>(&self, buffer: &mut B, offset1: usize, size1: usize, offset2: usize, size2: usize)
-> Result<(CheckedRegion, CheckedRegion), Error>
where B: ::std::ops::DerefMut<Target=Vec<u8>>
where B: ::core::ops::DerefMut<Target=Vec<u8>>
{
let end1 = offset1.checked_add(size1)
.ok_or_else(|| Error::Memory(format!("trying to access memory block of size {} from offset {}", size1, offset1)))?;
Expand Down Expand Up @@ -314,7 +316,7 @@ impl MemoryInstance {

let (read_region, write_region) = self.checked_region_pair(&mut buffer, src_offset, len, dst_offset, len)?;

unsafe { ::std::ptr::copy(
unsafe { ::core::ptr::copy(
buffer[read_region.range()].as_ptr(),
buffer[write_region.range()].as_ptr() as *mut _,
len,
Expand Down Expand Up @@ -343,7 +345,7 @@ impl MemoryInstance {
return Err(Error::Memory(format!("non-overlapping copy is used for overlapping regions")))
}

unsafe { ::std::ptr::copy_nonoverlapping(
unsafe { ::core::ptr::copy_nonoverlapping(
buffer[read_region.range()].as_ptr(),
buffer[write_region.range()].as_ptr() as *mut _,
len,
Expand Down
15 changes: 11 additions & 4 deletions src/module.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#[allow(unused_imports)]
use alloc::prelude::*;
use alloc::rc::Rc;
use runner::check_function_args;
use Trap;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt;
use core::cell::RefCell;
use core::fmt;

#[cfg(feature = "std")]
use std::collections::HashMap;
#[cfg(not(feature = "std"))]
use hashmap_core::HashMap;

use parity_wasm::elements::{External, InitExpr, Internal, Instruction, ResizableLimits, Type};
use {Module, Error, Signature, MemoryInstance, RuntimeValue, TableInstance};
use imports::ImportResolver;
Expand Down Expand Up @@ -32,7 +39,7 @@ use memory_units::Pages;
#[derive(Clone, Debug)]
pub struct ModuleRef(pub(crate) Rc<ModuleInstance>);

impl ::std::ops::Deref for ModuleRef {
impl ::core::ops::Deref for ModuleRef {
type Target = ModuleInstance;
fn deref(&self) -> &ModuleInstance {
&self.0
Expand Down
14 changes: 8 additions & 6 deletions src/runner.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::ops;
use std::{u32, usize};
use std::fmt;
use std::iter::repeat;
#[allow(unused_imports)]
use alloc::prelude::*;
use core::ops;
use core::{u32, usize};
use core::fmt;
use core::iter::repeat;
use parity_wasm::elements::Local;
use {Error, Trap, TrapKind, Signature};
use module::ModuleRef;
Expand All @@ -19,7 +21,7 @@ use nan_preserving_float::{F32, F64};
use isa;

/// Maximum number of entries in value stack.
pub const DEFAULT_VALUE_STACK_LIMIT: usize = (1024 * 1024) / ::std::mem::size_of::<RuntimeValue>();
pub const DEFAULT_VALUE_STACK_LIMIT: usize = (1024 * 1024) / ::core::mem::size_of::<RuntimeValue>();

// TODO: Make these parameters changeble.
pub const DEFAULT_CALL_STACK_LIMIT: usize = 64 * 1024;
Expand Down Expand Up @@ -122,7 +124,7 @@ impl Interpreter {
}

pub fn resume_execution<'a, E: Externals + 'a>(&mut self, return_val: Option<RuntimeValue>, externals: &'a mut E) -> Result<Option<RuntimeValue>, Trap> {
use std::mem::swap;
use core::mem::swap;

// Ensure that the VM is resumable. This is checked in `FuncInvocation::resume_execution`.
assert!(self.state.is_resumable());
Expand Down
12 changes: 7 additions & 5 deletions src/table.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::u32;
use std::fmt;
use std::cell::RefCell;
use std::rc::Rc;
#[allow(unused_imports)]
use alloc::prelude::*;
use alloc::rc::Rc;
use core::u32;
use core::fmt;
use core::cell::RefCell;
use parity_wasm::elements::ResizableLimits;
use Error;
use func::FuncRef;
Expand All @@ -16,7 +18,7 @@ use module::check_limits;
#[derive(Clone, Debug)]
pub struct TableRef(Rc<TableInstance>);

impl ::std::ops::Deref for TableRef {
impl ::core::ops::Deref for TableRef {
type Target = TableInstance;
fn deref(&self) -> &TableInstance {
&self.0
Expand Down
4 changes: 2 additions & 2 deletions src/tests/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct HostErrorWithCode {
error_code: u32,
}

impl ::std::fmt::Display for HostErrorWithCode {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
impl ::core::fmt::Display for HostErrorWithCode {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> {
write!(f, "{}", self.error_code)
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ fn assert_error_properties() {
fn unsigned_to_runtime_value() {
use super::RuntimeValue;

let overflow_i32: u32 = ::std::i32::MAX as u32 + 1;
let overflow_i32: u32 = ::core::i32::MAX as u32 + 1;
assert_eq!(RuntimeValue::from(overflow_i32).try_into::<u32>().unwrap(), overflow_i32);

let overflow_i64: u64 = ::std::i64::MAX as u64 + 1;
let overflow_i64: u64 = ::core::i64::MAX as u64 + 1;
assert_eq!(RuntimeValue::from(overflow_i64).try_into::<u64>().unwrap(), overflow_i64);
}

Expand Down
2 changes: 1 addition & 1 deletion src/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::borrow::Cow;
use alloc::borrow::Cow;

use parity_wasm::elements::{
FunctionType, ValueType as EValueType, GlobalType, TableType, MemoryType};
Expand Down
2 changes: 2 additions & 0 deletions src/validation/context.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#[allow(unused_imports)]
use alloc::prelude::*;
use parity_wasm::elements::{MemoryType, TableType, GlobalType, BlockType, ValueType, FunctionType};
use validation::Error;

Expand Down
Loading