Skip to content

Commit 0b4c754

Browse files
authored
Exception and control tags (#10251)
* Tags * Tag tests * Tests * Refer to tags issue * Engine index * Simplify * Fix clippy warnings
1 parent fb7dd61 commit 0b4c754

File tree

25 files changed

+649
-46
lines changed

25 files changed

+649
-46
lines changed

crates/c-api/src/extern.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t {
2323
Extern::SharedMemory(_) => panic!(
2424
"Shared Memory no implemented for wasm_* types. Please use wasmtime_* types instead"
2525
),
26+
Extern::Tag(_) => todo!(), // FIXME: #10252 C embedder API for exceptions and control tags.
2627
}
2728
}
2829

@@ -143,6 +144,7 @@ impl From<Extern> for wasmtime_extern_t {
143144
sharedmemory: ManuallyDrop::new(Box::new(sharedmemory)),
144145
},
145146
},
147+
Extern::Tag(_) => todo!(), // FIXME: #10252 C embedder API for exceptions and control tags.
146148
}
147149
}
148150
}

crates/c-api/src/types/extern.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ impl CExternType {
2525
ExternType::Global(f) => CExternType::Global(CGlobalType::new(f)),
2626
ExternType::Memory(f) => CExternType::Memory(CMemoryType::new(f)),
2727
ExternType::Table(f) => CExternType::Table(CTableType::new(f)),
28+
ExternType::Tag(_) => todo!(), // FIXME: #10252 C embedder API for exceptions and control tags.
2829
}
2930
}
3031
}

crates/environ/src/compile/module_environ.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use crate::{
77
ConstExpr, ConstOp, DataIndex, DefinedFuncIndex, ElemIndex, EngineOrModuleTypeIndex,
88
EntityIndex, EntityType, FuncIndex, GlobalIndex, IndexType, InitMemory, MemoryIndex,
99
ModuleInternedTypeIndex, ModuleTypesBuilder, PrimaryMap, SizeOverflow, StaticMemoryInitializer,
10-
TableIndex, TableInitialValue, Tunables, TypeConvert, TypeIndex, Unsigned, WasmError,
11-
WasmHeapTopType, WasmHeapType, WasmResult, WasmValType, WasmparserTypeConverter,
10+
TableIndex, TableInitialValue, Tag, TagIndex, Tunables, TypeConvert, TypeIndex, Unsigned,
11+
WasmError, WasmHeapTopType, WasmHeapType, WasmResult, WasmValType, WasmparserTypeConverter,
1212
};
1313
use anyhow::{bail, Result};
1414
use cranelift_entity::packed_option::ReservedValue;
@@ -318,9 +318,13 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
318318
self.result.module.num_imported_tables += 1;
319319
EntityType::Table(self.convert_table_type(&ty)?)
320320
}
321-
322-
// doesn't get past validation
323-
TypeRef::Tag(_) => unreachable!(),
321+
TypeRef::Tag(ty) => {
322+
let index = TypeIndex::from_u32(ty.func_type_idx);
323+
let signature = self.result.module.types[index];
324+
let tag = Tag { signature };
325+
self.result.module.num_imported_tags += 1;
326+
EntityType::Tag(tag)
327+
}
324328
};
325329
self.declare_import(import.module, import.name, ty);
326330
}
@@ -384,9 +388,12 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
384388
Payload::TagSection(tags) => {
385389
self.validator.tag_section(&tags)?;
386390

387-
// This feature isn't enabled at this time, so we should
388-
// never get here.
389-
unreachable!();
391+
for entry in tags {
392+
let sigindex = entry?.func_type_idx;
393+
let ty = TypeIndex::from_u32(sigindex);
394+
let interned_index = self.result.module.types[ty];
395+
self.result.module.push_tag(interned_index);
396+
}
390397
}
391398

392399
Payload::GlobalSection(globals) => {
@@ -424,9 +431,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
424431
ExternalKind::Table => EntityIndex::Table(TableIndex::from_u32(index)),
425432
ExternalKind::Memory => EntityIndex::Memory(MemoryIndex::from_u32(index)),
426433
ExternalKind::Global => EntityIndex::Global(GlobalIndex::from_u32(index)),
427-
428-
// this never gets past validation
429-
ExternalKind::Tag => unreachable!(),
434+
ExternalKind::Tag => EntityIndex::Tag(TagIndex::from_u32(index)),
430435
};
431436
self.result
432437
.module
@@ -770,7 +775,7 @@ and for re-adding support for interface types you can see this issue:
770775
EntityType::Table(ty) => EntityIndex::Table(self.result.module.tables.push(ty)),
771776
EntityType::Memory(ty) => EntityIndex::Memory(self.result.module.memories.push(ty)),
772777
EntityType::Global(ty) => EntityIndex::Global(self.result.module.globals.push(ty)),
773-
EntityType::Tag(_) => unimplemented!(),
778+
EntityType::Tag(ty) => EntityIndex::Tag(self.result.module.tags.push(ty)),
774779
}
775780
}
776781

crates/environ/src/component/translate/inline.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,7 @@ impl<'a> Inliner<'a> {
12291229
EntityIndex::Table(i) => frame.tables[i].clone().into(),
12301230
EntityIndex::Global(i) => frame.globals[i].clone().into(),
12311231
EntityIndex::Memory(i) => frame.memories[i].clone().into(),
1232+
EntityIndex::Tag(_) => todo!(), // FIXME: #10252 support for tags in the component model
12321233
},
12331234
}
12341235
}

crates/environ/src/module.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ pub struct Module {
333333
/// Number of imported or aliased globals in the module.
334334
pub num_imported_globals: usize,
335335

336+
/// Number of imported or aliased tags in the module.
337+
pub num_imported_tags: usize,
338+
336339
/// Number of functions that "escape" from this module may need to have a
337340
/// `VMFuncRef` constructed for them.
338341
///
@@ -354,6 +357,9 @@ pub struct Module {
354357

355358
/// WebAssembly global initializers for locally-defined globals.
356359
pub global_initializers: PrimaryMap<DefinedGlobalIndex, ConstExpr>,
360+
361+
/// WebAssembly exception and control tags.
362+
pub tags: PrimaryMap<TagIndex, Tag>,
357363
}
358364

359365
/// Initialization routines for creating an instance, encompassing imports,
@@ -500,6 +506,29 @@ impl Module {
500506
index.index() < self.num_imported_globals
501507
}
502508

509+
/// Test whether the given tag index is for an imported tag.
510+
#[inline]
511+
pub fn is_imported_tag(&self, index: TagIndex) -> bool {
512+
index.index() < self.num_imported_tags
513+
}
514+
515+
/// Convert a `DefinedTagIndex` into a `TagIndex`.
516+
#[inline]
517+
pub fn tag_index(&self, defined_tag: DefinedTagIndex) -> TagIndex {
518+
TagIndex::new(self.num_imported_tags + defined_tag.index())
519+
}
520+
521+
/// Convert a `TagIndex` into a `DefinedTagIndex`. Returns None if the
522+
/// index is an imported tag.
523+
#[inline]
524+
pub fn defined_tag_index(&self, tag: TagIndex) -> Option<DefinedTagIndex> {
525+
if tag.index() < self.num_imported_tags {
526+
None
527+
} else {
528+
Some(DefinedTagIndex::new(tag.index() - self.num_imported_tags))
529+
}
530+
}
531+
503532
/// Returns an iterator of all the imports in this module, along with their
504533
/// module name, field name, and type that's being imported.
505534
pub fn imports(&self) -> impl ExactSizeIterator<Item = (&str, &str, EntityType)> {
@@ -517,9 +546,16 @@ impl Module {
517546
EntityIndex::Table(i) => EntityType::Table(self.tables[i]),
518547
EntityIndex::Memory(i) => EntityType::Memory(self.memories[i]),
519548
EntityIndex::Function(i) => EntityType::Function(self.functions[i].signature),
549+
EntityIndex::Tag(i) => EntityType::Tag(self.tags[i]),
520550
}
521551
}
522552

553+
/// Appends a new tag to this module with the given type information.
554+
pub fn push_tag(&mut self, signature: impl Into<EngineOrModuleTypeIndex>) -> TagIndex {
555+
let signature = signature.into();
556+
self.tags.push(Tag { signature })
557+
}
558+
523559
/// Appends a new function to this module with the given type information,
524560
/// used for functions that either don't escape or aren't certain whether
525561
/// they escape yet.
@@ -548,6 +584,12 @@ impl Module {
548584
pub fn num_defined_memories(&self) -> usize {
549585
self.memories.len() - self.num_imported_memories
550586
}
587+
588+
/// Returns the number of tags defined by this module itself: all tags
589+
/// minus imported tags.
590+
pub fn num_defined_tags(&self) -> usize {
591+
self.tags.len() - self.num_imported_tags
592+
}
551593
}
552594

553595
impl TypeTrace for Module {
@@ -572,12 +614,14 @@ impl TypeTrace for Module {
572614
num_imported_tables: _,
573615
num_imported_memories: _,
574616
num_imported_globals: _,
617+
num_imported_tags: _,
575618
num_escaped_funcs: _,
576619
functions,
577620
tables,
578621
memories: _,
579622
globals,
580623
global_initializers: _,
624+
tags,
581625
} = self;
582626

583627
for t in types.values().copied() {
@@ -592,6 +636,9 @@ impl TypeTrace for Module {
592636
for g in globals.values() {
593637
g.trace(func)?;
594638
}
639+
for t in tags.values() {
640+
t.trace(func)?;
641+
}
595642
Ok(())
596643
}
597644

@@ -616,12 +663,14 @@ impl TypeTrace for Module {
616663
num_imported_tables: _,
617664
num_imported_memories: _,
618665
num_imported_globals: _,
666+
num_imported_tags: _,
619667
num_escaped_funcs: _,
620668
functions,
621669
tables,
622670
memories: _,
623671
globals,
624672
global_initializers: _,
673+
tags,
625674
} = self;
626675

627676
for t in types.values_mut() {
@@ -636,6 +685,9 @@ impl TypeTrace for Module {
636685
for g in globals.values_mut() {
637686
g.trace_mut(func)?;
638687
}
688+
for t in tags.values_mut() {
689+
t.trace_mut(func)?;
690+
}
639691
Ok(())
640692
}
641693
}

crates/environ/src/types.rs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,11 @@ entity_impl!(DataIndex);
13151315
pub struct ElemIndex(u32);
13161316
entity_impl!(ElemIndex);
13171317

1318+
/// Index type of a defined tag inside the WebAssembly module.
1319+
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1320+
pub struct DefinedTagIndex(u32);
1321+
entity_impl!(DefinedTagIndex);
1322+
13181323
/// Index type of an event inside the WebAssembly module.
13191324
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
13201325
pub struct TagIndex(u32);
@@ -1339,6 +1344,8 @@ pub enum EntityIndex {
13391344
Memory(MemoryIndex),
13401345
/// Global index.
13411346
Global(GlobalIndex),
1347+
/// Tag index.
1348+
Tag(TagIndex),
13421349
}
13431350

13441351
impl From<FuncIndex> for EntityIndex {
@@ -1365,6 +1372,12 @@ impl From<GlobalIndex> for EntityIndex {
13651372
}
13661373
}
13671374

1375+
impl From<TagIndex> for EntityIndex {
1376+
fn from(idx: TagIndex) -> EntityIndex {
1377+
EntityIndex::Tag(idx)
1378+
}
1379+
}
1380+
13681381
/// A type of an item in a wasm module where an item is typically something that
13691382
/// can be exported.
13701383
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -1373,7 +1386,7 @@ pub enum EntityType {
13731386
Global(Global),
13741387
/// A linear memory with the specified limits
13751388
Memory(Memory),
1376-
/// An event definition.
1389+
/// An exception and control tag definition.
13771390
Tag(Tag),
13781391
/// A table with the specified element type and limits
13791392
Table(Table),
@@ -1391,7 +1404,8 @@ impl TypeTrace for EntityType {
13911404
Self::Global(g) => g.trace(func),
13921405
Self::Table(t) => t.trace(func),
13931406
Self::Function(idx) => func(*idx),
1394-
Self::Memory(_) | Self::Tag(_) => Ok(()),
1407+
Self::Memory(_) => Ok(()),
1408+
Self::Tag(t) => t.trace(func),
13951409
}
13961410
}
13971411

@@ -1403,7 +1417,8 @@ impl TypeTrace for EntityType {
14031417
Self::Global(g) => g.trace_mut(func),
14041418
Self::Table(t) => t.trace_mut(func),
14051419
Self::Function(idx) => func(idx),
1406-
Self::Memory(_) | Self::Tag(_) => Ok(()),
1420+
Self::Memory(_) => Ok(()),
1421+
Self::Tag(t) => t.trace_mut(func),
14071422
}
14081423
}
14091424
}
@@ -1933,20 +1948,26 @@ impl From<wasmparser::MemoryType> for Memory {
19331948
}
19341949
}
19351950

1936-
/// WebAssembly event.
1951+
/// WebAssembly exception and control tag.
19371952
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
19381953
pub struct Tag {
1939-
/// The event signature type.
1940-
pub ty: TypeIndex,
1954+
/// The tag signature type.
1955+
pub signature: EngineOrModuleTypeIndex,
19411956
}
19421957

1943-
impl From<wasmparser::TagType> for Tag {
1944-
fn from(ty: wasmparser::TagType) -> Tag {
1945-
match ty.kind {
1946-
wasmparser::TagKind::Exception => Tag {
1947-
ty: TypeIndex::from_u32(ty.func_type_idx),
1948-
},
1949-
}
1958+
impl TypeTrace for Tag {
1959+
fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
1960+
where
1961+
F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
1962+
{
1963+
func(self.signature)
1964+
}
1965+
1966+
fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
1967+
where
1968+
F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
1969+
{
1970+
func(&mut self.signature)
19501971
}
19511972
}
19521973

0 commit comments

Comments
 (0)