Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 86f5724

Browse files
authored
Add bulk array creation instructions (#278)
1 parent 8dfabda commit 86f5724

File tree

2 files changed

+80
-13
lines changed

2 files changed

+80
-13
lines changed

proposals/gc/MVP.md

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,13 @@ This can compile to machine code that (1) reads the RTT from `$x`, (2) checks th
436436
* `struct.new_with_rtt <typeidx>` allocates a structure with RTT information determining its [runtime type](#values) and initialises its fields with given values
437437
- `struct.new_with_rtt $t : [t'* (rtt $t)] -> [(ref $t)]`
438438
- iff `expand($t) = struct (mut t')*`
439+
- this is a *constant instruction*
439440

440441
* `struct.new_default_with_rtt <typeidx>` allocates a structure of type `$t` and initialises its fields with default values
441442
- `struct.new_default_with_rtt $t : [(rtt $t)] -> [(ref $t)]`
442443
- iff `expand($t) = struct (mut t')*`
443444
- and all `t'*` are defaultable
445+
- this is a *constant instruction*
444446

445447
* `struct.get_<sx>? <typeidx> <fieldidx>` reads field `i` from a structure
446448
- `struct.get_<sx>? $t i : [(ref null $t)] -> [t]`
@@ -460,12 +462,39 @@ This can compile to machine code that (1) reads the RTT from `$x`, (2) checks th
460462

461463
* `array.new_with_rtt <typeidx>` allocates an array with RTT information determining its [runtime type](#values)
462464
- `array.new_with_rtt $t : [t' i32 (rtt $t)] -> [(ref $t)]`
463-
- iff `expand($t) = array (var t')`
465+
- iff `expand($t) = array (mut t')`
466+
- this is a *constant instruction*
464467

465468
* `array.new_default_with_rtt <typeidx>` allocates an array and initialises its fields with the default value
466469
- `array.new_default_with_rtt $t : [i32 (rtt $t)] -> [(ref $t)]`
467-
- iff `expand($t) = array (var t')`
470+
- iff `expand($t) = array (mut t')`
468471
- and `t'` is defaultable
472+
- this is a *constant instruction*
473+
474+
* `array.new_fixed <typeidx> <N>` allocates an array of fixed size and initialises it from operands
475+
- `array.new_fixed $t N : [t^N (rtt $t)] -> [(ref $t)]`
476+
- iff `expand($t) = array (mut t')`
477+
- this is a *constant instruction*
478+
479+
* `array.new_data <typeidx> <dataidx>` allocates an array and initialises it from a data segment
480+
- `array.new_data $t $d : [i32 i32 (rtt $t)] -> [(ref $t)]`
481+
- iff `expand($t) = array (mut t')`
482+
- and `t'` is numeric or packed numeric
483+
- and `$d` is a defined data segment
484+
- the 1st operand is the `offset` into the segment
485+
- the 2nd operand is the `size` of the array
486+
- traps if `offset + |t'|*size > len($d)`
487+
- this is a *constant instruction*
488+
489+
* `array.new_elem <typeidx> <elemidx>` allocates an array and initialises it from an element segment
490+
- `array.new_elem $t $e : [i32 i32 (rtt $t)] -> [(ref $t)]`
491+
- iff `expand($t) = array (mut t')`
492+
- and `t'` is a reference type
493+
- and `$e` is a defined element segment
494+
- the 1st operand is the `offset` into the segment
495+
- the 2nd operand is the `size` of the array
496+
- traps if `offset + size > len($e)`
497+
- note: for now, this is _not_ a constant instruction, in order to side-step issues of recursion between binary sections; this restriction will be lifted later
469498

470499
* `array.get_<sx>? <typeidx>` reads an element from an array
471500
- `array.get_<sx>? $t : [(ref null $t) i32] -> [t]`
@@ -642,6 +671,10 @@ Note: These instructions allow an operand of unrelated reference type, even thou
642671
In order to allow RTTs to be initialised as globals, the following extensions are made to the definition of *constant expressions*:
643672

644673
* `rtt.canon` is a constant instruction
674+
* `i31.new` is a constant instruction
675+
* `struct.new` and `struct.new_default` are constant instructions
676+
* `array.new`, `array.new_default`, `array.new_fixed`, and `array.new_data` are constant instructions
677+
- Note: `array.new_elem` is not for the time being, see above
645678
* `global.get` is a constant instruction and can access preceding (immutable) global definitions, not just imports as in the MVP
646679

647680

@@ -737,6 +770,9 @@ The opcode for heap types is encoded as an `s33`.
737770
| 0xfb15 | `array.get_u $t` | `$t : typeidx` |
738771
| 0xfb16 | `array.set $t` | `$t : typeidx` |
739772
| 0xfb17 | `array.len` | `_ : u32` (TODO: remove, was typeidx) |
773+
| 0xfb19 | `array.new_fixed $t N` | `$t : typeidx`, `N : u32` |
774+
| 0xfb1b | `array.new_data $t $d` | `$t : typeidx`, `$d : dataidx` |
775+
| 0xfb1c | `array.new_elem $t $e` | `$t : typeidx`, `$e : elemidx` |
740776
| 0xfb20 | `i31.new` | |
741777
| 0xfb21 | `i31.get_s` | |
742778
| 0xfb22 | `i31.get_u` | |
@@ -772,8 +808,6 @@ See [GC JS API document](MVP-JS.md) .
772808

773809
* Make rtt operands nullable?
774810

775-
* Make `i31.new` a constant instruction. Others too?
776-
777811
* Enable `i31` as a type definition.
778812

779813
* Should reference types be generalised to *unions*, e.g., of the form `(ref null? i31? data? func? extern? $t?)`? Perhaps even allowing multiple concrete types?

proposals/gc/Post-MVP.md

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,50 @@ To that end, _bulk copying_ instructions could be added, similar to the [bulk in
3636
- `struct.copy $d : [(ref $d) (ref $s)] -> []` where both `$d` and `$s` are struct types, `$d` has only mutable fields, and `$s <: $d` modulo mutability
3737

3838
* An instruction for bulk copying an array range:
39-
- `array.copy $d : [(ref $d) i32 (ref $s) i32 i32] -> []`
40-
- iff both `$d` and `$s` are array types
41-
- and `$d` has mutable element type
42-
- and `$s <: $d` modulo mutability
43-
- the remaining operands are destination and source offset and length of the range
39+
- `array.copy $d $s : [(ref null $d) i32 (ref null $s) i32 i32] -> []`
40+
- iff `expand($d) = array (var t1)`
41+
- and `expand($s) = array (mut t2)`
42+
- and `t2 <: t1`
43+
- the 1st i32 operand is the `destination` offset in the first array
44+
- the 2nd i32 operand is the `source` offset in the second array
45+
- the 3rd i32 operand is the `length` of the array subrange
46+
- traps if either array is null
47+
- traps if `destination + length > len(array1)`
48+
- traps if `source + length > len(array2)`
4449

4550
* An instruction for bulk setting an array range:
46-
- `array.fill $d : [(ref $d) i32 t i32] -> []`
47-
- iff `$d = (array (mut st))`
48-
- and `t = unpacked(st)`
49-
- the remaining operands are destination offset, initialisation value, and length of the range
51+
- `array.fill $t : [(ref null $t) i32 t i32] -> []`
52+
- iff `expand($t) = array (var t')`
53+
- and `t = unpacked(t')`
54+
- the 1st operand is the `offset` in the array
55+
- the 2nd operand is the `length` of the array subrange
56+
- traps if the array is null
57+
- traps if `offset + length > len(array)`
58+
59+
* An instruction to (re)initialise an array range from a data segment
60+
- `array.init_data $t $d : [(ref null $t) i32 i32 i32] -> []`
61+
- iff `expand($t) = array (var t')`
62+
- and `t'` is numeric or packed numeric
63+
- and `$d` is a defined data segment
64+
- the 1st operand is the `destination` offset in the array
65+
- the 2nd operand is the `source` offset in the segment
66+
- the 3rd operand is the `length` of the array subrange
67+
- traps if the array is null
68+
- traps if `destination + length > len(array)`
69+
- traps if `source + |t'|*length > len($d)`
70+
71+
* An instruction to (re)initialise an array range from an element segment
72+
- `array.init_elem $t $e : [(ref null $t) i32 i32 i32] -> []`
73+
- iff `expand($t) = array (var t')`
74+
- and `t'` is a reference type
75+
- and `$e` is a defined element segment
76+
- the 1st operand is the `destination` offset in the array
77+
- the 2nd operand is the `source` offset in the segment
78+
- the 3rd operand is the `length` of the array subrange
79+
- traps if the array is null
80+
- traps if `destination + length > len(array)`
81+
- traps if `source + length > len($e)`
82+
5083

5184

5285
## Array with Fields

0 commit comments

Comments
 (0)