@@ -440,3 +440,136 @@ TODO
440
440
## Type Section Field Deduplication
441
441
442
442
TODO
443
+
444
+ ## Binary Format
445
+
446
+ ### Describes and Desciptor Clauses
447
+
448
+ In the formal syntax,
449
+ we insert optional descriptor and describes clauses between ` comptype `
450
+ (or ` sharecomptype ` from shared-everything-threads)
451
+ and ` subtype ` :
452
+
453
+ ```
454
+ descriptorcomptype ::=
455
+ | 0x4D x:typeidx ct:sharecomptype => (descriptor x ct)
456
+ | ct:sharecomptype => ct
457
+
458
+ describescomptype ::=
459
+ | 0x4C x:typeidx ct:descriptorcomptype => (describes x ct)
460
+ | ct:descriptorcomptype => ct
461
+
462
+ subtype ::=
463
+ | 0x50 x*:vec(typeidx) ct:describescomptype => sub x* ct
464
+ | 0x4F x*:vec(typeidx) ct:describescomptype => sub final x* ct
465
+ | ct:describescomptype => sub final eps ct
466
+ ```
467
+
468
+ > TODO: Update the text format in the examples above to reflect this
469
+ > factoring of the syntax.
470
+
471
+ ### Exact Reference Types
472
+
473
+ Rather than use two new opcodes in the type opcode space
474
+ to represent nullable and non-nullable exact reference types,
475
+ we introduce just a single new prefix opcode that encode both:
476
+
477
+ ```
478
+ reftype :: ...
479
+ | 0x62 0x64 ht:heaptype => ref exact ht
480
+ | 0x62 0x63 ht:heaptype => ref null exact ht
481
+ ```
482
+
483
+ To make the most of the existing shorthands for nullable abstract heap types,
484
+ we also allow using the exact prefix with those shorthands:
485
+
486
+ ```
487
+ reftype :: ...
488
+ | 0x62 ht:absheaptype => ref null exact ht
489
+ ```
490
+
491
+ ### Instructions
492
+
493
+ The existing ` ref.test ` , ` ref.cast ` , ` br_on_cast ` and ` br_on_cast_fail ` instructions
494
+ need to be able to work with exact reference types.
495
+ ` ref.test ` and ` ref.cast ` currently have two opcodes each:
496
+ one for nullable target types and one for non-nullable target types.
497
+ Rather than introducing two new opcodes for each of these instructions
498
+ to allow for nullable exact and non-nullable exact target types,
499
+ we introduce one new opcode for each that takes a full reference type
500
+ rather than a heap type as its immediate.
501
+
502
+ ```
503
+ instr ::= ...
504
+ | 0xFB 32:u32 rt:reftype => ref.test rt
505
+ | 0xFB 33:u32 rt:reftype => ref.cast rt
506
+ ```
507
+
508
+ (` 0xFB 31 ` is already used by ` ref.i31_shared ` in the shared-everything-threads proposal.)
509
+
510
+ Note that these new encodings can be used instead of the existing encodings
511
+ to represent casts to inexact reference types.
512
+
513
+ > Note: We could alternatively restrict the new encoding to be usable only with exact types,
514
+ > but this artificial restriction does not seem useful.
515
+
516
+ > Note: We could alternatively continue the existing encoding scheme,
517
+ > at the cost of using 4 new opcodes instead of 2.
518
+
519
+ ` br_on_cast ` and ` br_on_cast_fail ` already encode the nullability of their
520
+ input and output types in a "castflags" u8 immediate. Castflags is extended to encode
521
+ exactness as well:
522
+
523
+ ```
524
+ castflags ::= ...
525
+ | 4:u8 => (exact, eps)
526
+ | 5:u8 => (null exact, eps)
527
+ | 6:u8 => (exact, null)
528
+ | 7:u8 => (null exact, null)
529
+ | 8:u8 => (eps, exact)
530
+ | 9:u8 => (null, exact)
531
+ | 10:u8 => (eps, null exact)
532
+ | 11:u8 => (null, null exact)
533
+ | 12:u8 => (exact, exact)
534
+ | 13:u8 => (null exact, exact)
535
+ | 14:u8 => (exact, null exact)
536
+ | 15:u8 => (null exact, null exact)
537
+ ```
538
+
539
+ Note that the bits now have the following meanings:
540
+
541
+ ```
542
+ bit 0: source nullability
543
+ bit 1: target nullability
544
+ bit 3: source exactness
545
+ bit 4: target exactness
546
+ ```
547
+
548
+ The other new instructions are encoded as follows:
549
+
550
+ ```
551
+ instr ::= ...
552
+ | 0xFB 34:u32 x:typeidx => ref.get_rtt x
553
+ | 0xFB 35:u32 rt:reftype => ref.cast_rtt reftype
554
+ | 0xFB 36:u32 (null_1? exact_1?, null_2? exact_2?):castflags
555
+ l:labelidx ht_1:heaptype ht_2:heaptype =>
556
+ br_on_cast_rtt l (ref null_1? exact_1? ht_1) (ref null_2? exact_2? ht_2)
557
+ | 0xFB 37:u32 (null_1? exact_1?, null_2? exact_2?):castflags
558
+ l:labelidx ht_1:heaptype ht_2:heaptype =>
559
+ br_on_cast_rtt_fail l (ref null_1? exact_1? ht_1) (ref null_2? exact_2? ht_2)
560
+ ```
561
+
562
+ ## Minimal Initial Prototyping for JS Interop
563
+
564
+ A truly minimal prototype for experimenting with JS interop can skip
565
+ implementing most of the new features in this proposal:
566
+
567
+ - Arbitrary fields on custom RTTs.
568
+ A minimal prototype can allow ` descriptor ` clauses only on empty structs.
569
+ - Exact reference types.
570
+ A minimal prototype can instead bake a custom RTT exactness check into the
571
+ semantics of ` struct.new ` and ` struct.new_default ` to ensure soundness.
572
+ - New instructions.
573
+ A minimal prototype only needs to update ` struct.new ` and ` struct.new_default `
574
+ to take references to custom RTTs as necessary.
575
+ It does not need to implement ` ref.get_rtt ` or any of the new RTT casts.
0 commit comments