-
Notifications
You must be signed in to change notification settings - Fork 758
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
Make local.tee's type its local's type #2511
Conversation
According to the current spec, `local.tee`'s return type should be the same as its local's type. (Discussions on whether we should change this rule is going on in WebAssembly/reference-types#55, but here I will assume this spec does not change. If this changes, we should change many parts of Binaryen transformation anyway...) But currently in Binaryen `local.tee`'s type is computed from its value's type. This didn't make any difference in the MVP, but after we have subtype relationship in WebAssembly#2451, this can become a problem. For example: ``` (func $test (result funcref) (local $0 anyref) (local.tee $0 (ref.func $test) ) ) ``` This shouldn't validate in the spec, but this will pass Binaryen validation with the current `local.tee` implementation. This makes `local.tee`'s type computed from the local's type, and makes `LocalSet::makeTee` get a type parameter, to which we should pass the its corresponding local's type. We don't embed the local type in the class `LocalSet` because it may increase memory size. This also fixes the type of `local.get` to be the local type where `local.get` and `local.set` pair is created from `local.tee`.
I'm a little worried about changes in the spec, though, let's discuss that before landing this. |
'tee': function(index, value) { | ||
return Module['_BinaryenLocalTee'](module, index, value); | ||
'tee': function(index, value, type) { | ||
return Module['_BinaryenLocalTee'](module, index, value, type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make it so that if type
is not specified, the type of value
is used - to make this backwards compatible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would only work in non-reference types. The purpose of this change is to prevent to use the value type for local.tee
's type in the first place because of subtypes... Wouldn't that be easy to be used incorrectly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly thinking in terms of existing projects that don't use reference types yet, where having to change every single local.tee
might be quite some work for no immediate benefit. Perhaps only make if backwards compatible for i32, i64, f32, f64?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still inclined to change the signature to be consistent; making the old signature only work for old number types seems a little unnatural and also adds checking overhead to every local.tee
call. I don't know how high the cost of changing existing code will be, but doesn't all existing code have to undergo significant changes after #2510 lands anyway..? WDYT? cc @kripken
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to make the change as less confusing as possible for people with existing code. It seems like they would not provide the parameter, so it would be coerced from undefined to 0, which is none
. Then they'd get a validation error later, which might not be that obvious?
Automatically converting the 0 to the proper type is one option, silently - IIUC @dcodeIO that's what you suggest?
Another option is to give an immediate error, if (type === undefined) throw Error('tee() must receive the type as a fourth parameter (this was an API change)
);` perhaps? A benefit to doing it that way is people will know to update their code, so it won't keep using the old API forever.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by
Automatically converting the 0 to the proper type is one option
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant what @dcodeIO said, at least as I understood it:
Can we make it so that if type is not specified, the type of value is used - to make this backwards compatible?
If type
is not provided, use the type of the value
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think @dcodeIO? I like the idea of requiring type
parameter in all local.tee
, and explicitly error out if type
is undefined. Allowing untyped API only for the number types doesn't seem to be very consistent. Can we land this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, go ahead :). Should be fine with other breaking changes already landed.
Co-Authored-By: Thomas Lively <[email protected]>
Which part of the spec do you mean? The |
'tee': function(index, value) { | ||
return Module['_BinaryenLocalTee'](module, index, value); | ||
'tee': function(index, value, type) { | ||
return Module['_BinaryenLocalTee'](module, index, value, type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to make the change as less confusing as possible for people with existing code. It seems like they would not provide the parameter, so it would be coerced from undefined to 0, which is none
. Then they'd get a validation error later, which might not be that obvious?
Automatically converting the 0 to the proper type is one option, silently - IIUC @dcodeIO that's what you suggest?
Another option is to give an immediate error, if (type === undefined) throw Error('tee() must receive the type as a fourth parameter (this was an API change)
);` perhaps? A benefit to doing it that way is people will know to update their code, so it won't keep using the old API forever.
2edbea8
to
94966e2
Compare
According to the current spec,
local.tee
's return type should be thesame as its local's type. (Discussions on whether we should change this
rule is going on in WebAssembly/reference-types#55, but here I will
assume this spec does not change. If this changes, we should change many
parts of Binaryen transformation anyway...)
But currently in Binaryen
local.tee
's type is computed from itsvalue's type. This didn't make any difference in the MVP, but after we
have subtype relationship in #2451, this can become a problem. For
example:
This shouldn't validate in the spec, but this will pass Binaryen
validation with the current
local.tee
implementation.This makes
local.tee
's type computed from the local's type, and makesLocalSet::makeTee
get a type parameter, to which we should pass theits corresponding local's type. We don't embed the local type in the
class
LocalSet
because it may increase memory size.This also fixes the type of
local.get
to be the local type wherelocal.get
andlocal.set
pair is created fromlocal.tee
.