Skip to content
This repository has been archived by the owner on Aug 17, 2022. It is now read-only.

Are i32 and s32 the same? #86

Open
alexcrichton opened this issue Nov 19, 2019 · 10 comments
Open

Are i32 and s32 the same? #86

alexcrichton opened this issue Nov 19, 2019 · 10 comments

Comments

@alexcrichton
Copy link

The wasm core spec has the i32 type, and the interface types spec currently has the s32 (signed 32-bit integer) type. We also have the ability to connect the core wasm module's imports with an adapter function, such as:

(module 
    (import "" "" (func (param i32)))
    (@interface implement (import "" "") (param ??) (; ... ;)))

What should ?? be here? I can see one of two options here for validators to implement:

  • Both i32 and s32 are the same type. Interface adapters would only list interface types as parameters and results, and to match i32 you'd have to write s32. The downside of this approach is that we're unifying these two types and implicitly saying that any i32 coming from the core wasm module is signed, which isn't necessarily always correct. Additionally if the core wasm spec later gets a u16 type, for example, we'd have to be careful to also ensure that it unifies with the adapter type u16, but this may not be the easiest thing to do.

  • The i32 and s32 types are distinct, so they do not unify. This means that adapter functions must be able to list core wasm types as parameters/results. The upside of this approach is that the two worlds are a bit more sequestered from each other. The downside, however, is that you can export an adapter function with the i32 type as a parameter or a result, so we still have to define what an i32 is, which is probably going to be a signed integer.

Do others have thoughts on how best to tackle this? This is the same issue for i64 and s64. I don't think this is an issue for f32 and f64 since there's clearly only one way to interpret it there.

I would personally lean towards keeping these distinct types, but also having a validation pass that the exported adapter functions are not allowed to have core wasm type i32/i64 in their type signatures.

@fgmccabe
Copy link
Contributor

fgmccabe commented Nov 19, 2019 via email

@devsnek
Copy link
Member

devsnek commented Nov 19, 2019

i32 is just some 32 bit "thing". The interface types would say whether to treat that as signed or unsigned.

@alexcrichton
Copy link
Author

The main thrust of this issue is that I thought that the intention was that the two types were different, but due to the impelment functionality of hooking up an adapter function to a wasm core import they weren't as different as I originally thought. The existence of this functionality implies that interface adapter functions are actually a function from a list of types to a list of types where the set of types on each end is the union of interface types and wasm core types. (where f32 and f64 are supposably the same element in each set).

If we want to keep the two types distinct we need to rationalize this somehow. What does it mean for i32/i64 wasm core types to show up in interface adapter exports? Are there other type checking/validation things to concern ourselves with if these two types are distinct? (e.g. I thought arg.get would always produce an interface types, but it can actually produce an interface type or a wasm type)

@devsnek
Copy link
Member

devsnek commented Nov 19, 2019

i have admittedly not been as active with interface types as i'd like to be, but i think i'd expect there to be s32 and u32 in interface types which cover i32, and then all three of those would be valid within interface types.

@fgmccabe
Copy link
Contributor

fgmccabe commented Nov 19, 2019 via email

@alexcrichton
Copy link
Author

@fgmccabe

EIther a function has an interface type signature or a core wasm signature.

To clarify, this is what I'm mostly opening this issue about. As written today with the explainer this is not currently upheld. For example the original comment on this issue lists an example where an adapter function must have a core wasm type in its signature.

This issue is either:

  • Clarifying you can't write core wasm types in adapter signatures, meaning i32 and s32 are equivalent (more or less)
  • Clarifying you can write core wasm types in adapter signatures, then requiring a further clarification of what to do about exported adapter functions with core wasm types in their signature.

@lukewagner
Copy link
Member

lukewagner commented Nov 20, 2019

I think we have to consider adapter functions that implement a core import differently from adapter functions that are exported. The former must use core wasm types and only core wasm types to match the core wasm import's function signature. For the latter, it seems attractive to say "only interface types" (with f32, f64, anyref, and some other future core types explicitly included), but I think we need to be a bit more nuanced so that we can support use cases like a single "nanoprocess" that is composed of multiple modules sharing a memory. In this case, interface types would be used to describe the external interface of the nanoprocess, but core types would be used for imports within the nanoprocess.

@alexcrichton
Copy link
Author

@lukewagner it sounds like you're advocating (to confirm) for distinct types, but also not forbidding i32/i64 in exports and requiring that host languages, environments, and such will have to specify a definition for i32/i64?

@lukewagner
Copy link
Member

That would address the "dynamically-linked nanoprocess" use case. The reason I was ambiguous is that I've been wondering about a slightly more nuanced approach of trying to distinguish imports between nanoprocesses (which should logically only use interface types) and imports between the "main" module and its ".dll" modules (which should logically only use core wasm types).

One idea is to say: imported/exported adapter functions can only use interface types while "re-exported" core imported/exported functions would, of course, only use core wasm types. "Re-export"/"Re-import" hasn't been spelled out in detail yet, but we've discussed it informally as a way to trivially propagate the core module's imports/exports into the adapted module's imports/exports. But ultimately this is just a restriction on the general case (of allowing the full union of types), so I'm not sure if it's worth making.

@Serentty
Copy link

Serentty commented Apr 8, 2020

I would be happy if modules are not allowed to use i32 at all through interfaces, and had to specify signedness. Having APIs which leave signedness unspecified just seems like an oversight.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants