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

Add no_std support #122

merged 18 commits into from Oct 29, 2018

Conversation

ghost
Copy link

@ghost ghost commented Aug 24, 2018

This PR should contain no breaking changes.

  • Add a std feature, enabled by default and sync it with parity-wasm/std
  • Remove uses of std::io
  • Change to a HashMap implementation that works on alloc
  • Disable std::error for no_std
  • The biggest change is using core and alloc everywhere and substituting std if available.
    This is -- as far as I know -- the accepted way to support no_std (as mentioned in the alloc RFC).

no_std should probably be added to the Travis configuration.
Nom has a working no_std Travis: https://github.com/Geal/nom/blob/master/.travis.yml.

@ghost
Copy link
Author

ghost commented Aug 24, 2018

Also had to add a no_std feature to disable hashmap_core in no_std environments.

@CryZe
Copy link

CryZe commented Aug 25, 2018

Features should never / can't ever be negative. So the no_std feature is a bug waiting to happen.

@ghost
Copy link
Author

ghost commented Aug 25, 2018

How else would you enable hashmap_core only in no_std?
AFAIK, you need a feature to enable a dependency.

@CryZe
Copy link

CryZe commented Aug 25, 2018

Does it not work via a cfg dependency? It may actually not, because cargo has tons of bugs around features and targets.

@ghost
Copy link
Author

ghost commented Aug 25, 2018

I was not aware of cfg dependencies, thanks for the tip.
I tried it now, but sadly rust-lang/cargo#2524.

@pepyakin
Copy link
Collaborator

Hello , thanks for such a great work! I don’t have much time to review because I’m travelling now

@CryZe is right, using negative features is not recommended.

You can add a new feature ‘core’ for this though. Take a look to a cranelift for example https://github.com/CraneStation/cranelift/blob/master/lib/codegen/Cargo.toml

@ghost
Copy link
Author

ghost commented Aug 25, 2018

The "std" feature enables use of libstd. The "core" feature enables use of some minimal std-like replacement libraries. At least one of these two features need to be enabled.

This is just using different names:
With this PR, either std or no_std has to be enabled.
At Cranelift's, either std or core has to be enabled.

But sure, I can rename it, if you want me to?

@pepyakin
Copy link
Collaborator

oh sorry havent had a look into the PR. Yes, that’s should work! I think I would vote for ‘core’ because I think i’ve seen it more often used in such situations

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 🙃

@lexfrl
Copy link

lexfrl commented Aug 26, 2018

Yes, that’s should work! I think I would vote for ‘core’ because I think i’ve seen it more often used in such situations

But in Parity we use feature with name std everywhere. It was started by analogy with https://github.com/BurntSushi/byteorder/blob/master/Cargo.toml#L23

@ghost
Copy link
Author

ghost commented Aug 26, 2018

@fckt core is a negative feature, which has to be enabled iff no_std is to be used.
The default-on normal feature is still called std.
We have to use an ugly negative feature, because cfg dependencies are buggy: rust-lang/cargo#2524.

@ghost
Copy link
Author

ghost commented Aug 26, 2018

Only the float handling in value.rs is left with std dependencies.
This relies on nan-preserving-float and some bits of the standard library that are not in core (for example std::f32::fract).

I have filed a PR for no_std support in nan-preserving-float: eira-fransham/nan-preserving-float#1.
With that and libm, I was able to compile wasmi for no_std.
libm has some panics in debug mode (rust-lang/libm#4), so we still use std when available.

If the PR to nan-preserving-float is accepted and released, we're good to go.

default = ["std"]
# Disable for no_std support
std = ["parity-wasm/std", "byteorder/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.

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

@sorpaas
Copy link
Contributor

sorpaas commented Sep 13, 2018

I'm trying to get this branch working with a real embedded environment (Rux microkernel!), but so far, it still needs some changes, and I would hope we can fix them!

First, hashmap_core crate doesn't work well in my environment. I hope we can remove that crate, but instead, use something like this:

#[cfg(feature = "std")]
use std::collections::{HashMap as Map};
#[cfg(not(feature = "std"))]
use alloc::btree_map::{BTreeMap as Map};

BTreeMap/BTreeSet are actually sufficient for all our use-cases, and using hashmap would impose unnecessary additional memory consumption for those embedded environments.

The second issue I'm facing is missing fract functions for floating points. That doesn't seem to always be defined in some environments, but we can do something like this in impl_float! in value.rs:

			#[cfg(not(feature = "std"))]
			fn fract(self) -> $type {
				self - self.trunc()
			}

I have a branch that's working for Rux microkernel's demo propose at https://github.com/sorpaas/wasmi/tree/jrakow-nostd. That branch also contains some further modifications that make it work with older Rust nightly versions, which I guess we don't need here.

@ghost
Copy link
Author

ghost commented Sep 14, 2018

I had actually solved the float issues locally by depending on libm for the implementation of fract.
These commits are now published here.

The remaining blocker is eira-fransham/nan-preserving-float#1, which is inactive.
I am not sure how to proceed without waiting on that PR.

@sorpaas
Copy link
Contributor

sorpaas commented Sep 14, 2018

@jrakow Would you mind also fixing the hashmap_core issue described above? We can safely use BTreeMap for no_std environments.

@ghost
Copy link
Author

ghost commented Sep 14, 2018

@sorpaas I was just writing a response to that as a second comment:

As for BTreeMap vs. hashmap_core, I am fine with using BTreeMap.
If you would open a PR against https://github.com/jrakow/wasmi/tree/no_std with your changes on that issue, I would happily merge that.

@ghost
Copy link
Author

ghost commented Sep 14, 2018

BTW, the Rust issue for float operations in libcore is rust-lang/rfcs#2505.
Using a Rust libm is the second solution highlighted there.

@sorpaas
Copy link
Contributor

sorpaas commented Sep 14, 2018

@jrakow Thanks! I still need to test whether your solutions work for me regarding libm. The issue is that I need to compile to targets that both support and does not support native floating point. I haven't tested whether libm works in all those cases. Even if it does, I think we would miss some opportunities to use native floating point ops to make code run faster -- All we're missing in libcore is the one single fract function.

Another situation is that it looks like current floating point implementations actually depend on some extern functions (which I have not yet understood why, see this).

One of the possible solutions is to add a feature flag to disable all floating points operations from compiling -- we don't need them in deterministic environments like blockchain virtual machines, so it might be a good feature to have.

Anyway, the above looks not trivial so I might just get another PR if I figured out something (and will definitely fix BTreeMap issue, but probably also just in that PR, to make pulling logistics simple!). Please feel free to continue and merge this!

@pepyakin
Copy link
Collaborator

After chatting with @Vurich in private we decided to embed nan-preserving-float into wasmi repo.

@ghost
Copy link
Author

ghost commented Oct 21, 2018

Looks like the Travis cache is getting too big.

@pepyakin pepyakin merged commit 20154c5 into wasmi-labs:master Oct 29, 2018
@pepyakin
Copy link
Collaborator

Finally we merged it! Thanks for the great job, @jrakow !

@ghost ghost deleted the no_std branch October 29, 2018 14:35
eira-fransham pushed a commit to eira-fransham/wasmi that referenced this pull request Nov 21, 2018
* add default-enabled std feature

* use parity-wasm/std feature only if std is enabled

* drop dependency on std::io

* use hashmap_core instead of std::collections::HashMap

* disable std::error in no_std

* core and alloc all the things

* mention no_std in readme

* add no_std feature and use hashmap_core only on no_std

* rename the no_std feature to core

* drop dependency on byteorder/std

* simplify float impl macro

* remove some trailing whitespace

* use libm for float math in no_std

* add note about no_std panics of libm to readme

* Embed nan-preserving-float crate.

* Add no_std check to the Travis CI config

* add missing dev-dependency
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants