Initial implementation of "Memory64" proposal#3130
Conversation
|
As I mentioned, this contains a lot of fixes to test scripts and such, which aren't strictly part of Memory64 of course, but were required for me to get all this up and running on Windows. Some could be pulled out into a PR to be merged before this one (since I can't test this functionality without them), but would be simpler to just merge them here. |
|
Took a look at the emcc test error fwiw and found that it is happening at binaryen/test/binaryen.js/expressions.js Lines 492 to 494 in bcc6f29 indicating that calling |
|
@dcodeIO thanks so much for that insight! I did change |
|
Ok, changed the way |
sbc100
left a comment
There was a problem hiding this comment.
Surprisingly small change (tests aside)! Even makes some things simpler.
lgtm % comments
|
I remember that there has been the idea to refactor |
kripken
left a comment
There was a problem hiding this comment.
Nice work! Some initial comments here.
I think it would be worth splitting out the unrelated windows test improvements. I'd be fine with them all in one big "fix windows" PR.
|
Ok, non-Memory64 related changes have been split into a separate PR, please review that one first, as it is required for me to be able to test this one: #3142 |
|
Ok, rebased to not include the Windows/test changes, and most comments above resolved, please review. |
Why is the current memory or module not accessible from functions calling finalize? Where are these callers? |
|
@tlively |
|
That sounds fine to me. We will have to do something similar when we expose Poppy IR to the C/JS API because that changes block validation as well. Maybe we can introduce a |
|
Omg, CI beast has been slain! |
|
@aardappel can you push additional commits instead of force pushing? It makes it hard to figure out what has been changed from version to version. |
I know you are not talking to me here but as someone who uses a "rebase early and squash often" approach in all my repos I would find this request hard. I suppose I could still do what I want with my local branch and then every time I want to push a change to github I could just push the delta between what I have in my branch and what github currently has? i.e. have my work branch and the github branch be basically unrelated. I guess I could write a script for that. |
|
@tlively they are often very tiny formatting changes and what not, and make it harder for me to see locally what's all in a PR. |
|
Ok, I don't want to mess with your normal workflow too much. GitHub's "changes since last review" feature is great, but I wish it worked with with rebases. When I need to see everything that's in a PR I usually just do |
|
@tlively I use a local git tool (Fork). |
| value64 + offset64 <= uint64_t(std::numeric_limits<int32_t>::max())) { | ||
| last->value = Literal(int32_t(value64 + offset64)); | ||
| if (getModule()->memory.is64) { | ||
| last->value = Literal(int64_t(value64 + offset64)); |
There was a problem hiding this comment.
I think the danger is still relevant in memory64, if it wraps doesn't it trap? (what does the memory64 spec do there?)
There was a problem hiding this comment.
I believe we haven't decided on that yet, see: WebAssembly/memory64#3
I'd be happy to add any checks.. but for now doing the simplest thing seems fine to me.
There was a problem hiding this comment.
Oh, I didn't realize the state of the spec... sounds fine then, but maybe add a comment that this is in flux?
| bool is64; | ||
|
|
||
| public: | ||
| Builder(MixedArena& allocator) : allocator(allocator) {} |
There was a problem hiding this comment.
the first constructor looks dangerous, as it won't set is64. we should maybe remove that constructor entirely (separately from this PR). meanwhile, it would be good to at least check in makeConstPtr if we know the memory size.
There was a problem hiding this comment.
It now takes a module, and made sure all users of Builder always supply a valid module
|
|
||
| class Builder { | ||
| MixedArena& allocator; | ||
| bool is64; |
There was a problem hiding this comment.
I'd suggest storing a Module& here instead of is64. is64 duplicates info that might get stale, if we add a pass to convert from 64 to 32 or vice versa etc.
Or this could be a Module* defaulting to nullptr which would help with the issue from a few lines down.
There was a problem hiding this comment.
All callers have a valid module, so wasn't necessary to make it a *
There was a problem hiding this comment.
This is going to be inconsistent with Poppy IR, where individual functions rather than the module are the source of truth for the extra validation context. I would have preferred taking the risk of stale data. Most builders are not long-lived, anyhow, and most passes will not be changing the validation context in any way. I just uploaded #3144, but I would actually prefer to keep the allocator and use an is64 bool. @kripken, wdyt?
There was a problem hiding this comment.
I'm confused, why would Poppy IR change the relationship of functions to the module?
Anyhow it's late on Friday, let's discuss this in depth on Monday?
Also includes a lot of new spec tests that eventually need to go into the spec repo
kripken
left a comment
There was a problem hiding this comment.
Very nice!
I didn't go through each spec test manually. I figure we'll go through those carefully upstream anyhow. Also once we get fuzzing integration for wasm64 that should be a good check on them.
| Builder(MixedArena& allocator) : allocator(allocator) {} | ||
| Builder(Module& wasm) : allocator(wasm.allocator) {} | ||
| Builder(MixedArena& allocator, Module& wasm) | ||
| : allocator(allocator), wasm(wasm) {} |
There was a problem hiding this comment.
As a followup I think we can remove this constructor. The allocator should always be from the wasm, so there is no need to pass an allocator manually.
There was a problem hiding this comment.
I did see at least one use where it seemed that a single allocator was used for potentially processing multiple modules, and I didn't know how intentional that was, so I left it in.
| return ret; | ||
| } | ||
| Const* makeConstPtr(uint64_t val) { | ||
| return makeConst(Literal::makeFromUInt64(val, wasm.memory.indexType)); |
|
|
||
| Type ptrType = Type::i32; | ||
|
|
||
| void make64(); |
There was a problem hiding this comment.
In general we don't like adding methods to these classes, to keep them minimalistic. But I can't think of a better pattern, and these are rarely-used anyhow, so sgtm.
There was a problem hiding this comment.
I tried adding an argument to the constructor, but that didn't work with the alloc template, so did this instead to keep it simple.
Builders gained a `Module` field in WebAssembly#3130 because they now require extra context to properly finalize some Expressions. Since modules contain allocators, the old allocator field on the builder became redundant after that change. This PR removes the redundant allocator field.
Builders gained a `Module` field in #3130 because they now require extra context to properly finalize some Expressions. Since modules contain allocators, the old allocator field on the builder became redundant after that change. This PR removes the redundant allocator field.
Also includes a lot of new spec tests that eventually need to go into the spec repo.