Skip to content

Commit b0d1dd7

Browse files
authored
Add the GC canonical option (#2182)
* Add the GC canonical option Disallow using the `core-type` option without `gc`. * require cm-gc feature * fix test expectations
1 parent e66756b commit b0d1dd7

File tree

15 files changed

+264
-311
lines changed

15 files changed

+264
-311
lines changed

crates/wasm-encoder/src/component/canonicals.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub enum CanonicalOption {
2929
Callback(u32),
3030
/// The core function type to lower a component function into.
3131
CoreType(u32),
32+
/// Use the GC variant of the canonical ABI.
33+
Gc,
3234
}
3335

3436
impl Encode for CanonicalOption {
@@ -60,6 +62,9 @@ impl Encode for CanonicalOption {
6062
sink.push(0x08);
6163
idx.encode(sink);
6264
}
65+
Self::Gc => {
66+
sink.push(0x09);
67+
}
6368
}
6469
}
6570
}

crates/wasm-encoder/src/reencode/component.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,7 @@ pub mod component_utils {
13931393
wasmparser::CanonicalOption::CoreType(u) => {
13941394
crate::component::CanonicalOption::CoreType(reencoder.type_index(u)?)
13951395
}
1396+
wasmparser::CanonicalOption::Gc => crate::component::CanonicalOption::Gc,
13961397
})
13971398
}
13981399

crates/wasmparser/src/readers/component/canonicals.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub enum CanonicalOption {
3030
Callback(u32),
3131
/// The core function type to lower this component function to.
3232
CoreType(u32),
33+
/// Use the GC version of the canonical ABI.
34+
Gc,
3335
}
3436

3537
/// Represents a canonical function in a WebAssembly component.
@@ -404,6 +406,7 @@ impl<'a> FromReader<'a> for CanonicalOption {
404406
0x06 => CanonicalOption::Async,
405407
0x07 => CanonicalOption::Callback(reader.read_var_u32()?),
406408
0x08 => CanonicalOption::CoreType(reader.read_var_u32()?),
409+
0x09 => CanonicalOption::Gc,
407410
x => return reader.invalid_leading_byte(x, "canonical option"),
408411
})
409412
}

crates/wasmparser/src/validator/component.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ pub(crate) struct CanonicalOptions {
239239
pub(crate) post_return: Option<u32>,
240240
pub(crate) concurrency: Concurrency,
241241
pub(crate) core_type: Option<CoreTypeId>,
242+
pub(crate) gc: bool,
242243
}
243244

244245
impl CanonicalOptions {
@@ -304,6 +305,13 @@ impl CanonicalOptions {
304305
);
305306
}
306307

308+
if self.gc && self.core_type.is_none() {
309+
bail!(
310+
offset,
311+
"cannot specify `gc` without also specifying a `core-type` for lowerings"
312+
)
313+
}
314+
307315
Ok(self)
308316
}
309317

@@ -2334,7 +2342,8 @@ impl ComponentState {
23342342
CanonicalOption::PostReturn(_) => "post-return",
23352343
CanonicalOption::Async => "async",
23362344
CanonicalOption::Callback(_) => "callback",
2337-
CanonicalOption::CoreType(_) => "core type",
2345+
CanonicalOption::CoreType(_) => "core-type",
2346+
CanonicalOption::Gc => "gc",
23382347
}
23392348
}
23402349

@@ -2345,6 +2354,7 @@ impl ComponentState {
23452354
let mut is_async = false;
23462355
let mut callback = None;
23472356
let mut core_type = None;
2357+
let mut gc = false;
23482358

23492359
for option in options {
23502360
match option {
@@ -2475,6 +2485,21 @@ impl ComponentState {
24752485
}
24762486
};
24772487
}
2488+
CanonicalOption::Gc => {
2489+
if gc {
2490+
return Err(BinaryReaderError::new(
2491+
"canonical option `gc` is specified more than once",
2492+
offset,
2493+
));
2494+
}
2495+
if !self.features.cm_gc() {
2496+
return Err(BinaryReaderError::new(
2497+
"canonical option `gc` requires the `cm-gc` feature",
2498+
offset,
2499+
));
2500+
}
2501+
gc = true;
2502+
}
24782503
}
24792504
}
24802505

@@ -2489,12 +2514,17 @@ impl ComponentState {
24892514
(true, callback, false) => Concurrency::Async { callback },
24902515
};
24912516

2517+
if !gc && core_type.is_some() {
2518+
bail!(offset, "cannot specify `core-type` without `gc`")
2519+
}
2520+
24922521
Ok(CanonicalOptions {
24932522
memory,
24942523
realloc,
24952524
post_return,
24962525
concurrency,
24972526
core_type,
2527+
gc,
24982528
})
24992529
}
25002530

crates/wasmprinter/src/component.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ impl Printer<'_, '_> {
835835
self.print_idx(&state.core.type_names, *idx)?;
836836
self.end_group()?;
837837
}
838+
CanonicalOption::Gc => self.result.write_str("gc")?,
838839
}
839840
}
840841
Ok(())

crates/wast/src/component/binary.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ impl From<&CanonOpt<'_>> for wasm_encoder::CanonicalOption {
976976
CanonOpt::Async => Self::Async,
977977
CanonOpt::Callback(f) => Self::Callback(f.idx.into()),
978978
CanonOpt::CoreType(t) => Self::CoreType(t.idx.into()),
979+
CanonOpt::Gc => Self::Gc,
979980
}
980981
}
981982
}

crates/wast/src/component/func.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,8 @@ pub enum CanonOpt<'a> {
951951
Callback(CoreItemRef<'a, kw::func>),
952952
/// Lower this component function into the specified core function type.
953953
CoreType(CoreItemRef<'a, kw::r#type>),
954+
/// Use the GC variant of the canonical ABI.
955+
Gc,
954956
}
955957

956958
impl Default for kw::r#type {
@@ -974,6 +976,9 @@ impl<'a> Parse<'a> for CanonOpt<'a> {
974976
} else if l.peek::<kw::r#async>()? {
975977
parser.parse::<kw::r#async>()?;
976978
Ok(Self::Async)
979+
} else if l.peek::<kw::gc>()? {
980+
parser.parse::<kw::gc>()?;
981+
Ok(Self::Gc)
977982
} else if l.peek::<LParen>()? {
978983
parser.parens(|parser| {
979984
let mut l = parser.lookahead1();
@@ -1015,6 +1020,7 @@ impl Peek for CanonOpt<'_> {
10151020
|| kw::string_utf16::peek(cursor)?
10161021
|| kw::string_latin1_utf16::peek(cursor)?
10171022
|| kw::r#async::peek(cursor)?
1023+
|| kw::gc::peek(cursor)?
10181024
|| match cursor.lparen()? {
10191025
Some(next) => {
10201026
kw::memory::peek(next)?

crates/wast/src/component/resolve.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,8 @@ impl<'a> Resolver<'a> {
481481
CanonOpt::StringUtf8
482482
| CanonOpt::StringUtf16
483483
| CanonOpt::StringLatin1Utf16
484-
| CanonOpt::Async => {}
484+
| CanonOpt::Async
485+
| CanonOpt::Gc => {}
485486
CanonOpt::Memory(r) => self.core_item_ref(r)?,
486487
CanonOpt::Realloc(r) | CanonOpt::PostReturn(r) | CanonOpt::Callback(r) => {
487488
self.core_item_ref(r)?

crates/wast/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ pub mod kw {
545545
custom_keyword!(with);
546546
custom_keyword!(core);
547547
custom_keyword!(core_type = "core-type");
548+
custom_keyword!(gc);
548549
custom_keyword!(true_ = "true");
549550
custom_keyword!(false_ = "false");
550551
custom_keyword!(language);

0 commit comments

Comments
 (0)