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

Support 32-bit targets #43

Closed
pepyakin opened this issue Feb 8, 2018 · 21 comments · Fixed by #186
Closed

Support 32-bit targets #43

pepyakin opened this issue Feb 8, 2018 · 21 comments · Fixed by #186

Comments

@pepyakin
Copy link
Collaborator

pepyakin commented Feb 8, 2018

To properly support them we need to setup CI for these targets

@eira-fransham
Copy link
Contributor

I'm working on this. There's an issue with how sNaN is interpreted and I haven't found the cause yet

@eira-fransham
Copy link
Contributor

Right, so I found the cause of the failures: when compiled for i686 (which is the 32-bit system I was using) the tests fail because the bit-level representation of floats is wrong. The IEEE754 spec allows NaNs to be quieted at basically any time but the WASM spec specifies that they may not be quietened when converting to and from i32, only when doing operations like multiplication. Unfortunely, on x87 LLVM will sometimes use the x87 float register stack to pass floats in and out of functions, using fld to push it on the callee and fstp to pop it on the caller. Unfortunately, these operations can and do mask the signalling bit. It works on x86_64 because the floating-point register stack was not inherited from x87 and it appears that it just uses %eap to return floats like it would return any other value.

The only solution I can see for this is to internally use integers to store floats, converting them to/from floats when doing * and /, but not when doing unary negation. In the long-term it might be better to use soft floats, since that would mean that we wouldn't have to disallow floating-point operations in the Polkadot WASM VM.

@sunfishcode
Copy link

Another possible approach is to build i686 builds with -C target-feature=+sse2 .

Beyond sNaNs, x87 also rounds some arithmetic results differently, due to double rounding, and WebAssembly's testsuite is designed to detect such differences. There are techniques for adjusting the rounding, though it's simpler if you can avoid having to.

@eira-fransham
Copy link
Contributor

eira-fransham commented Apr 20, 2018

target-feature works for i686 but is not a generic solution. We should really only rely on behaviour specified in IEEE754 (which essentially means that we can only cast to "real" float when doing binary operations)

@sunfishcode
Copy link

If you're planning to support x87 floating-point, also be aware that x87's mul and div sometimes round differently on x87 than WebAssembly requires, even if you store the values between every operation, and even if you configure the x86 control register to 64-bit precision mode.

@eira-fransham
Copy link
Contributor

If that is the case, then there are no tests for it so far.

@sunfishcode
Copy link

The spec testsuite's float_misc.wast has eg. this and this which should show it.

@eira-fransham
Copy link
Contributor

float_misc succeeds on i686

@sunfishcode
Copy link

Other implementations fail on those tests when using with x87 arithmetic. I don't know what wasmi is doing differently that allows it to pass.

@sunfishcode
Copy link

With cargo test --target i686-unknown-linux-gnu --features opt-in-32bit --no-fail-fast, float_misc.wast passes for me. It appears Rust enables SSE2 by default.

With SSE2 disabled, via RUSTFLAGS="-C target-feature=-sse2" cargo test --target i686-unknown-linux-gnu --features opt-in-32bit --no-fail-fast, float_misc.wast fails for me, with a rounding difference:

Line 58:
thread 'spec::wasm_float_misc' panicked at 'assertion failed: `(left == right)`
  left: `F64(1.0)`,
 right: `F64(1.0000000000000002)`', tests/spec/run.rs:375:54

(this is just the first difference; other tests in float_misc.wast will also round differently too).

@pepyakin
Copy link
Collaborator Author

Guess we need to reopen then.

@pepyakin pepyakin reopened this Apr 25, 2018
@eira-fransham
Copy link
Contributor

I think enforcing SSE2 arithmetic is reasonable for now, but we'd probably want to emulate it down the line. Fixing floats on x87+SSE2 is a fix for the vast majority of 32-bit x86-family CPUs out there. There hasn't been an x86 CPU without SSE2 since 2001 as far as I can tell (apart from a 2013 microcontroller but I can't imagine that x86 microcontrollers are flying off the shelves)

@crsCR
Copy link

crsCR commented Jun 8, 2018

So, is there a way to sort this for a 32bit x86 CPU? Trying to set up on an old Acer Aspire one as only spare I can run 24/7 with Linux (Debian) on.

32 bit targets are not supported at the moment. You can use '32bit_opt_in' feature. See #43

@eira-fransham
Copy link
Contributor

It should now work on post-2003 x86 CPUs (i.e. those with SSE2, if your CPU can build and run Rust programs with no custom configuration then this includes you). Maybe you need to run cargo update -p wasmi and if that doesn't work then we need to push a new version.

@crsCR
Copy link

crsCR commented Jun 8, 2018

Can you tell me where I need to run that update command from please. I have to CD to a directory with a Cargo.toml file or it won't run - I've tried a few places (lots of Cargo.toml files) but when compiling it still says wasmi V 0.1.3 and not the latest (0.2.0). It's an intel Atom N270 cpu - supports SSE2.

@eira-fransham
Copy link
Contributor

cargo update will only update to compatible versions. Your Cargo.toml should specify a version for wasmi that is compatible with 0.2.0. Probably your Cargo.toml says wasmi = "0.1" or wasmi = "0.1.3", change that to wasmi = "0.2".

@crsCR
Copy link

crsCR commented Jun 11, 2018

You've got the Cargo.lock file in /Polkadot Master that refers to wasmi v0.1.3 several times then the Cargo.toml in /Polkadot Master/Polkadot/Parachain that mentions wasmi v0.1 under dependancies... (The Cargo.toml in /Polkadot Master doesn't mention wasmi.) So edit what and run the update from where?

@crsCR
Copy link

crsCR commented Jun 11, 2018

I got it downloading v.0.2.0 but can't stop the thing downloading v0.1.3 as well. :/

@crsCR
Copy link

crsCR commented Jun 12, 2018

OK, so I've edited all .toml and .lock files - and it looks like only wasmi v0.2.0 is going to compile - but now get this:

error[E0308]: mismatched types
  --> substrate/primitives/src/sandbox.rs:97:49
   |
97 |             TypedValue::F32(v_bits) => RuntimeValue::F32(f32::from_bits(v_bits as u32)),
   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `nan_preserving_float::F32`, found f32
   |
   = note: expected type `nan_preserving_float::F32`
              found type `f32`

error[E0308]: mismatched types
  --> substrate/primitives/src/sandbox.rs:98:49
   |
98 |             TypedValue::F64(v_bits) => RuntimeValue::F64(f64::from_bits(v_bits as u64)),
   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `nan_preserving_float::F64`, found f64
   |
   = note: expected type `nan_preserving_float::F64`
              found type `f64`

@pepyakin
Copy link
Collaborator Author

If you're playing with Polkadot, then you can easily replace this code with unimplemented! macro. I think this is the easiest way.

Eventually, we need to migrate Polkadot to wasmi 0.2.0 though.

@crsCR
Copy link

crsCR commented Jun 13, 2018

Meh - looks like I'll have to install a VM on my Windows 64bit desktop...

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 a pull request may close this issue.

4 participants