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

Stabilize memory-releated std::arch::wasm32 intrinsics #56292

Closed
7 tasks done
alexcrichton opened this issue Nov 27, 2018 · 44 comments
Closed
7 tasks done

Stabilize memory-releated std::arch::wasm32 intrinsics #56292

alexcrichton opened this issue Nov 27, 2018 · 44 comments
Labels
disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@alexcrichton
Copy link
Member

alexcrichton commented Nov 27, 2018

This is a tracking issue where I'm going to propose that we stabilize two functions in the standard library:

These intrinsics are currently existing as memory::size and memory::grow, but I'm going to propose here that we don't do that and flatten them in the wasm32 module. As a reference, their signatures are:

fn memory_size(memory_index: u32) -> usize;
fn memory_grow(memory_index: u32, delta_pages: usize) -> isize;

Semantics

These two intrinsics represent instructions stabilized in the WebAssembly specification.

The memory.size instruction will return the current size, in WebAssembly pages, of the specified memory index. Currently only index 0 is allowed, the index is required to be a constant value, and the return value is an usize value. Note that usize is used instead of the spec's i32 for two reasons: this is more forward compatible with a possible wasm64 architecture and the return value is always an unsigned number.

The memory.grow instruction will grow the memory index specified by the given number of pages. The old size of memory, in pages, is returned. If the grow operation fails, then -1 is returned. LIke memory_size, the memory index is currently required to be 0 and must be a constant value. The delta may be a runtime value, however.

The binary encoding of these two instructions each have a reserved zero byte which is intended to be used to specify a different nonzero memory index in the future. As a recap, each WebAssembly module may have multiple "memory" instances, each assigned a unique index starting from zero. In the WebAssembly MVP, however, only at most one memory can be assigned with each wasm module, always located at index 0. (the memory may be omitted as well)

While the memory argument is currently required to be zero, it's expected that future versions of WebAssembly will no longer have this requirement and any u32 value can be specified. It's also worth noting that the zero byte in the encoding of memory.size and memory.grow may not only be exclusively used for new indices. Current proposals to WebAssembly have repurposed required zero bytes as flags fields in addition to specified more than nonzero indices. While I'm not aware of any proposal to do so, it may be possible that a future feature to WebAssembly will have more than just a memory index argument to these instructions.

Stabilization in Rust

Stabilization of these intrinsics would be a significant step for Rust on multiple axes:

  • Primarily these would be the first non-x86 intrinsics stabilized. This means it's the first architecture to have a stable std::arch module which isn't x86/x86_64.
  • Unlike x86 intrinsics, there is no prior art for how these intrinsics should be stabilized. Unlike x86/x86_64 the "vendor" (the WebAssembly specification) isn't giving us a document of functions with signatures.

Stabilization here will be paving a path forward for future stabilization of WebAssembly intrinsics, so it's good to consider conventions! It's unclear if the WebAssembly specification will, if ever, provide a document like Intel does for intrinsics with function names and function signatures for other languages to provide.

We've had some discussion on the naming of wasm intrinsics. We'd like to ensure that we match Clang (like we do for x86/x86_64), but Clang doesn't currently (AFAIK) have a naming convention beyond the __builtin_* internal defines it has today.

What I'm proposing here is basically a convention of:

  • We provide intrinsics for instructions not natively expressable in Rust. For example we don't give an i32.add intrinsic function as it's just a + b.
  • Intrinsic signatures match the effective signature of the instruction, to the best it can. Above the memory.grow and memory.size intrinsics are fairly simple.
  • Intrinsic names match the name of the wasm intstructions, with non-rust-identifier characters mapped to an underscore.

The thinking behind these set of conventions it that it should be very easy to figure out what each intrinsic does, just like it is for Intel. The Rust documentation would always link to the WebAssembly specification for stabilized intrinsics.

Additionally we won't have any sort of automatic verification of WebAssembly intrinsics just yet like we do for x86 intrinsics in the stdsimd repository. There's so few WebAssembly intrinsics it's thought that we can simply manually verify each intrinsic.

TODO items before stabilization is finalized

  • FCP (this issue)
  • Rename the intrinsics (if that's decided on)
  • Fix the "This is supported on MIPS only" message in documentation
  • Update documentation to link to WebAssembly specification
  • maybe flag functions as safe
  • Update documentation on behavior with nonzero indexes
  • Document the page size on these intrinsics.
@alexcrichton alexcrichton added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Nov 27, 2018
@alexcrichton
Copy link
Member Author

Note that for alternatives of naming I'm not listing them exhaustively here as there's some discussion already at rust-lang/stdarch#562, but if others feel that we should name them differently, it'd be good to discuss here/there!

@alexcrichton
Copy link
Member Author

@rfcbot fcp merge

cc @rust-lang/wg-wasm
cc @tlively

There's a good long description in the post above about the stabilization here, and now I'd like to request a sign-off

@rfcbot
Copy link

rfcbot commented Nov 27, 2018

Team member @alexcrichton has proposed to merge this. The next step is review by the rest of the tagged teams:

Concerns:

Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Nov 27, 2018
@alexcrichton
Copy link
Member Author

Oh sorry it's probably also worth mentioning the rationale for stabilization here. That's twofold:

  • First, this enables allocators like wee_alloc to be built on stable Rust now that they'd have access to the actual wasm instructions to allocate memory.
  • Second, this starts the process on stabilizing a convention for how to encode WebAssembly intrinsics in Rust, paving the way for future instructions like atomics and SIMD

@fitzgen
Copy link
Member

fitzgen commented Nov 27, 2018

First: I would love to get wee_alloc on stable and anything else using these wasm instructions! +1 from me.

However, I find it very strange from a language design perspective that there is this exception to the way that functions and their arguments behave where certain functions' arguments must be "const" but that is not expressible in the type system at all. It didn't feel weird for intrinsics, since those are not normal functions, but here it does. Alex tells me that the extant arch::x86 functions already behave like this, so I suppose it isn't worth re-litigating...

@alexcrichton
Copy link
Member Author

Ah yes @fitzgen, an excellent point! FWIW I think it was briefly considered for arch::x86{,_64} to use traits for this, but it was quickly ruled out for that use case specifically because:

  • There are thousands of intrinsics which would require practically thousands of traits
  • We couldn't automatically generate "the most appropriate trait" for each intrinsic with good naming and such, as it wasn't programmatically specified anywhere
  • There's so much history with the existing intrinsics in C/C++ we wanted to draw from that instead of trying to pave a new set of conventions.

You might realize, though, that none of these arguments apply to WebAssembly! We're talking about a handful of possible intrinsics as well as no prior art/history/specification. We're blazing a new trail here!

The std::arch module I think is definitely open to having a per-platform conventions rather than attempting to have a cross-platform convention for all the various intrinsics here and there. In that sense I do think it's a possible legitimate alternative to have something like:

fn memory_size<T: Memory>() -> i32;
fn memory_grow<T: Memory>(delta: i32) -> i32;

trait Memory: Sealed { /* all unstable */ }
struct Memory0;

impl Memory for Memory0 { /* ... */ }

memory_size::<Memory0>(); 
// etc...

I would probably personally still be in favor of an x86/x86_64-like approach where we require, for now, arguments to be constants. It makes the functions a little weird, but is in theory something we can fix in the future and is hopefully a largely forward-compatible story. With these being such low-level intrinsics I'm also tempted to not try to add too much abstraction as it could run the risk of not being too beneficial in practice (as these are so rarely used) and also providing hindrances to usage or stabilization accidentally.

@alexcrichton
Copy link
Member Author

Oh one other point I can bring up as well, is that both of these intrinsics are unsafe. Neither, however, actually need to be unsafe. Unlike x86/x86_64 we don't have to worry about "what happens if a cpu executes an unknown instruction" because that's actually impossible for WebAssembly. As a result these functions can likely be safe as they don't expose any amount of inherent unsafety.

@Centril
Copy link
Contributor

Centril commented Nov 27, 2018

cc @rust-lang/lang I think this proposal seems fine, but as it affects intrinsics / the abstract machine, I think we'll want to look at this. :)

@eddyb
Copy link
Member

eddyb commented Nov 27, 2018

IMO we should bring in either @rust-lang/lang and/or @rust-lang/compiler into the decision (not sure what adding T- tags will do, but we probably don't need to change the FCP?).

For myself, this change is fine, including (only for intrinsics), "required-const arguments".

cc @sunfishcode

@joshtriplett
Copy link
Member

I'd like to see the low-level intrinsics match the instructions as closely as possible. We can then have higher level wrappers similar to the type system approach proposed above.

Could we please name the "memory" argument something else, though? Something that makes it less ambiguous?

@Centril
Copy link
Contributor

Centril commented Nov 27, 2018

@eddyb

not sure what adding T- tags will do

Nothing due to rfcbot bugs. :(

For myself, this change is fine, including (only for intrinsics), "required-const arguments".

Wait; I missed this... What exactly does #[rustc_args_required_const(n)] do? make the nth argument const X: T such that it must be evaluable at compile time? Seems this is used in a bunch of stable intrinsics for x86 right now.

@eddyb
Copy link
Member

eddyb commented Nov 27, 2018

@Centril Yes, this would ideally be information that the compiler has about intrinsics, but it appears that infrastructure like platform-intrinsics has gone mostly unused and stdsimd relies on LLVM intrinsics directly, which is not a future/compiler-friendly approach.

@Centril
Copy link
Contributor

Centril commented Nov 27, 2018

OK; ummh... feels like a legitimized hack to me especially since const-only parameters in fn foo(const X: T, ...) won't unify with fn foo<const X: T>() since the latter is inferrable and the former is not and I don't know how we'll solve this for the Fn traits... What strikes me as problematic was that the language team never was in on this in rust-lang/rfcs#2325. I suppose that the change to the type system has already been done so adding it here doesn't cause any new type of problems.

@eddyb
Copy link
Member

eddyb commented Nov 27, 2018

@Centril It's not part of the typesystem and it should (very importantly) be only done for intrinsics - they're already special in ways the typesystem can't capture (e.g. transmute).

@tlively
Copy link
Contributor

tlively commented Nov 27, 2018

LGTM FWIW. I did notice on the documentation that it's telling me these functions are available for MIPS only, but that is an entirely separate issue.

Edit: I see this is already in the TODOs!

@SimonSapin
Copy link
Contributor

Currently only index 0 is allowed

The doc-comments and code don’t agree on what happens if this is not the case. The former talks about a “runtime validation error of the wasm module”, but the Rust code wrapping the intrinsic calls abort().

the index is required to be a constant value

What does that mean, from a user’s point of view? What happens if I try to use it with a non-constant? What exactly is considered "constant"? Is it the same as if I copy-pasted the source expression used as the argument into a const item?

All of this is worth documenting in the respective doc-comments. (Perhaps a reference to some shared documentation of "constant argument" in some place. Perhaps in the Nomicon?)

The memory.grow instruction will grow the memory index specified by the given number of pages.

The delta argument is a i32. What happens if it is negative?

the current size, in WebAssembly pages

It seems that this API can only be useful if the size of a page is known. https://github.com/WebAssembly/design/blob/master/Semantics.md#resizing says this is currently 64 KB, but could be (optionally) larger in the future. Should there be an API to query the page size?

Unlike x86/x86_64 we don't have to worry about "what happens if a cpu executes an unknown instruction" because that's actually impossible for WebAssembly.

How is it impossible? Won’t future extensions to the WebAssembly "language" ever add new instructions? What do (older) implementations do when encountering an unknown instruction?

@Centril
Copy link
Contributor

Centril commented Nov 28, 2018

@SimonSapin

What does that mean, from a user’s point of view? What happens if I try to use it with a non-constant? What exactly is considered "constant"? Is it the same as if I copy-pasted the source expression used as the argument into a const item?

All of this is worth documenting in the respective doc-comments. (Perhaps a reference to some shared documentation of "constant argument" in some place. Perhaps in the Nomicon?)

From @eddyb's answer (#56292 (comment)) to my question re. rustc_args_required_const we know that the formal parameter is a const context such that the actual argument must be a constant expression, thus it must also be assignable to a const item. The reference explains what a const context/expr means and you can refer to that in the documentation.

@gnzlbg
Copy link
Contributor

gnzlbg commented Nov 28, 2018

@SimonSapin

What exactly is considered "constant"? What does that mean, from a user’s point of view? What happens if I try to use it with a non-constant?

From a user's point of view, these arguments are const (that's what is considered "constant"). So the answer to the question "What happens if one tries to assign a const a non-constant?" is "the same thing that happens if one tries to assign a non-constant-expression to a const": one gets an error saying that the argument is not a constant expression. Playground:

error: argument 1 is required to be a constant
 --> src/main.rs:5:5
  |
5 |     foo(x);
  |     ^^^^^^

error: aborting due to previous error

The error message could be arguably a bit better, but I think it is good enough, and there is nothing blocking anyone from working on that.


@joshtriplett

Could we please name the "memory" argument something else, though? Something that makes it less ambiguous?

The technical term in the WebAssembly spec is "memory index" (http://webassembly.github.io/spec/core/syntax/instructions.html#syntax-instr-memory).

AFAICT changing an argument name is not a backwards incompatible change, so we can probably do this any time.


@fitzgen

However, I find it very strange from a language design perspective that there is this exception to the way that functions and their arguments behave where certain functions' arguments must be "const" but that is not expressible in the type system at all.

Hardware has the concept of immediate mode arguments but Rust does not support these in its type system yet, so APIs for intrinsics that accept immediate mode arguments are necessarily awkward (they are something that the language cannot properly express). A couple of different alternatives were considered in the std::arch RFCs, but they all had even more downsides than this "hack".

Work on this topic is currently blocked on const-generics stabilization. But the worst case scenario that I can imagine is that afterwards we discover that this was all a bad idea and that we don't want to support these in the type system, such that we will do nothing here and these APIs will remain awkward to use, or such that we deprecate them and replace them with better APIs. Either way, this is in my opinion better than not adding these APIs (we wouldn't be able to use SIMD on stable Rust right now without these, WASM would have to continue to require nightly Rust, etc.).

@gnzlbg
Copy link
Contributor

gnzlbg commented Nov 28, 2018

Oh one other point I can bring up as well, is that both of these intrinsics are unsafe. Neither, however, actually need to be unsafe. Unlike x86/x86_64 we don't have to worry about "what happens if a cpu executes an unknown instruction" because that's actually impossible for WebAssembly. As a result these functions can likely be safe as they don't expose any amount of inherent unsafety.

IIRC the only reason the x86/x86_64 intrinsics are unsafe is because they require target features to work correctly (and until something like RFC target_feature 1.1 is merged, we can't do any better). These functions do not require any target features to work correctly, so the only reason they would have to be unsafe is if there is anything that callers must uphold for safety.

I am not sure if this is the case:

  • memory_size(x: i32): the docs state that if x != 0 then this might produce a WASM validation error. AFAIK the WebAssembly spec requires validation to be performed, so calling memory_size with x != 0 cannot lead safe Rust code to violate any of Rust safety guarantees, and therefore, memory_size can be safe.

  • grow also takes a delta: i32 argument that represents the number of memory pages requested. The docs state that if the request cannot be satisfied, grow returns -1. From reading the spec, it is unclear to me what happens if delta < 0. Is grow guaranteed to return -1 in this case ? If so, I think it can be safe as well.

@pepyakin
Copy link
Contributor

I think grow should take u32, since memory.grow implicitly assumes unsigned value AFAIU.

@sunfishcode
Copy link
Member

WebAssembly interprets all of these values as unsigned, including the delta, so there's no possibility for it to be negative.

Separately, while 64-bit linear memories aren't designed yet, it's likely that LLVM will model this as a separate architecture "wasm64", even though at the wasm level, it's still one architecture. This is why we call the current target "wasm32". So if that happens, then on wasm64, memory.grow and memory.size will want to work in terms of 64-bit types.

So I recommend Rust use usize for the return types and delta argument of memory.grow and memory.size. The memory index argument could also be unsigned, though we don't know a lot about what things would look like if there were very large numbers of linear memories.

@SimonSapin
Copy link
Contributor

@sunfishcode These functions are in a std::arch::wasm32 module. Presumably, was64 targets will have a corresponding std::arch::wasm64 module where corresponding functions can have a different signature.

@SimonSapin
Copy link
Contributor

It seems that at least some of the values in these signatures should be u32 instead of i32.

@rfcbot concern u32

@sunfishcode
Copy link
Member

@SimonSapin That makes sense. Still though, these are related to memory sizes, and code intending to support both wasm32 and wasm64 will likely be using usize for related values, so using usize in these builtins would make them more convenient.

@gnzlbg
Copy link
Contributor

gnzlbg commented Nov 28, 2018

@SimonSapin changing u32 to usize is not backwards compatible, if we were to use usize here we could re-export these as is from the wasm64 module.

Having said this, I don't know of any good reason to re-export these: they are tiny, and re-implementing them with u64 for wasm64 is zero work (this is something we do in x86/x86_64 though).

From a semantic point-of-view, usize is not only pointer sized, but is also the integer type that fixes how much a pointer can be offseted, the maximum number of elements in an array, the maximum size of a Rust object, and has the same layout as uintptr_t. I don't know which types does __builtin_wasm_memory_grow accept in clang, but in the tests these use __SIZE_TYPE__, it might be worth it to pick a type that's semantically equivalent to what the C compilers exposes. Although @alexcrichton mentioned that for clang at least this is all still pretty much in the air.

@Kimundi
Copy link
Member

Kimundi commented Nov 28, 2018

I second the notion that using i32 in these signatures should at least be justified somehow. For reference, WebAssembly spec uses the name i32 to mean "uninterpreted 32 bit", while s32 and u32 correspond to our" i32 and u32.

@Centril
Copy link
Contributor

Centril commented Nov 28, 2018

Looking through the specification and the operational semantics of WASM we have:

However; The OCaml implementation of grow is:

let grow mem delta =
  let old_size = size mem in
  let new_size = Int32.add old_size delta in
  if I32.gt_u old_size new_size then raise SizeOverflow else
  if not (within_limits new_size mem.max) then raise SizeLimit else
  let after = create new_size in
  let dim = Array1_64.dim mem.content in
  Array1.blit (Array1_64.sub mem.content 0L dim) (Array1_64.sub after 0L dim);
  mem.content <- after

In particular we have: if I32.gt_u old_size new_size then raise SizeOverflow else.
Thus we can conclude that delta >= 0 or an exception is raised so this seems to be validated at runtime?

@sunfishcode
Copy link
Member

In particular we have: if I32.gt_u old_size new_size then raise SizeOverflow else.
Thus we can conclude that delta >= 0 or an exception is raised so this seems to be validated at runtime?

That's a runtime check for overflow, not for negative deltas. If the old size is 0 and the delta is 0x80000000, that's valid here and not an overflow, because it's using an unsigned interpretation (gt_u), even though that delta value would be negative if interpreted as signed.

@fitzgen
Copy link
Member

fitzgen commented Nov 28, 2018

@sunfishcode

As a minor detail, while the memory size is defined as a u32 today, the actual binary encoding uses a variable-length field which is compatible with larger sizes, so nothing fundamentally prevents WebAssembly from increasing the allowed size in the future.

On the rare chance we need to access memory indices that are larger than u32::MAX we can always add a memory_grow2 function. /me shrugs

@Centril
Copy link
Contributor

Centril commented Nov 28, 2018

@sunfishcode Hmm; ok -- then the WASM specification does not, as far as I can tell, whether specify whether delta < 0 is permitted or not... Can we check what the semantics are with the folks that wrote the spec?

@rfcbot rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Dec 8, 2018
@rfcbot
Copy link

rfcbot commented Dec 8, 2018

The final comment period, with a disposition to merge, as per the review above, is now complete.

alexcrichton added a commit to alexcrichton/stdarch that referenced this issue Dec 9, 2018
This commit stabilizes the wasm32 memory-related intrinsics, as
specified in rust-lang/rust#56292. The old intrinsics were removed and
the current intrinsics were updated in place, but it's the last breaking
change!
@alexcrichton
Copy link
Member Author

I've opened a stabilization PR at rust-lang/stdarch#613

alexcrichton added a commit to alexcrichton/stdarch that referenced this issue Dec 10, 2018
This commit stabilizes the wasm32 memory-related intrinsics, as
specified in rust-lang/rust#56292. The old intrinsics were removed and
the current intrinsics were updated in place, but it's the last breaking
change!
alexcrichton added a commit to rust-lang/stdarch that referenced this issue Dec 10, 2018
This commit stabilizes the wasm32 memory-related intrinsics, as
specified in rust-lang/rust#56292. The old intrinsics were removed and
the current intrinsics were updated in place, but it's the last breaking
change!
@alexcrichton
Copy link
Member Author

Ok the stdsimd implementation has been merged. I've made one final tweak suggested by @sunfishcode that the memory_grow function actually returns a usize instead of an isize. The "failed to grow" scenario is documented as "returns usize::max_value()" and now a very-large success won't have to cast into an unsigned value just afterwards.

alexcrichton added a commit to alexcrichton/rust that referenced this issue Dec 10, 2018
Includes some new stabilized intrinsics for the wasm32 target!

Closes rust-lang#56292
pietroalbini added a commit to pietroalbini/rust that referenced this issue Dec 11, 2018
…matsakis

Update the stdsimd submodule

Includes some new stabilized intrinsics for the wasm32 target!

Closes rust-lang#56292
kennytm added a commit to kennytm/rust that referenced this issue Dec 12, 2018
…matsakis

Update the stdsimd submodule

Includes some new stabilized intrinsics for the wasm32 target!

Closes rust-lang#56292
pietroalbini added a commit to pietroalbini/rust that referenced this issue Dec 12, 2018
…matsakis

Update the stdsimd submodule

Includes some new stabilized intrinsics for the wasm32 target!

Closes rust-lang#56292
pietroalbini added a commit to pietroalbini/rust that referenced this issue Dec 13, 2018
…matsakis

Update the stdsimd submodule

Includes some new stabilized intrinsics for the wasm32 target!

Closes rust-lang#56292
kennytm added a commit to kennytm/rust that referenced this issue Dec 14, 2018
…matsakis

Update the stdsimd submodule

Includes some new stabilized intrinsics for the wasm32 target!

Closes rust-lang#56292
pietroalbini added a commit to pietroalbini/rust that referenced this issue Dec 14, 2018
…matsakis

Update the stdsimd submodule

Includes some new stabilized intrinsics for the wasm32 target!

Closes rust-lang#56292
pietroalbini added a commit to pietroalbini/rust that referenced this issue Dec 15, 2018
…matsakis

Update the stdsimd submodule

Includes some new stabilized intrinsics for the wasm32 target!

Closes rust-lang#56292
JakeOShannessy added a commit to Daohub-io/cap9 that referenced this issue May 22, 2019
The previous nightly version specified (nightly-2019-03-05) had an issue
where components where not supported on Windows. 2018 versions had an
issue with some wasm memory functions not being finalised
(see rust-lang/rust#56292). This could all be
wrong but I found this version worked for me where others didn't.
Latrasis pushed a commit to Daohub-io/cap9 that referenced this issue May 23, 2019
* Change nightly version.

The previous nightly version specified (nightly-2019-03-05) had an issue
where components where not supported on Windows. 2018 versions had an
issue with some wasm memory functions not being finalised
(see rust-lang/rust#56292). This could all be
wrong but I found this version worked for me where others didn't.

* Add batch equivalent to build.sh
Latrasis pushed a commit to Daohub-io/cap9 that referenced this issue Jun 7, 2019
* Change nightly version.

The previous nightly version specified (nightly-2019-03-05) had an issue
where components where not supported on Windows. 2018 versions had an
issue with some wasm memory functions not being finalised
(see rust-lang/rust#56292). This could all be
wrong but I found this version worked for me where others didn't.

* Add batch equivalent to build.sh

* Update windows build command

* Rough validation testing

This tests the proofs-of-concept for the validation code. It is not
currently integrated into the test suites or CI.

* Fix contract name

* Add cap9-build to link in sycalls

* Validate syscalls.

* Functioning syscall linking and validation (albeit very messy)

* Change toolchain version

* Use cross platform CWD.

* Use no_std in native validator

* Clean up cap9-build logging

* Add toolchain to native-validator

* Move validation code into separate lib

* Switch to HTTP transport for tests

This is what I'd used previously and it had always worked well for me.

* Experiment with circleci

* Remove SolC

* Only build ewasm

* Change parity command

* Fix directory

* Build wasm-build 0.6.0

* Fix parity url

* Fix directory to run parity

* Fix location of cargo.lock

* Fix parity path

* Don't need to kill database

* Fix Cargo.lock path

* Remove reference to Cargo.lock, which is not commited

* Correct specification of dev dependencies

* Fix no_std build

* Fix std build

* Add get_code_size to the kernel

* Use custom parity node in CI

* Fix installation of parity

* circleci: install cmake

* circleci: use the right package manager

* circleci: needed privileges

* circleci: add more dependencies

* circleci: remove gflags

* circleci: try different gflags package name

* circleci: add perl and yasm

* circleci: see if we can use parity's image

* circleci: remove sudo

* circleci: remove install line

* circleci: try building parity's branch

* Copy example from parity's docker image

* circleci: actually clone parity

* circleci: switch to stable parity

* circleci: build syn first

* circleci: build syn from git

* circleci: dev build

* circleci: build 1 package at a time

* circleci: save cache after parity build

* Revert "circleci: save cache after parity build"

This reverts commit df48168.

* circleci: save cache after parity build

* circleci: checkout code

* circleci: restore cache

* circleci: cache parity builds

* circleci: version bump deps

* circleci: install parity stage

* circleci: don't update rust

* circleci: set default toolchain

* circleci: reorder rustup

* circleci: check for the existence of cargo

* circleci: only install not build then install

* circleci: install this package

* circleci: formatting

* Don't update rust

* circleci: cache rustup

* circleci: update PATH

* circleci: checkout code

* circleci: fix .profile

* circleci: force overwrite of parity node

* circleci: wrong line

* circleci: add log line

* circleci: more log lines

* circleci: fix cache path

* circleci: properly namespace directories

* circleci: fix yaml syntax error

* circleci: install nodejs

* circleci: add repo for nodejs

* circleci: add missing -y

* circleci: install newer version of node

* circleci: use .xz

* circleci: switch parity to master

* Build custom parity as part of ci (#152)

* circleci: add more dependencies

* circleci: remove gflags

* circleci: try different gflags package name

* circleci: add perl and yasm

* circleci: see if we can use parity's image

* circleci: remove sudo

* circleci: remove install line

* circleci: try building parity's branch

* Copy example from parity's docker image

* circleci: actually clone parity

* circleci: switch to stable parity

* circleci: build syn first

* circleci: build syn from git

* circleci: dev build

* circleci: build 1 package at a time

* circleci: save cache after parity build

* Revert "circleci: save cache after parity build"

This reverts commit df48168.

* circleci: save cache after parity build

* circleci: checkout code

* circleci: restore cache

* circleci: cache parity builds

* circleci: version bump deps

* circleci: install parity stage

* circleci: don't update rust

* circleci: set default toolchain

* circleci: reorder rustup

* circleci: check for the existence of cargo

* circleci: only install not build then install

* circleci: install this package

* circleci: formatting

* Don't update rust

* circleci: cache rustup

* circleci: update PATH

* circleci: checkout code

* circleci: fix .profile

* circleci: force overwrite of parity node

* circleci: wrong line

* circleci: add log line

* circleci: more log lines

* circleci: fix cache path

* circleci: properly namespace directories

* circleci: fix yaml syntax error

* circleci: install nodejs

* circleci: add repo for nodejs

* circleci: add missing -y

* circleci: install newer version of node

* circleci: use .xz

* circleci: switch parity to master

* validation: update whitelist and reorder to match parity.

* validation: add EXTCODECOPY and simple test

* Validation merge (#154)

* circleci: add more dependencies

* circleci: remove gflags

* circleci: try different gflags package name

* circleci: add perl and yasm

* circleci: see if we can use parity's image

* circleci: remove sudo

* circleci: remove install line

* circleci: try building parity's branch

* Copy example from parity's docker image

* circleci: actually clone parity

* circleci: switch to stable parity

* circleci: build syn first

* circleci: build syn from git

* circleci: dev build

* circleci: build 1 package at a time

* circleci: save cache after parity build

* Revert "circleci: save cache after parity build"

This reverts commit df48168.

* circleci: save cache after parity build

* circleci: checkout code

* circleci: restore cache

* circleci: cache parity builds

* circleci: version bump deps

* circleci: install parity stage

* circleci: don't update rust

* circleci: set default toolchain

* circleci: reorder rustup

* circleci: check for the existence of cargo

* circleci: only install not build then install

* circleci: install this package

* circleci: formatting

* Don't update rust

* circleci: cache rustup

* circleci: update PATH

* circleci: checkout code

* circleci: fix .profile

* circleci: force overwrite of parity node

* circleci: wrong line

* circleci: add log line

* circleci: more log lines

* circleci: fix cache path

* circleci: properly namespace directories

* circleci: fix yaml syntax error

* circleci: install nodejs

* circleci: add repo for nodejs

* circleci: add missing -y

* circleci: install newer version of node

* circleci: use .xz

* circleci: switch parity to master

* validation: update whitelist and reorder to match parity.

* validation: add EXTCODECOPY and simple test

* cap9-build: increase the amount of available memory in kernel

* kernel: link in basic validation code for testing

* example_contact: expand

* cap9-build: properly pass the number of memory pages

* kernel: LTO needs to be turned off for mem access bug workaround

* kernel: unlock more tests

* kernel: switch to git version of parity-wasm

* kernel: use wasm module type exposed by validator

* kernel: set number of memory pages to 3

* kernel: panic on inability to parse wasm

* kernel: test simple procedure contract

* Switch to manual parsing for validation (#157)

* wasm-parser: remove parity-wasm dependency

* wasm-parser: proof of basic idea

* wasm-parser: import instruction mappings from parity-wasm

* wasm-parser: build and link with kernel

* wasm-parser: fix parsing of import entries

* wasm-parser: add missing file

* kernel: add test script

* wasm-parser: minor cleanup

* circleci: don't force rebuild of parity-ethereum

* kernel: update tests to be more accurate

* kernel: update nightly version for alloc crate

* circleci: fix error with parity installation

* circleci: fix error in previous commit

* wasm-parser: reinclude alloc

* wasm-parser: merge Cursor and CodeCursor

* circleci: add example contract 2

* circleci: set-up environment for test

* circleci: fix example_contract_2 build

* wasm-parser: properly validate instructions in syscall

* wasm-parser: fix import cursor progression

* circleci: remove config step from parity

* circleci: clear cache

* remove and gitignore build files

* validation: rustfmt and add tests

* wasm-parse: refactor

* wasm-parser: docs

* validation: forbid indirect calls

* validation: correct invalidation of bad dcall

* wasm-parser: minor cleanup

* kernel: skip unimplemented test

* wasm-parser: check for varuint32 issues

* wasm-parser: additional comments

* whitespace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests