Skip to content

Commit 61a7487

Browse files
feat: (CM64) context.{set, get} accept i64 immediate (#2502)
* wip * details * tests * address comments * resolve ref * factor out ref * fix
1 parent b7e2c70 commit 61a7487

21 files changed

Lines changed: 369 additions & 118 deletions

File tree

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -507,14 +507,14 @@ impl ComponentBuilder {
507507
}
508508

509509
/// Declares a new `context.get` intrinsic.
510-
pub fn context_get(&mut self, i: u32) -> u32 {
511-
self.canonical_functions().context_get(i);
510+
pub fn context_get(&mut self, ty: ValType, i: u32) -> u32 {
511+
self.canonical_functions().context_get(ty, i);
512512
self.core_funcs.add(Some(&format!("context.get {i}")))
513513
}
514514

515515
/// Declares a new `context.set` intrinsic.
516-
pub fn context_set(&mut self, i: u32) -> u32 {
517-
self.canonical_functions().context_set(i);
516+
pub fn context_set(&mut self, ty: ValType, i: u32) -> u32 {
517+
self.canonical_functions().context_set(ty, i);
518518
self.core_funcs.add(Some(&format!("context.set {i}")))
519519
}
520520

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use crate::{ComponentSection, ComponentSectionId, ComponentValType, Encode, encode_section};
1+
use crate::{
2+
ComponentSection, ComponentSectionId, ComponentValType, Encode, ValType, encode_section,
3+
};
24
use alloc::vec::Vec;
35

46
/// Represents options for canonical function definitions.
@@ -234,19 +236,21 @@ impl CanonicalFunctionSection {
234236
self
235237
}
236238

237-
/// Defines a new `context.get` intrinsic of the ith slot.
238-
pub fn context_get(&mut self, i: u32) -> &mut Self {
239+
/// Defines a new `context.get` intrinsic of the ith slot with the given
240+
/// value type.
241+
pub fn context_get(&mut self, ty: ValType, i: u32) -> &mut Self {
239242
self.bytes.push(0x0a);
240-
self.bytes.push(0x7f);
243+
ty.encode(&mut self.bytes);
241244
i.encode(&mut self.bytes);
242245
self.num_added += 1;
243246
self
244247
}
245248

246-
/// Defines a new `context.set` intrinsic of the ith slot.
247-
pub fn context_set(&mut self, i: u32) -> &mut Self {
249+
/// Defines a new `context.set` intrinsic of the ith slot with the given
250+
/// value type.
251+
pub fn context_set(&mut self, ty: ValType, i: u32) -> &mut Self {
248252
self.bytes.push(0x0b);
249-
self.bytes.push(0x7f);
253+
ty.encode(&mut self.bytes);
250254
i.encode(&mut self.bytes);
251255
self.num_added += 1;
252256
self

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -996,11 +996,11 @@ pub mod component_utils {
996996
wasmparser::CanonicalFunction::TaskCancel => {
997997
section.task_cancel();
998998
}
999-
wasmparser::CanonicalFunction::ContextGet(i) => {
1000-
section.context_get(i);
999+
wasmparser::CanonicalFunction::ContextGet { ty, slot } => {
1000+
section.context_get(reencoder.val_type(ty)?, slot);
10011001
}
1002-
wasmparser::CanonicalFunction::ContextSet(i) => {
1003-
section.context_set(i);
1002+
wasmparser::CanonicalFunction::ContextSet { ty, slot } => {
1003+
section.context_set(reencoder.val_type(ty)?, slot);
10041004
}
10051005
wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
10061006
section.thread_yield(cancellable);

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

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::limits::MAX_WASM_CANONICAL_OPTIONS;
22
use crate::prelude::*;
3-
use crate::{BinaryReader, ComponentValType, FromReader, Result, SectionLimited};
3+
use crate::{BinaryReader, ComponentValType, FromReader, Result, SectionLimited, ValType};
44

55
/// Represents options for component functions.
66
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -109,9 +109,23 @@ pub enum CanonicalFunction {
109109
/// A function to acknowledge cancellation of the current task.
110110
TaskCancel,
111111
/// A `context.get` intrinsic for the `i`th slot of task-local storage.
112-
ContextGet(u32),
112+
ContextGet {
113+
/// The type of the slot. Currently only `ValType::I32` and
114+
/// `ValType::I64` are accepted by the validator (with `I64` gated on
115+
/// the component-model 64-bit feature).
116+
ty: ValType,
117+
/// The index of the task-local storage slot.
118+
slot: u32,
119+
},
113120
/// A `context.set` intrinsic for the `i`th slot of task-local storage.
114-
ContextSet(u32),
121+
ContextSet {
122+
/// The type of the slot. Currently only `ValType::I32` and
123+
/// `ValType::I64` are accepted by the validator (with `I64` gated on
124+
/// the component-model 64-bit feature).
125+
ty: ValType,
126+
/// The index of the task-local storage slot.
127+
slot: u32,
128+
},
115129
/// A function which yields control to the host so that other tasks are able
116130
/// to make progress, if any.
117131
ThreadYield {
@@ -338,13 +352,13 @@ impl<'a> FromReader<'a> for CanonicalFunction {
338352
result: crate::read_resultlist(reader)?,
339353
options: read_opts(reader)?,
340354
},
341-
0x0a => match reader.read_u8()? {
342-
0x7f => CanonicalFunction::ContextGet(reader.read_var_u32()?),
343-
x => return reader.invalid_leading_byte(x, "context.get intrinsic type"),
355+
0x0a => CanonicalFunction::ContextGet {
356+
ty: reader.read()?,
357+
slot: reader.read_var_u32()?,
344358
},
345-
0x0b => match reader.read_u8()? {
346-
0x7f => CanonicalFunction::ContextSet(reader.read_var_u32()?),
347-
x => return reader.invalid_leading_byte(x, "context.set intrinsic type"),
359+
0x0b => CanonicalFunction::ContextSet {
360+
ty: reader.read()?,
361+
slot: reader.read_var_u32()?,
348362
},
349363
0x0c => CanonicalFunction::ThreadYield {
350364
cancellable: reader.read()?,

crates/wasmparser/src/validator/component.rs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,8 +1203,8 @@ impl ComponentState {
12031203
self.task_return(&result, &options, types, offset)
12041204
}
12051205
CanonicalFunction::TaskCancel => self.task_cancel(types, offset),
1206-
CanonicalFunction::ContextGet(i) => self.context_get(i, types, offset),
1207-
CanonicalFunction::ContextSet(i) => self.context_set(i, types, offset),
1206+
CanonicalFunction::ContextGet { ty, slot } => self.context_get(ty, slot, types, offset),
1207+
CanonicalFunction::ContextSet { ty, slot } => self.context_set(ty, slot, types, offset),
12081208
CanonicalFunction::ThreadYield { cancellable: _ } => self.thread_yield(types, offset),
12091209
CanonicalFunction::SubtaskDrop => self.subtask_drop(types, offset),
12101210
CanonicalFunction::SubtaskCancel { async_ } => {
@@ -1517,34 +1517,64 @@ impl ComponentState {
15171517
Ok(())
15181518
}
15191519

1520-
fn context_get(&mut self, i: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1520+
fn context_get(
1521+
&mut self,
1522+
ty: ValType,
1523+
i: u32,
1524+
types: &mut TypeAlloc,
1525+
offset: usize,
1526+
) -> Result<()> {
15211527
if !self.features.cm_async() {
15221528
bail!(
15231529
offset,
15241530
"`context.get` requires the component model async feature"
15251531
)
15261532
}
1533+
self.validate_context_type(ty, "context.get", offset)?;
15271534
self.validate_context_immediate(i, "context.get", offset)?;
15281535

15291536
self.core_funcs
1530-
.push(types.intern_func_type(FuncType::new([], [ValType::I32]), offset));
1537+
.push(types.intern_func_type(FuncType::new([], [ty]), offset));
15311538
Ok(())
15321539
}
15331540

1534-
fn context_set(&mut self, i: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1541+
fn context_set(
1542+
&mut self,
1543+
ty: ValType,
1544+
i: u32,
1545+
types: &mut TypeAlloc,
1546+
offset: usize,
1547+
) -> Result<()> {
15351548
if !self.features.cm_async() {
15361549
bail!(
15371550
offset,
15381551
"`context.set` requires the component model async feature"
15391552
)
15401553
}
1554+
self.validate_context_type(ty, "context.set", offset)?;
15411555
self.validate_context_immediate(i, "context.set", offset)?;
15421556

15431557
self.core_funcs
1544-
.push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
1558+
.push(types.intern_func_type(FuncType::new([ty], []), offset));
15451559
Ok(())
15461560
}
15471561

1562+
fn validate_context_type(&self, ty: ValType, intrinsic: &str, offset: usize) -> Result<()> {
1563+
match ty {
1564+
ValType::I32 => Ok(()),
1565+
ValType::I64 => {
1566+
if !self.features.cm64() {
1567+
bail!(
1568+
offset,
1569+
"64-bit `{intrinsic}` requires the component model 64-bit feature"
1570+
)
1571+
}
1572+
Ok(())
1573+
}
1574+
_ => bail!(offset, "`{intrinsic}` only supports `i32` or `i64`"),
1575+
}
1576+
}
1577+
15481578
fn thread_yield(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
15491579
if !self.features.cm_async() {
15501580
bail!(

crates/wasmprinter/src/component.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -977,15 +977,19 @@ impl Printer<'_, '_> {
977977
CanonicalFunction::TaskCancel => {
978978
self.print_intrinsic(state, "canon task.cancel", &|_, _| Ok(()))?;
979979
}
980-
CanonicalFunction::ContextGet(i) => {
981-
self.print_intrinsic(state, "canon context.get", &|me, _state| {
982-
write!(me.result, " i32 {i}")?;
980+
CanonicalFunction::ContextGet { ty, slot } => {
981+
self.print_intrinsic(state, "canon context.get", &|me, state| {
982+
me.result.write_str(" ")?;
983+
me.print_valtype(state, ty)?;
984+
write!(me.result, " {slot}")?;
983985
Ok(())
984986
})?;
985987
}
986-
CanonicalFunction::ContextSet(i) => {
987-
self.print_intrinsic(state, "canon context.set", &|me, _state| {
988-
write!(me.result, " i32 {i}")?;
988+
CanonicalFunction::ContextSet { ty, slot } => {
989+
self.print_intrinsic(state, "canon context.set", &|me, state| {
990+
me.result.write_str(" ")?;
991+
me.print_valtype(state, ty)?;
992+
write!(me.result, " {slot}")?;
989993
Ok(())
990994
})?;
991995
}

crates/wast/src/component/binary.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,13 +392,13 @@ impl<'a> Encoder<'a> {
392392
self.core_func_names.push(name);
393393
self.funcs.task_cancel();
394394
}
395-
CoreFuncKind::ContextGet(i) => {
395+
CoreFuncKind::ContextGet(ty, i) => {
396396
self.core_func_names.push(name);
397-
self.funcs.context_get(*i);
397+
self.funcs.context_get((*ty).into(), *i);
398398
}
399-
CoreFuncKind::ContextSet(i) => {
399+
CoreFuncKind::ContextSet(ty, i) => {
400400
self.core_func_names.push(name);
401-
self.funcs.context_set(*i);
401+
self.funcs.context_set((*ty).into(), *i);
402402
}
403403
CoreFuncKind::ThreadYield(info) => {
404404
self.core_func_names.push(name);

crates/wast/src/component/func.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ pub enum CoreFuncKind<'a> {
5858
BackpressureDec,
5959
TaskReturn(CanonTaskReturn<'a>),
6060
TaskCancel,
61-
ContextGet(u32),
62-
ContextSet(u32),
61+
ContextGet(crate::core::ValType<'a>, u32),
62+
ContextSet(crate::core::ValType<'a>, u32),
6363
ThreadYield(CanonThreadYield),
6464
SubtaskDrop,
6565
SubtaskCancel(CanonSubtaskCancel),
@@ -139,12 +139,12 @@ impl<'a> CoreFuncKind<'a> {
139139
Ok(CoreFuncKind::TaskCancel)
140140
} else if l.peek::<kw::context_get>()? {
141141
parser.parse::<kw::context_get>()?;
142-
parser.parse::<kw::i32>()?;
143-
Ok(CoreFuncKind::ContextGet(parser.parse()?))
142+
let ty = parser.parse()?;
143+
Ok(CoreFuncKind::ContextGet(ty, parser.parse()?))
144144
} else if l.peek::<kw::context_set>()? {
145145
parser.parse::<kw::context_set>()?;
146-
parser.parse::<kw::i32>()?;
147-
Ok(CoreFuncKind::ContextSet(parser.parse()?))
146+
let ty = parser.parse()?;
147+
Ok(CoreFuncKind::ContextSet(ty, parser.parse()?))
148148
} else if l.peek::<kw::thread_yield>()? {
149149
Ok(CoreFuncKind::ThreadYield(parser.parse()?))
150150
} else if l.peek::<kw::subtask_drop>()? {

crates/wast/src/component/resolve.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,8 @@ impl<'a> Resolver<'a> {
408408
}
409409
self.canon_opts(&mut info.opts)?;
410410
}
411-
CoreFuncKind::ContextGet(_) | CoreFuncKind::ContextSet(_) => {}
411+
CoreFuncKind::ContextGet(ty, _) => self.ref_type(ty)?,
412+
CoreFuncKind::ContextSet(ty, _) => self.ref_type(ty)?,
412413
CoreFuncKind::StreamNew(info) => {
413414
self.resolve_ns(&mut info.ty, Ns::Type)?;
414415
}
@@ -486,6 +487,18 @@ impl<'a> Resolver<'a> {
486487
Ok(())
487488
}
488489

490+
fn ref_type(&mut self, ty: &mut ValType<'a>) -> Result<(), Error> {
491+
Ok(match ty {
492+
ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => {}
493+
ValType::Ref(r) => match &mut r.heap {
494+
core::HeapType::Abstract { .. } => {}
495+
core::HeapType::Concrete(id) | core::HeapType::Exact(id) => {
496+
self.resolve_ns(id, Ns::Type)?;
497+
}
498+
},
499+
})
500+
}
501+
489502
fn canon_opts(&mut self, opts: &mut [CanonOpt<'a>]) -> Result<(), Error> {
490503
for opt in opts {
491504
match opt {
@@ -658,15 +671,7 @@ impl<'a> Resolver<'a> {
658671
self.stack.pop();
659672
}
660673
TypeDef::Resource(r) => {
661-
match &mut r.rep {
662-
ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => {}
663-
ValType::Ref(r) => match &mut r.heap {
664-
core::HeapType::Abstract { .. } => {}
665-
core::HeapType::Concrete(id) | core::HeapType::Exact(id) => {
666-
self.resolve_ns(id, Ns::Type)?;
667-
}
668-
},
669-
}
674+
self.ref_type(&mut r.rep)?;
670675
if let Some(dtor) = &mut r.dtor {
671676
self.core_item_ref(dtor)?;
672677
}

crates/wit-component/src/encoding.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,12 +1977,12 @@ impl<'a> EncodingState<'a> {
19771977
let index = self.component.waitable_join();
19781978
Ok((ExportKind::Func, index))
19791979
}
1980-
Import::ContextGet(n) => {
1981-
let index = self.component.context_get(*n);
1980+
Import::ContextGet { ty, slot } => {
1981+
let index = self.component.context_get((*ty).try_into()?, *slot);
19821982
Ok((ExportKind::Func, index))
19831983
}
1984-
Import::ContextSet(n) => {
1985-
let index = self.component.context_set(*n);
1984+
Import::ContextSet { ty, slot } => {
1985+
let index = self.component.context_set((*ty).try_into()?, *slot);
19861986
Ok((ExportKind::Func, index))
19871987
}
19881988
Import::ExportedTaskCancel => {
@@ -2630,8 +2630,8 @@ impl<'a> Shims<'a> {
26302630
| Import::WaitableSetNew
26312631
| Import::WaitableSetDrop
26322632
| Import::WaitableJoin
2633-
| Import::ContextGet(_)
2634-
| Import::ContextSet(_)
2633+
| Import::ContextGet { .. }
2634+
| Import::ContextSet { .. }
26352635
| Import::ThreadIndex
26362636
| Import::ThreadSuspendToSuspended { .. }
26372637
| Import::ThreadSuspend { .. }

0 commit comments

Comments
 (0)