Skip to content
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

Enabling features by default in LLVM #158

Closed
tlively opened this issue Dec 21, 2020 · 46 comments
Closed

Enabling features by default in LLVM #158

tlively opened this issue Dec 21, 2020 · 46 comments

Comments

@tlively
Copy link
Member

tlively commented Dec 21, 2020

I know we discussed this a while ago, but I forget what exactly we came up with @aheejin @dschuff @sbc100 @sunfishcode. IIRC, it wasn't too different from enabling new features once the following two conditions are satisfied:

  • The feature has been in phase 4 for six months.
  • All major browsers have shipped it.

Am I remembering that correctly? (I couldn't find this discussion in our notes). Should there be a time delay on the second condition as well? I'm thinking about this because multivalue and mutable globals might be eligible to be turned on by default. If so, it would be nice to get that in before LLVM 12 is cut.

@sbc100
Copy link
Member

sbc100 commented Dec 22, 2020

Thanks for reviving this issue. I seem to remember it was something I meant to do a while back.

Aside from the issue of what to do when in LLVM, did we agree that binaryen and emscripten should be in sync with LLVM (i.e. was there any reason not to have them all be in sync?)

@tlively
Copy link
Member Author

tlively commented Dec 22, 2020

I don't remember having discussed what to do with other tools, but IMO having them match LLVM seems reasonable.

@aardappel
Copy link

Same with WABT. You don't really want these tools to error on every LLVM generated binary because --enable-* was omitted.

@tlively
Copy link
Member Author

tlively commented Dec 22, 2020

For Binaryen this generally wouldn't be an issue because it reads the target features section by default. I assume WABT is more frequently used with binaries that have had their target features section stripped, though.

@sbc100
Copy link
Member

sbc100 commented Dec 22, 2020

Yeah I think it makes sense for all tools to stay in sync. They should all probably strive for an --mvp mode that can be set on the command line for folks that don't like progress.

@AlexEne
Copy link

AlexEne commented Mar 11, 2021

Is this criteria decided? As someone who works in non-web browser wasm32-wasi scenarios, making this tied to browser release cycle makes it different from all other rustc targets and at a pace where it's not ideal for anything other than web.

The feature has been in phase 4 for six months.
All major browsers have shipped it.

What's the mechanism to decide this as doing things in this way hurts places like IOT, or others where HOST programs cannot be updated due to various reasons at the same pace. This essentially locks application writers that target wasm to run on those host programs to a particular rust version (as WASM and WASI evolve). In the case of wasi, this may be alleviated by having stdlibs independent of rustc releases (not possible today tho).

E.g. if we could use the latest rust with a stdlib from 3 versions ago, then the addition of new wasi capabilities for wasm32-wasi targets won't really affect this type of use-cases.

This also goes towards a more philosophical discussion of what does it mean to have targets in stable rust and what guarantees those build targets are going to be held against but this is probably not the right forum to discuss it I think.

@sbc100
Copy link
Member

sbc100 commented Mar 11, 2021

Presumably rust, like any other toolchain, will need some way to disable certainly features at compile time if they hope to target older/legacy runtimes? If not, then its output would only be use-able on platforms that support the same set of defaults (i.e. no legacy targets).

Another option for toolchains (other than allowing feature selection on the command line) is to use a tool like binaryen to remove the use of certain features, post link. This would allow the compiler itself to be less configurable, and delay feature selection until a late phase. (Obviously this only works for features that can be polyfilled or re-written away)

@AlexEne
Copy link

AlexEne commented Mar 12, 2021

I like the disable feature for defaults that break backwards compatibility. E.g. Threads won't break anything as now for example rust panics whenever you try to instantiate a thread, so having it panic because it can't find some functionality after threads are moved into the default feature set doesn't really qualify as breaking.

But in the case they are breaking, we could add flags to disable those once they move into the default set of features. The case i'm describing isn't the majority so adding some flags to remove breaking stuff makes sense

@sbc100
Copy link
Member

sbc100 commented Mar 12, 2021

As well is individual features tools can/should probably provide an --mvp flag of some find to remove all non-mvp features. I believe binaryen, wabt and llvm already support this.

@sunfishcode
Copy link
Member

The proposed wording at the top of this issue talks about browsers, which doesn't address major non-Web engines. And even among browsers, there are different versions. And the idea of documenting a 6-month waiting period feels too rigid. Some features have taken engines longer to implement. Others were implemented before reaching stage 4.

Even if we wrote words to pin these things down more, for the foreseeable future I expect we'd still end up adding an informal decision-making on top for each feature anyway. So I've now added a comment to this proposed LLVM patch which just says:

+// This includes features that have achieved phase 4 of the standards process,
+// and that are expected to work for most users in the current time, with
+// consideration given to available support in relevant engines and tools, and
+// the importance of the features.

@kripken
Copy link
Member

kripken commented Oct 18, 2022

I agree some amount of informal reasoning is necessary.

But I do hope we can do that in a cross-ecosystem way, that is, avoid differences between toolchains. In some sense maybe it's ok if say Emscripten is web-focused and makes choices based on browsers, and WASI-libc is server-focused and chooses based on server VMs, and maybe those choices end up different sometimes. But if it would be possible to make a single set of decisions across the entire ecosystem I think that simplicity would have benefits.

@sunfishcode
Copy link
Member

@kripken Do you have a concern about the wording of the comment above, or about the selection of proposed features in the patch: bulk-memory, mutable-globals, nontrapping-fptoint, and sign-ext?

@kripken
Copy link
Member

kripken commented Oct 18, 2022

The wording seems ok to me. About the selection, I'd be happiest if we knew we were also going to enable those precise features in Emscripten shortly. I'm not sure of current plans there (@sbc100 @dschuff ?).

But I guess my larger suggestion is, it might be nice if we decided at the level of the entire ecosystem on the set of features rather than doing so in separate toolchains. I don't feel terribly strongly, though - I think that would have benefits, but minor, so if it slows progress maybe it's not worth it.

@dschuff
Copy link
Member

dschuff commented Oct 18, 2022

In terms of switching emscripten defaults, we need to decide when we're ready to break users on old devices with the default build, and finish getting the tools and/or documentation in place to help developers target them.

For the first question, the long pole on the web is nontrapping and bulk memory, shipped in Safari/iOS 15, which Apple says is on about 90% of phones and 80% of tablets released in the last 4 years.
If we don't like those numbers, we could just enable mutable-gobals and signext as they have been out for longer. Of those I might guess that nontrapping-fptoint would be the most valuable because of the extra blocks we have to insert to implement LLVM IR's version of FP to int conversion.

Then we need to decide whether we want to expand the use of the -s MIN_SAFARI_VERSION etc flags at compile time, or lower features away at link time with Binaryen as mentioned above, or just have a doc that says "if you want to target Safari 15, use the following feature flags".

Regarding the ecosystem I think it would be nice to all move together too, and if we can get get this first step coordinated we'd at least have done the easy first step. It wouldn't necessarily surprise me if there were some SDK in the future that went their own way; that was basically the sentiment expressed above that people might not want to wait on Safari to implement something to enable a feature in some completely unrelated embedding. But if we coordinate LLVM itself, at lease we're applying a nudge in that direction.

@sunfishcode
Copy link
Member

I've now updated D125729 to remove bulk-memory and nontrapping-fptoint. Does anyone have any objections to the patch now?

@kripken
Copy link
Member

kripken commented Oct 19, 2022

sgtm. It does seem safer to not enable features by default that won't work on almost 20% of a major platform like iPhone, since it says only 82% of all iPhones are at 15. (I don't see a reason to focus on just those released in the last 4 years @dschuff ?)

Also just 72% of iPads, which is a smaller market, but still that's almost 30%.

I guess iOS ties major Safari updates to OS updates? Especially unfortunate as apps can't ship their own browser engines.

@fgmccabe
Copy link

Technically, on ios & mac, safari updates are not always connected to os upgrades.

@kripken
Copy link
Member

kripken commented Oct 19, 2022

@fgmccabe Major versions, or security updates? (I did some searching and can't find a clear answer, but I'm not an Apple user so maybe I don't know the right terms.)

@fgmccabe
Copy link

Definitely both. It's a mostly transparent process on ios: apps are 'just updated' every so often, whenever the developer releases a new version. This appears similar to how chrome is updated in the background too.

@sbc100
Copy link
Member

sbc100 commented Oct 19, 2022

@fgmccabe, that seems to contradict the information that apple supplies on how to update safari: https://support.apple.com/en-us/HT204416: "If a Safari update is available, you can get it by following the steps to update or upgrade macOS, iOS, or iPadOS."
I'm not an iOS user so don't have first hand information, but are you sure? Where are you getting your information about this from?

@fgmccabe
Copy link

Well, I have seen those message too. I have also experienced it being upgraded without (esp on ios). But, my experience is stricly anecdotal.

@jryans
Copy link

jryans commented Oct 19, 2022

On macOS, it's definitely possible (at least in recent times) to update just Safari alone (though not always to the latest Safari version if your version of macOS is old enough that support has been dropped). For example, if I'm on macOS major version N - 1 (where N is the latest), sometimes the latest Safari is available as a standalone update. The Safari version history on Wikipedia shows that each release is available for multiple macOS versions:

image

On iOS, as far as I've seen over the last ~5 years at least, Safari is always tied to the overall iOS system version. I have iOS app auto-updates disabled and review each app updates manually before installing them. I do not recall seeing a Safari standalone update on iOS. Once again, the Safari version history on Wikipedia supports this by showing each Safari is connected to an iOS version:

image

So to summarise, AFAIK only macOS allows installing Safari separately from the overall OS version. In recent times, only the previous 1 or 2 macOS versions have been supported by the latest version of Safari.

@fgmccabe, that seems to contradict the information that apple supplies on how to update safari: support.apple.com/en-us/HT204416: "If a Safari update is available, you can get it by following the steps to update or upgrade macOS, iOS, or iPadOS."

That wording doesn't really help with this particular question because (at least on macOS where I have seen standalone Safari updates before), they are delivered through the same settings UI flow for upgrading the overall system version. You have to manually choose to install only the Safari update and not the latest macOS (they appear as separate line items that can each be unchecked).

@sunfishcode
Copy link
Member

As an update here, D125729 updating LLVM to enable mutable-globals and signext has now landed.

@fornwall
Copy link

fornwall commented Dec 6, 2023

multivalue and mutable globals might be eligible to be turned on by default. If so, it would be nice to get that in before LLVM 12 is cut

While this didn't happen, what about enabling multi-value by default in LLVM 18 or 19 (can look into a PR if this might be a good idea)? Considering the guideline that was added in D125729 about what to enable by default, implementation support as well as the utility value (see for instance this comment):

// This includes features that have achieved phase 4 of the standards process,
// and that are expected to work for most users in the current time, with
// consideration given to available support in relevant engines and tools, and
// the importance of the features.

@glandium
Copy link

@aheejin here you go:
repro.zip

Unpack and run wasm-ld @response.txt.

@aheejin
Copy link
Member

aheejin commented Jul 2, 2024

@aheejin here you go: repro.zip

Unpack and run wasm-ld @response.txt.

The command in response.txt has --import-table, and builds/worker/fetches/sysroot-wasm32-wasi/lib/wasm32-wasi/crt1-command.o imports __indirect_function_table:

 (import "env" "__indirect_function_table" (table $timport$0 0 funcref))

llvm-nm lists the symbol as undefined (as expected, because it is to be imported):

$ llvm-nm builds/worker/fetches/sysroot-wasm32-wasi/lib/wasm32-wasi/crt1-command.o
         U __indirect_function_table
         ...

It looks this causes an error, but I'm not very familiar with why this works in this way. @sbc100 Any ideas?

@sbc100
Copy link
Member

sbc100 commented Jul 2, 2024

Looks like that could be a bug in wasm-ld yes.

@glandium to be clear its not the building of wasi-sdk that fails here but you usage of the SDK once its built, right?

Out of interest, is there some reason why you need to build with --import-memory and --import-table?

@glandium
Copy link

glandium commented Jul 2, 2024

@glandium to be clear its not the building of wasi-sdk that fails here but you usage of the SDK once its built, right?

Yes

Out of interest, is there some reason why you need to build with --import-memory and --import-table?

The wasm is translated to C afterwards via wasm2c for consumption by rlbox (https://github.com/PLSysSec/rlbox_wasm2c_sandbox). I'm not sure exactly why these flags are used, specifically, but @shravanrn should know.

@shravanrn
Copy link

shravanrn commented Jul 2, 2024

@sbc100 RLBox uses both import-memory and import-table because of the following high level constraints

  • the wasm host/embedder has specific alignment and size requirements on memory allocated for a wasm instance's linear memory, hence the memory is created by the host and imported by the module

  • the wasm host/embedder needs to dynamically make some of it's functions callable by the wasm instance. This can be done by inserting these functions as entries to the wasm instance's indirect function table. For this, we make the host responsible for creating (and updating) the table and simply import the table from the wasm instance

I can offer more concrete/specific examples if needed.

@glandium
Copy link

glandium commented Jul 2, 2024

@aheejin here you go: repro.zip
Unpack and run wasm-ld @response.txt.

The command in response.txt has --import-table, and builds/worker/fetches/sysroot-wasm32-wasi/lib/wasm32-wasi/crt1-command.o imports __indirect_function_table:

 (import "env" "__indirect_function_table" (table $timport$0 0 funcref))

llvm-nm lists the symbol as undefined (as expected, because it is to be imported):

$ llvm-nm builds/worker/fetches/sysroot-wasm32-wasi/lib/wasm32-wasi/crt1-command.o
         U __indirect_function_table
         ...

It looks this causes an error, but I'm not very familiar with why this works in this way. @sbc100 Any ideas?

Note that the symbol is also similarly undefined in most if not all the other files in the archive, but that doesn't cause a problem. Only the one in crt1-command.o does. As in, if you get rid of the one in crt1-command.o somehow, then it links fine.

@sbc100
Copy link
Member

sbc100 commented Jul 2, 2024

Note that the symbol is also similarly undefined in most if not all the other files in the archive, but that doesn't cause a problem. Only the one in crt1-command.o does. As in, if you get rid of the one in crt1-command.o somehow, then it links fine.

Indeed, this looks like a wasm-ld a bug. I will look into it.

sbc100 added a commit to sbc100/llvm-project that referenced this issue Jul 2, 2024
…d symbols

When an undefined symbol is referenced from more than one file we were
reporting all undefined symbols as originating from just one of them.

This came up while working on WebAssembly/tool-conventions#158
where undefined symbols in one object file were being reported as
coming from another.
@sbc100
Copy link
Member

sbc100 commented Jul 2, 2024

It looks like there are actually two bugs here. The first one was mis-reporting the source of the undefined symbols references. They are actually coming from __stdio_exit.o. I'm fixes that first issue in llvm/llvm-project#97444.

sbc100 added a commit to sbc100/llvm-project that referenced this issue Jul 2, 2024
…d symbols

When an undefined symbol is referenced from more than one file we were
reporting all undefined symbols as originating from just one of them.

This came up while working on WebAssembly/tool-conventions#158
where undefined symbols in one object file were being reported as
coming from another.
sbc100 added a commit to sbc100/llvm-project that referenced this issue Jul 2, 2024
…e types

When reference types are enabled clang will generate call_indirect
instructions that explicitly reference the global
`__indirect_function_table` symbol.

In this case the resulting global symbol was not being correctly marked
with explicit import name/module, resulting in the linker reporting
errors when it was referenced.

This issue was reported in WebAssembly/tool-conventions#158
sbc100 added a commit to llvm/llvm-project that referenced this issue Jul 2, 2024
…e types (#97451)

When reference types are enabled clang will generate call_indirect
instructions that explicitly reference the global
`__indirect_function_table` symbol.

In this case the resulting global symbol was not being correctly marked
with explicit import name/module, resulting in the linker reporting
errors when it was referenced.

This issue was reported in
WebAssembly/tool-conventions#158
sbc100 added a commit to llvm/llvm-project that referenced this issue Jul 2, 2024
…d symbols (#97444)

When an undefined symbol is referenced from more than one file we were
reporting all undefined symbols as originating from just one of them.

This came up while working on
WebAssembly/tool-conventions#158 where
undefined symbols in one object file were being reported as coming from
another.
lravenclaw pushed a commit to lravenclaw/llvm-project that referenced this issue Jul 3, 2024
…e types (llvm#97451)

When reference types are enabled clang will generate call_indirect
instructions that explicitly reference the global
`__indirect_function_table` symbol.

In this case the resulting global symbol was not being correctly marked
with explicit import name/module, resulting in the linker reporting
errors when it was referenced.

This issue was reported in
WebAssembly/tool-conventions#158
lravenclaw pushed a commit to lravenclaw/llvm-project that referenced this issue Jul 3, 2024
…d symbols (llvm#97444)

When an undefined symbol is referenced from more than one file we were
reporting all undefined symbols as originating from just one of them.

This came up while working on
WebAssembly/tool-conventions#158 where
undefined symbols in one object file were being reported as coming from
another.
kbluck pushed a commit to kbluck/llvm-project that referenced this issue Jul 6, 2024
…e types (llvm#97451)

When reference types are enabled clang will generate call_indirect
instructions that explicitly reference the global
`__indirect_function_table` symbol.

In this case the resulting global symbol was not being correctly marked
with explicit import name/module, resulting in the linker reporting
errors when it was referenced.

This issue was reported in
WebAssembly/tool-conventions#158
kbluck pushed a commit to kbluck/llvm-project that referenced this issue Jul 6, 2024
…d symbols (llvm#97444)

When an undefined symbol is referenced from more than one file we were
reporting all undefined symbols as originating from just one of them.

This came up while working on
WebAssembly/tool-conventions#158 where
undefined symbols in one object file were being reported as coming from
another.
sunfishcode added a commit to sunfishcode/llvm-project that referenced this issue Oct 11, 2024
We were prepared to enable these features [back in February], but they
got pulled for what appear to be unrelated reasons. So let's have another
try at enabling them!

Another motivation here is that it'd be convenient for the
[Trail1 proposal] if "trail1" is a superset of "generic".

[back in February]: WebAssembly/tool-conventions#158 (comment)
[Trail1 proposal]: llvm#112035
@sunfishcode
Copy link
Member

The original issue here is resolved in D125729. "generic" will evolve over time, as features are implemented in engines.

#233 is a discussion about the specific feature of reference-types being enabled by default in LLVM 19, and the change to call_indirect encoding.

People interested in feature sets may be interested in #235, which proposes Trail1, a new table target "CPU" configuration for LLVM.

Also relevant here is that I've now submitted llvm/llvm-project#112049 to LLVM to enable nontrapping-fptoint and bulk-memory. They were planned to be enabled here back in February but were reverted for what appear to be unrelated issues, so I'm now proposing to re-add them.

And finally here, @sbc100, you mentioned here that there were two bugs. It looks like those were fixed in llvm/llvm-project#97444 and llvm/llvm-project#97451. If that's true, then I propose we can close this issue now.

@sbc100
Copy link
Member

sbc100 commented Oct 11, 2024

Yup, it looks like both issue were fixed.

@sunfishcode
Copy link
Member

Thanks!

sunfishcode added a commit to sunfishcode/llvm-project that referenced this issue Oct 14, 2024
We were prepared to enable these features [back in February], but they
got pulled for what appear to be unrelated reasons. So let's have another
try at enabling them!

Another motivation here is that it'd be convenient for the
[Trail1 proposal] if "trail1" is a superset of "generic".

[back in February]: WebAssembly/tool-conventions#158 (comment)
[Trail1 proposal]: llvm#112035
sunfishcode added a commit to sunfishcode/llvm-project that referenced this issue Oct 14, 2024
We were prepared to enable these features [back in February], but they
got pulled for what appear to be unrelated reasons. So let's have another
try at enabling them!

Another motivation here is that it'd be convenient for the
[Trail1 proposal] if "trail1" is a superset of "generic".

[back in February]: WebAssembly/tool-conventions#158 (comment)
[Trail1 proposal]: llvm#112035
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

No branches or pull requests