Use Binaryen StackIR at the end of the pipeline (#22218)

Before this PR, if we did -O3 then we ended up doing this:

* wasm-opt -O3
* wasm-metadce
* wasm-opt --minify-imports-and-exports

The first invocation uses StackIR (which is enabled by default in -O3), but then the
later invocations "lose" those optimizations, since they read the wasm binary and
generate structured BinaryenIR once more. We would need to do StackIR opts again,
but even more, we'd need to do work to undo the effects of stackiness, which can
lead to more locals and such, see #22196

After this PR, we do this:

* wasm-opt -O3 --no-stack-ir
* wasm-metadce
* wasm-opt --minify-imports-and-exports --optimize-stack-ir

The first command is now told to not use StackIR. The second remains unchanged.
The last then does StackIR optimizations.

This is the same amount of work (we just shuffle around the StackIR opts), so
compile times are unaffected, but we gain some code improvements. To see them,
see the commit before last which applies the size changes on top of a recent rebase.
Many tests improve by small but noticeable amounts, though two wasm2js tests
somehow lose by a few bytes, which I think is noise.

There is a slight code complexity downside here, but given this avoids corner
cases that may be quite annoying (#22196) it seems worthwhile.

Also improve our handling of --emit-symbol-map to use llvm-objcopy, which avoids
wasm-opt roundtrip issues (this is necessary in this commit as otherwise the
improvements of this PR are undone by that roundtrip, which was caught by a test).
23 files changed
tree: d998a83955ae4ec2a3732eb18cc5c54fcfa78693
  1. .circleci/
  2. .github/
  3. cmake/
  4. docs/
  5. media/
  6. site/
  7. src/
  8. system/
  9. test/
  10. third_party/
  11. tools/
  12. .clang-format
  13. .coveragerc
  14. .editorconfig
  15. .eslintrc.yml
  16. .flake8
  17. .git-blame-ignore-revs
  18. .gitattributes
  19. .gitignore
  20. .gitmodules
  21. .mypy.ini
  22. .prettierrc.yml
  23. .style.yapf
  24. AUTHORS
  25. bootstrap
  26. bootstrap.bat
  27. bootstrap.py
  28. ChangeLog.md
  29. CONTRIBUTING.md
  30. em++
  31. em++.bat
  32. em++.py
  33. em-config
  34. em-config.bat
  35. em-config.py
  36. emar
  37. emar.bat
  38. emar.py
  39. embuilder
  40. embuilder.bat
  41. embuilder.py
  42. emcc
  43. emcc.bat
  44. emcc.py
  45. emcmake
  46. emcmake.bat
  47. emcmake.py
  48. emconfigure
  49. emconfigure.bat
  50. emconfigure.py
  51. emdump
  52. emdump.bat
  53. emdwp
  54. emdwp.bat
  55. emmake
  56. emmake.bat
  57. emmake.py
  58. emnm
  59. emnm.bat
  60. emprofile
  61. emprofile.bat
  62. emranlib
  63. emranlib.bat
  64. emranlib.py
  65. emrun
  66. emrun.bat
  67. emrun.py
  68. emscons
  69. emscons.bat
  70. emscons.py
  71. emscripten-version.txt
  72. emsize
  73. emsize.bat
  74. emsize.py
  75. emstrip
  76. emstrip.bat
  77. emstrip.py
  78. emsymbolizer
  79. emsymbolizer.bat
  80. emsymbolizer.py
  81. LICENSE
  82. Makefile
  83. package-lock.json
  84. package.json
  85. README.md
  86. requirements-dev.txt
  87. SECURITY.md
README.md

emscripten logo

Main project page: https://emscripten.org

GitHub CI status: CircleCI

Chromium builder status: emscripten-releases

Overview

Emscripten compiles C and C++ to WebAssembly using LLVM and Binaryen. Emscripten output can run on the Web, in Node.js, and in wasm runtimes.

Emscripten provides Web support for popular portable APIs such as OpenGL and SDL2, allowing complex graphical native applications to be ported, such as the Unity game engine and Google Earth. It can probably port your codebase, too!

While Emscripten mostly focuses on compiling C and C++ using Clang, it can be integrated with other LLVM-using compilers (for example, Rust has Emscripten integration, with the wasm32-unknown-emscripten and asmjs-unknown-emscripten targets).

License

Emscripten is available under 2 licenses, the MIT license and the University of Illinois/NCSA Open Source License.

Both are permissive open source licenses, with little if any practical difference between them.

The reason for offering both is that (1) the MIT license is well-known and suitable for a compiler toolchain, while (2) LLVM‘s original license, the University of Illinois/NCSA Open Source License, was also offered to allow Emscripten’s code to be integrated upstream into LLVM. The second reason became less important after Emscripten switched to the LLVM wasm backend, at which point there isn't any code we expect to move back and forth between the projects; also, LLVM relicensed to Apache 2.0 + exceptions meanwhile. In practice you can just consider Emscripten as MIT licensed (which allows you to do pretty much anything you want with a compiler, including commercial and non-commercial use).

See LICENSE for the full content of the licenses.