Skip to content

WIP: Transpile sign extension proposal #375

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

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

maurobringolf
Copy link
Collaborator

@maurobringolf maurobringolf commented May 31, 2018

Here is what I've been working on:

  • New package that transpiles sign extension instructions back to functions with the (hopefully) same behavior.

  • The functions replacing the instructions are written in assemblyScript, compiled to wasm, parsed by wasm-parser and then injected into a given ast.

  • Only the necessary functions are inserted

The package is currently written as ast->ast transform and the tests are setup as text->text for readability. We can add another API using wasm-edit for binaries directly. I would like to have a test setup for functional correctness though and haven't really figured out how to do that yet.

@maurobringolf maurobringolf changed the title Transpile sign extension proposal WIP: Transpile sign extension proposal May 31, 2018
@ColinEberhardt
Copy link
Collaborator

Nice idea :-)

The use of Assembly Script to generated the function that polyfills does feel like overkill. The generated WAT is really quite simple:

  (func $main/i32_extend16_s (export "i32_extend16_s") (type $t2) (param $p0 i32) (result i32)
    get_local $p0
    i32.const 32768
    i32.and
    if $I0 (result i32)
      get_local $p0
      i32.const -32768
      i32.or
    else
      get_local $p0
      i32.const 32767
      i32.and
    end
    return)

I'd just use the above wat directly, parsing it into AST, then 'injecting' it as part of your polyfill transform.

@maurobringolf
Copy link
Collaborator Author

maurobringolf commented May 31, 2018

Thanks for the feedback! It might very well be overkill and caused some extra work in the build process. It simply represents the way I arrived at these (first in C, Sven suggested migrating to AssemblyScript). There might be one advantage though: I am looking for a way to test the functional correctness of the polyfill functions. One possibility would be to test the AssemblyScript source. Do you have an alternative suggestion for this kind of testing?

We could use the interpreter, but its probably not ready yet? Also much more errorprone I imagine

@ColinEberhardt
Copy link
Collaborator

I am looking for a way to test the functional correctness of the polyfill functions. One possibility would be to test the AssemblyScript source. Do you have an alternative suggestion for this kind of testing?

If you write these functions in WAT, I'd just unit test that via JS - e.g. unit test the $main/i32_extend16_s function I added in the comment above

"type": "Func",
"name": {
"type": "Identifier",
"value": "packages/proposal-sign-extension-ops/src/polyfills/i64_extend32_s/i64_extend32_s"
Copy link
Owner

Choose a reason for hiding this comment

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

do we need to commit the AST generated by the polyfill compilation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I was not sure how releases / packaging works. The proposal package directly loads the json ast to avoid unnecessary parsing. We could load and parse from WAT as suggested by Colin as an alternative

@xtuc
Copy link
Owner

xtuc commented May 31, 2018

We could use the interpreter, but its probably not ready yet? Also much more errorprone I imagine

How? It's not a C compiler.

Assembly Script to generated the function that polyfills does feel like overkill

I think it will be more maintainable

@maurobringolf
Copy link
Collaborator Author

@xtuc Its not a C compiler yet. Just kidding 😄 I meant that the interpreter could be used to run the polyfill wasm function to test functional correctness.

@ColinEberhardt
Copy link
Collaborator

Assembly Script to generated the function that polyfills does feel like overkill

I think it will be more maintainable

For complex polyfills I'd agree, but in this case it's a few lines of WAT. I like simple :-)

Also, how stable is AssemblyScript? If you encounter an error, can you be sure it is in your code? Or is it the AssemblyScript compiler? How optimised is the output?

Anyhow, this is not a strong objection, just my thoughts!

@xtuc
Copy link
Owner

xtuc commented May 31, 2018

Yeah I agree @ColinEberhardt. What do you think @maurobringolf?

Our interpreter is definitely not ready.

@maurobringolf
Copy link
Collaborator Author

Less things to maintain is fine with me 👍 It was a fun experiment. Would you make the wat->ast translation build-time or runtime?

@xtuc
Copy link
Owner

xtuc commented May 31, 2018

We could do it at publish-time but runtime seems easier for now.

@ColinEberhardt
Copy link
Collaborator

Yeah, I’d go runtime for simplicity. It’s a pretty simple transform and transforms aren’t really that performance critical

@maurobringolf maurobringolf force-pushed the transpile-sign-extension branch from e723e46 to 2c07ba0 Compare June 1, 2018 20:41
@maurobringolf
Copy link
Collaborator Author

maurobringolf commented Jun 1, 2018

Thanks for the feedback, I prefer text format as source for the polyfills now too. I also realized that the other approach would not work in the long run anyways: As soon as a feature becomes standard it wouldnt make sense to use a compiler anymore since it might output code that relies on the feature (instructions in this case) we're trying to polyfill in the first place.

  • Now .wast polyfills are loaded from source files and parsed with wast-parser
  • I added functional tests for both i32 polyfills by converting the wast source to wasm with wat2wasm from wabt and then running it as module in node directly.
  • Not sure what to do with i64

0xc1: createSymbolObject("extend16_s", "i32"),
0xc2: createSymbolObject("extend8_s", "i64"),
0xc3: createSymbolObject("extend16_s", "i64"),
0xc4: createSymbolObject("extend32_s", "i64"),
Copy link
Owner

Choose a reason for hiding this comment

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

Maybe we should change that to support two or more bytes? Atomic operations also have an additional byte.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Are you referring to the threads proposal? i.e. https://webassembly.github.io/threads/binary/instructions.html#atomic-memory-instructions. Then it shouldn't affect this proposal but something to look out for in the future I think?

Copy link
Owner

Choose a reason for hiding this comment

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

I already added a check for the atomic operations prefix byte. I just saying that we could move the logic here by matching an array of bytes?

@@ -0,0 +1,4 @@
(module
(func)
Copy link
Owner

Choose a reason for hiding this comment

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

I'm not sure this test is very useful

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah this was my test to check that the test setup works before having the transform. I dont think it is useless though, empty function body might trigger an edge case somewhere. But we might also remove it

@xtuc
Copy link
Owner

xtuc commented Jun 2, 2018

Not sure what to do with i64

Sorry, what do you mean

@maurobringolf
Copy link
Collaborator Author

@xtuc There is no functional test for i64 polyfills since we cannot call functions directly from JS.

@xtuc
Copy link
Owner

xtuc commented Jun 2, 2018

You can deactivate the check: https://github.com/xtuc/webassemblyjs/blob/master/packages/repl/src/index.js#L299-L307

We are testing i64 in the spectest via our REPL.

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.

3 participants