Discussing `record.lift/lower` for multi-dimensional records
Discussing about this version of the proposal (the latest at the time of writing): https://github.com/WebAssembly/interface-types/blob/5af0606baceab6c5ecc8bd247fae944998c2aa61/proposals/interface-types/working-notes/Instructions.md#stringlower_memory
I want to discuss about the record.lift instruction (same ideas for record.lower). Let's assume the following type, that could represent a Point:
;; Point { x: i32, y: i32 }
(@interface type (record (field i32) (field i32)))
Then the set of instructions would look like the following:
| Instruction | Stack | Comment |
|---|---|---|
arg.get 0 |
[i32(7)] |
Load x |
arg.get 1 |
[i32(7), i32(42)] |
Load y |
record.lift 0 |
[record([7, 42])] |
Tada, our record |
My question is what happens with a multi-dimensional record? Let's assume the Line type:
;; Line { p1: Point, p2: Point }
(@interace type
(record
(field
record (field i32) (field i32))
(field
record (field i32) (field i32))))
Then the set of instructions would look like as follows:
| Instruction | Stack | Comment |
|---|---|---|
arg.get 0 |
[i32(7)] |
Load x for p1 |
arg.get 1 |
[i32(7), i32(42)] |
Load y for p1 |
arg.get 2 |
[i32(7), i32(42), i32(153)] |
Load x for p2 |
arg.get 3 |
[i32(7), i32(42), i32(153), i32(256)] |
Load y for p2 |
record.lift 0 |
[record([record([7, 42]), record([153, 256])])] |
Tada, our record |
Is this correct? Should we have all the fields “flattened”, and the record.lift instruction rebuild everything? Or do we expect the following:
| Instruction | Stack | Comment |
|---|---|---|
arg.get 0 |
[i32(7)] |
Load x for p1 |
arg.get 1 |
[i32(7), i32(42)] |
Load y for p1 |
record.lift ?? |
[record([i32(7), i32(42)])] |
Record for p1 |
arg.get 2 |
[record([i32(7), i32(42)]), i32(153)] |
Load x for p2 |
arg.get 3 |
[record([i32(7), i32(42)]), i32(153), i32(256)] |
Load y for p2 |
record.lift ?? |
[record([i32(7), i32(42)]), record([i32(153), i32(256)])] |
Record for p2 |
record.lift 0 |
[record([record([7, 42]), record([153, 256])])] |
Tada, our final record |
In this case, we load intermediate Point records. But since record.lift requires a record type index, what would it be? It would mean that record type must be flattened too, something like:
(@interface type $point (record (field i32) (field i32)))
(@interface type $line (record (field (record type $point) (record type $point))))
The same observation can be applied to record.lower.
I hope my question isn't too trivial. With the Covid-19 situation, I have difficulties to follow every discussions of this WG.
Thanks!
- Record.lift/lower (not my preferred names for these ops) wrap and unwrap interface value types. I.e., they go from a sequence of IT values on the stack <-> a single IT value. Multi-dimensional records as you put it would follow this pattern too. Each lift/lower wraps/unwraps a single record.
- Although it can seem expensive to push entries on the stack, be aware that in most implementations a push/pop operation does not actually result in any code being executed. Think of it as a systematic way of supporting multi-operand instructions.
On Tue, Apr 7, 2020 at 5:23 AM Ivan Enderlin [email protected] wrote:
Discussing about this version of the proposal (the latest at the time of writing): https://github.com/WebAssembly/interface-types/blob/5af0606baceab6c5ecc8bd247fae944998c2aa61/proposals/interface-types/working-notes/Instructions.md#stringlower_memory
I want to discuss about the record.lift instruction (same ideas for record.lower). Let's assume the following type, that could represent a Point:
;; Point { x: i32, y: i32 }
(@interface type (record (field i32) (field i32)))
Then the set of instructions would look like the following: Instruction Stack Comment arg.get 0 [i32(7)] Load x arg.get 1 [i32(7), i32(42)] Load y record.lift 0 [record([7, 42])] Tada, our record
My question is what happens with a multi-dimensional record? Let's assume the Line type:
;; Line { p1: Point, p2: Point }
(@interace type
(record
(field record (field i32) (field i32)) (field record (field i32) (field i32))))Then the set of instructions would look like as follows: Instruction Stack Comment arg.get 0 [i32(7)] Load x for p1 arg.get 1 [i32(7), i32(42)] Load y for p1 arg.get 2 [i32(7), i32(42), i32(153)] Load x for p2 arg.get 3 [i32(7), i32(42), i32(153), i32(256)] Load y for p2 record.lift 0 [record([record([7, 42]), record([153, 256])])] Tada, our record
Is this correct? Should we have all the fields “flattened”, and the record.lift instruction rebuild everything? Or do we expect the following: Instruction Stack Comment arg.get 0 [i32(7)] Load x for p1 arg.get 1 [i32(7), i32(42)] Load y for p1 record.lift ?? [record([i32(7), i32(42)])] Record for p1 arg.get 2 [record([i32(7), i32(42)]), i32(153)] Load x for p2 arg.get 3 [record([i32(7), i32(42)]), i32(153), i32(256)] Load y for p2 record.lift ?? [record([i32(7), i32(42)]), record([i32(153), i32(256)])] Record for p2 record.lift 0 [record([record([7, 42]), record([153, 256])])] Tada, our final record
In this case, we load intermediate Point records. But since record.lift requires a record type index, what would it be? It would mean that record type must be flattened too, something like:
(@interface type $point (record (field i32) (field i32)))
(@interface type $line (record (field (record type $point) (record type $point))))
The same observation can be applied to record.lower.
I hope my question isn't too trivial. With the Covid-19 situation, I have difficulties to follow every discussions of this WG.
Thanks!
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/WebAssembly/interface-types/issues/108, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAQAXUAI6UP3RHPFFZ33UJTRLMLKVANCNFSM4MDCGGMQ .
-- Francis McCabe SWE
- Record.lift/lower (not my preferred names for these ops) wrap and unwrap interface value types. I.e., they go from a sequence of IT values on the stack <-> a single IT value.
Agreed, it took me some time to grasp what were the methods for.
I think record.wrap, record.unwrap might be a bit clearer. Thoughts?
Prefer pack and unpack but not super committed to that