I have some questions to understand the packed types. Are the follow points right?
- This value types can only occur on arrays and structs.
- i8 and i16 can NOT occur on function parameters, function locals or return parameters
Yes, as you can see from the grammar, they can only appear as <storagetype>. They are not value types.
- i8 and i16 have a negative type value like i32. For example -0x05 and -0x06. They must not be declared in the type section.
The proposal doesn't fix opcodes yet, but yes, that would be the idea.
They cannot be declared in the type section, as the grammar specifies.
- Are the values signed or unsigned if I access struct.get/array.get? How will it extends to a local of i32?
Good question. This definitely still needs sorting out. As sketched, the MVP assumes that a choice is fixed regarding sign extension and that you use e.g. explicit masking or sign extension instruction if the other semantics is needed. The (older) overview on the other hand mentions explicit load_packed instructions which include a choice of sign extension semantics.
- Are there traps on struct.set/array.set if the value is to large? Or will the high part cut?
They would be truncating, just like store instructions.
Thoughts on the signedness of packed types:
i8 and u8 and i16 and u16 packed types. That removes the need for putting this information into the opcode, but means that, e.g. i8 values cannot also be loaded as u8. I think this is fine, since these rare cases can be handled with manual sign/zero-extension. We'd also have to decide if i8 is structurally compatible with u8 from the type system perspective.From my point of view (Java to WebAssembly compiler) I would prefer different types for signed and unsigned data. Then I can simple match the Java data type "byte" to i8 and the Java data type "char" to u16.
The same is valid for every other programming language.
If we want to be consistent with the rest of Wasm then we should probably have instructions with an _s/u suffix selecting sign extension semantics for packed loads. Whether these are separate instructions (like suggested in the Overview) or flags on the existing instruction is mainly a binary encoding detail. I agree that using a flag field might come in handy for atomics later.
Adjusted MVP.md to add a sign extension suffix.
This seems to already have been decided, but here is another vote towards not encoding signedness in the type. LLVM had this, but decided to drop it as it made the type system more complex than needed: http://nondot.org/sabre/LLVMNotes/TypeSystemChanges.txt
In fact, I would go even further and say that perhaps packed loads should probably avoid sign extension as well. If there is a sign extension instruction (I don't know whether it already exists), it should be trivial for an implementor to fuse an unsigned load and sign extension into a single sign-extending load on supported platforms. Separating these two may lead to slightly increased code size, but probably simplifies the implementation while leaving room for optimizations.
It seems the original clarification was addressed.The current proposal does not encode the sign into the type, but instead provides load/store instructions with sign extension to the supported wasm value types (i32 or i64).
The remaining question is whether these instructions should sign-extend at all, or always zero-extend. The threads proposal was faced with a similar choice, and we opted to only include the zero-extend operations, and provide separate sign-extension instructions. Those have since been standardized. So it seems reasonable to follow suit here and provide only zero-extending packed loads, and require the use of i32.extend8_s etc. if sign-extension is desired.
I don't feel strongly, but it seems like we would be inconsistent with memory instructions if we didn't provide both options. IIRC, the original argument for those was that we want to provide as separate instructions what is already available as separate instructions on the hardware.
Most helpful comment
Yes, as you can see from the grammar, they can only appear as
<storagetype>. They are not value types.The proposal doesn't fix opcodes yet, but yes, that would be the idea.
They cannot be declared in the type section, as the grammar specifies.
Good question. This definitely still needs sorting out. As sketched, the MVP assumes that a choice is fixed regarding sign extension and that you use e.g. explicit masking or sign extension instruction if the other semantics is needed. The (older) overview on the other hand mentions explicit load_packed instructions which include a choice of sign extension semantics.
They would be truncating, just like store instructions.