Skip to content

Add an option to support big-endian machines #12387

Open

Description

@miladfarca

Hello,

It seems like Big Endian machines are not able to use emscripten, as assertions are added in this commit:
f178541

Runtime error: expected the system to be little-endian!

I understand that there are problems when it comes to "Typed Arrays" in Javascript since they are endianness dependent,
however, WebAssembly is little endian enforced. Runtime compilers such as Google V8 are compatible with running wasm (LE) binary code on BE machines.

Is the above assertion for endianness only done when generating regular js code (such as asm.js) or it
also checks when compiling to WebAssembly? In the case of wasm, would it be possible to continue with LE compilation even on BE machines? (I'm assuming assertions are only done during compilation to JS or to WASM and emscripten isn't concerned with how the generated output gets executed?).

Activity

  1. miladfarca commented on Oct 1, 2020

    @miladfarca
    ContributorAuthor

    Hi @kripken, would you have any suggestions on this issue?

  2. kripken commented on Oct 1, 2020

    @kripken
    Member

    Yes, it is a little odd that typed arrays use the system endianness, while wasm Memories are always little endian.

    This is an issue for all emscripten output, because it is a combination of wasm (for compiled code) and JS (to access Web APIs). The JS will use a typed array view to read from memory in a fast way (for example compiled C can call an OpenGL API, and the JS side will read data to send to WebGL). On a big endian machine that may not be correct, hence we have that assertion.

    In principle we could add a mode in which we rewrite all memory access from JS to use DataView. We haven't had a request for this yet. Do you have a use case that needs it?

  3. miladfarca commented on Oct 1, 2020

    @miladfarca
    ContributorAuthor

    Thanks for the info, yes an issue has come up when using eslint-plugin-jest , yarn v2 uses emscripten and this error is generated down the road:
    nodejs/citgm#824

    So to clarify, it's not possible to always continue with LE ordering when compiling to wasm and only assert when compiling to JS?

  4. kripken commented on Oct 1, 2020

    @kripken
    Member

    @miladfarca Correct. Any time there is any JS - and there is by default, as wasm can't access Web APIs itself - then this is an issue.

    The only solutions are either

    1. Use standalone mode (no JS, or you write the JS yourself - not recommended if you use any non-trivial amount of JS APIs from the wasm), or
    2. Add support for big endian code in emscripten, using DataView.

    Option 2 wouldn't be a large amount of work. Is this important for your project?

  5. miladfarca commented on Oct 1, 2020

    @miladfarca
    ContributorAuthor

    @kripken Thanks for clarifying. It's not a specific project we are trying to support, rather we are trying to support BE architectures in general. Nodejs and V8 support big endian platforms and we are seeing endianness problems with modules similar to eslint-plugin-jest.

    In terms of adding support using DataView, is this something we could contribute or emscripten would be able to add the changes and we can test it on BE machines?

  6. bvibber commented on Oct 1, 2020

    @bvibber
    Collaborator

    I think some web APIs like WebGL in particular would be more difficult as they'd have to convert data back and forth, knowing which buffers contain what kind of data. However this may be moot, if BE arches are mostly a mainframe/server thing that run node, not browsers.

  7. miladfarca commented on Oct 1, 2020

    @miladfarca
    ContributorAuthor

    @Brion correct, at this point we are only concerned with Node.js and server related processes and as you mentioned WebGL should not be an issue.

  8. kripken commented on Oct 2, 2020

    @kripken
    Member

    In terms of adding support using DataView, is this something we could contribute or emscripten would be able to add the changes and we can test it on BE machines?

    A contribution would be great! It shouldn't be too hard I think. The key thing would be to write a transformation pass on the acorn AST, see for example the growableHeap pass. That pass changes each HEAP8 etc. usage into a function call. For this, I think we'd want to do

    HEAP16[..]  =>  dataView.getInt16(.., endianness)

    and similar for sets. (The safeHeap pass may also be interesting as it does something very close, but it hasn't been converted to acorn yet.) dataView would need to be created and updated whenever we create/update the HEAP views. And during startup we'd need to detect the endianness. I think that's all of it (well, plus adding an option for this, and a test).

    @Brion WebGL would indeed be an issue, yeah. That would come up specifically when doing HEAP*.subarray operations, I think. It's possible we could fix those up just like individual reads. That seems doable, assuming WebGL never receives an Int8Array that it then reads from as a Float32Array, or any other such type mismatch, which I'm not sure of offhand... I think there are packed data structures with multiple types?

  9. kripken commented on Oct 6, 2020

    @kripken
    Member

    Btw, there is a PR up to write SAFE_HEAP using acorn. That replaces HEAP8 etc. usage with a call to a SAFE_HEAP function. An endianness fixup could do something similar (then implement the fixup functions that swap endianness) so that code may be helpful to look at for anyone interested to implement this, #12450

  10. changed the title [-]Clarifying endianness dependency of emscripten[/-] [+]Add an option to support big-endian machines[/+] on Oct 6, 2020
  11. miladfarca commented on Nov 15, 2020

    @miladfarca
    ContributorAuthor

    @kripken I've created this PR #12780 as a start so we can discuss possible ways to support BE machines. In this case i'm redirecting all the HEAP get/sets with a proxy and using Data Views to do the actual reading and wiring.

    I made a simple hello world in C and compiled it in a LE machine with emcc, moved both a.out.wasm and a.out.js to a BE machine and the output is now showing properly. (It was just printing empty lines before this PR, when LE check was commented out).

    Note that we still cannot compile with emcc on a BE machine as we get this error:

     Exception message: "SyntaxError: Unexpected token -" | SyntaxError: Unexpected token -
    

    Once runtime is fixed we can fix the BE compilation after.

  12. miladfarca commented on Mar 15, 2021

    @miladfarca
    ContributorAuthor

    Initial PR to add BE support has landed: #13413

  13. 10 remaining items

  14. bvibber commented on Aug 8, 2024

    @bvibber
    Collaborator

    Looks like the current big-endian mode already wraps the DataView accessors in functions which are called as replacements for sets/loads into the HEAP arrays, eg $LE_HEAP_STORE_U16 and friends. These ought to minify fairly well in the resulting JS, with some runtime overhead from the function calls versus the current default array accessors. Might be worth running some standard benchmarks with big-endian-friendly builds and double-check the resulting .js sizes (raw and gzipped) and if any effect on runtime is visible.

  15. sbc100 commented on Aug 8, 2024

    @sbc100
    Collaborator

    @bvibber I curious what LE platforms you are interested in targeting?

  16. sbc100 commented on Aug 8, 2024

    @sbc100
    Collaborator

    Given that we now have SUPPORT_BIG_ENDIAN=1 maybe we can close this issue and open a new one to discuses the possibility of making the default?

  17. bvibber commented on Aug 8, 2024

    @bvibber
    Collaborator

    LE platforms is Windows, mac, iOS, Android x86_64, arm64, and I guess anything else. BE is only s390/Linux node AFAIK.

  18. bvibber commented on Aug 8, 2024

    @bvibber
    Collaborator

    (IMHO a better fix is to re-spec TypedArrays to be always little-endian, fix V8's s390 output for that, and probably fix a billion other bugs in things using typed arrays and/or wasm in node libraries.)

    But that's obviously out of scope for emscripten.

  19. sbc100 commented on Aug 8, 2024

    @sbc100
    Collaborator

    Are you looking to run your emscripten modules on s390/Linux? Do chrome or firefox even run there?

  20. bvibber commented on Aug 8, 2024

    @bvibber
    Collaborator

    All I care about is things running in node. I assume there are no browsers on s390/Linux in practice.

  21. bvibber commented on Aug 8, 2024

    @bvibber
    Collaborator

    Also I have no particular investment in s390 nor any software I require running there, I simply wish the tooling I work with to be correct whereever it's run.

  22. sbc100 commented on Aug 8, 2024

    @sbc100
    Collaborator

    Also I have no particular investment in s390 nor any software I require running there, I simply wish the tooling I work with to be correct whereever it's run.

    So this is really a hypothetical requirement (at least from your POV @bvibber). You don't have have an s390 machine that you want to run your modules on, nor any specific users asking for this?

    I'm not saying that means we should not invest all in this effort, just trying to get an idea of where the demand for it is coming from.

  23. bvibber commented on Aug 8, 2024

    @bvibber
    Collaborator

    Correct; my primary concern is with the difficulty of debugging for downstream users of libraries using wasm components in them, as a person who sometimes creates such libraries and wants to make peoples' lives easier if the case comes up later.

    I don't think there's a lot of specific demand for big-endian in production, but some folks are aware that s390/linux exists, and has node available on it, and in case anybody's libraries end up getting used on one of those machines they should either work or fail gracefully, at a minimum. :)

    Since the build-time support option is already in there, as long as we have a clean fail-out if you try to instantiate a module on a big-endian host I'm happy with that.

    If there's interest in doing the work to push forward a clean, no-regressions "works everywhere" default build, that can live on a separate issue I think.

  24. juru1234 commented on Aug 8, 2024

    @juru1234

    I'm a Linux on s390x developer and yes, at least a graceful fail would have helped me a lot when I ran into this issue with bash-language-server :)

  25. sbc100 commented on Aug 8, 2024

    @sbc100
    Collaborator

    So we do have the Runtime error: expected the system to be little-endian! message, but that would only appear in debug builds (or builds with -sASSERTIONS enabled).

    @juru1234 I assume you are asking for this message to also appear in release builds? In general we try to avoid that kind of thing, since even the text of the message itself ends up adding code side to all builds. In this case we could perhaps gate the inclusion on node support, since those building modules for the web who care about code size will already be removing the node support.

  26. sbc100 commented on Aug 10, 2024

    @sbc100
    Collaborator

    If somebody wants to send a PR to add this error message, even in release builds (but only when node support is enabled) that would great.

  27. kripken commented on Aug 14, 2024

    @kripken
    Member

    @bvibber Thanks for running those benchmarks!

    I did some size comparisons. On a typical benchmark in our benchmark suite (e.g. zlib) the JS gets 5% larger with big-endian support. I also see similar things when compiling WebGL testcases. So this is not a huge increase, but I think that's big enough that we wouldn't want it to be the default.

    @sbc100 Interesting idea to improve the error message only in builds targeting non-Web. I would be ok with that.

  28. bvibber commented on Aug 16, 2024

    @bvibber
    Collaborator

    I'll see if I can whip up a quick warning patch that at least dumps a warning to console on non-debug non-big-endian build if run on big endian :D It will have a small but constant size cost, since it won't bloat the actual load/store sites.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions