Page MenuHomePhabricator

[WebAssembly] New-style command support

Authored by sunfish on Jun 11 2020, 1:48 PM.



This adds support for new-style command support. In this mode, all exports
are considered command entrypoints, and the linker inserts calls to
__wasm_call_ctors and __wasm_call_dtors for all such entrypoints.

This enables support for:

  • Command entrypoints taking arguments other than strings and return values other than int.
  • Multicall executables without requiring on the use of string-based command-line arguments.

This new behavior is disabled when the input has an explicit call to
__wasm_call_ctors, indicating code not expecting new-style command

This change does mean that wasm-ld no longer supports DCE-ing the
__wasm_call_ctors function when there are no calls to it. If there are no
calls to it, and there are ctors present, we assume it's wasm-ld's job to
insert the calls. This seems ok though, because if there are ctors present,
the program is expecting them to be called. This change affects the
init-fini-gc.ll test.

Diff Detail

Event Timeline

sunfish created this revision.Jun 11 2020, 1:48 PM
sunfish updated this revision to Diff 270386.Jun 12 2020, 7:06 AM

Use the return value of handleUndefined instead of doing a separate lookup, which avoids a redundant lookup and handles LazySymbols properly.

sunfish updated this revision to Diff 270412.Jun 12 2020, 8:38 AM

Run clang-format and fix lint warnings.

Interesting direction! I'm only skimmed it for now. Not strongly opposed to this direction although it makes me sad to see more codegen/magic in the linker.


Can we make this a separate change? Its seems pretty distinct.


Is this just a de-duplication with the code below? It is related to this change to independent?


Can you replace these 2 lines with WasmSym::callCtors->isExported() ?

sunfish updated this revision to Diff 270489.Jun 12 2020, 12:21 PM
  • Address review feedback
  • Mark callCtors live in the MarkLive pass rather than in the Writer pass.
sunfish marked 6 inline comments as done.Jun 12 2020, 12:48 PM
sunfish added inline comments.

Ok, I've removed it, and I'll submit it in a separate patch.


I guess it is deduplication and possibly separable, but it's closely related to the rest of the patch.

Previously, when the input didn't have a __wasm_call_ctors call, we'd treat the init functions as dead code and delete them. With this patch, when the input doesn't have a __wasm_call_ctors call, we assume it's wasm-ld's job to insert __wasm_call_ctors calls. So it no longer makes sense to say "if __wasm_call_ctors is live then the init functions are live". The init functions are now just always live.



sbc100 added inline comments.Jun 26 2020, 4:45 PM
5 ↗(On Diff #270489)

no-tors.ll -> no-ctors.ll?

Also, I've been converting existing tests over to the .s format. For an example of this see ctor_return_value.s. If possible, I'd prefer to add .s tests only going forward .

2 ↗(On Diff #270489)

Ditto .s if possible.


I guess we should rename this test...?


Why this?


What do we actually want to test for here?


config->isPic is already checked at the call site.

Description needs updating after --emscripten was split out.

sbc100 added inline comments.Jun 26 2020, 5:02 PM

The comment say *or* but the code says "&&".

Can this part just be reverted? Since callCtors should not be live unless its needed.

sunfish updated this revision to Diff 282304.Jul 31 2020, 1:27 PM
sunfish marked 9 inline comments as done.

Address review feedback.

5 ↗(On Diff #270489)

no-tors.ll has no ctors *or* dtors. I've now converted these to .s tests.




That's how __cxa_atexit will typically be defined. And we don't want it being exported to prevent GC, which might defeat the purpose of the test.


I've now added comments to these CHECK lines.


I've now changed it to an assert.

Friendly ping!

sbc100 accepted this revision.Sep 30 2020, 5:17 PM

The description needs updating to reflect the fact that this change no longer adds the --emscripten flag.


You can remove the .section directives for all functions I believe to make the tests most concise.


And these explicit .type entries for functions. (the .functype on its own below I think is enough).


And these two lines can go too.


No need for __dso_handle here or above.

This revision is now accepted and ready to land.Sep 30 2020, 5:17 PM
sunfish edited the summary of this revision. (Show Details)Sep 30 2020, 5:19 PM
sunfish closed this revision.Sep 30 2020, 7:06 PM

Thanks! Description updated, fixes applied, and landed in

realuptime added a subscriber: realuptime.EditedFeb 20 2022, 12:51 AM

Hey, this new behaviour broke existing functionality!

I can still see this a workaround by making a call to __wasm_call_ctors.
Be sure that people are notified when such functionality change!

Calling by default C++ static constructors and functions (static int x = somefunc()) for each "export" entry point is a very very bad idea!!!
I had to compile with -fno-c++-static-destructors first and then refactor my code.
Or use no_destroy flag(
For example, on the project that I am working on I am calling a function(export.NeedsDisplay()) for each rendered frame, which could be 1000 times per second without VSYNC!

The project:

Here is my GitHub issue, which is closed now after spending two days finding the cause!