diff --git a/src/Config.cs b/src/Config.cs
index 273bb147..e22974d9 100644
--- a/src/Config.cs
+++ b/src/Config.cs
@@ -257,6 +257,17 @@ public Config WithWideArithmetic(bool enable)
return this;
}
+ ///
+ /// Configures whether the WebAssembly exceptions proposal is enabled.
+ ///
+ /// True to enable exceptions or false to disable.
+ /// Returns the current config.
+ public Config WithExceptions(bool enable)
+ {
+ Native.wasmtime_config_wasm_exceptions_set(handle, enable);
+ return this;
+ }
+
///
/// Sets whether the WebAssembly stack switching proposal is enabled.
///
@@ -264,7 +275,7 @@ public Config WithWideArithmetic(bool enable)
/// Returns the current config.
private Config WithStackSwitching(bool enable)
{
- // todo: unlikely to be compatible with wasmtime-dotnet on Windows due to threads
+ // warning: **unlikely to be ever compatible with wasmtime-dotnet on Windows due to fibers**
Native.wasmtime_config_wasm_stack_switching_set(handle, enable);
return this;
@@ -632,6 +643,9 @@ private static class Native
[DllImport(Engine.LibraryName)]
public static extern void wasmtime_config_wasm_component_model_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool value);
+ [DllImport(Engine.LibraryName)]
+ public static extern void wasmtime_config_wasm_exceptions_set(Handle config, [MarshalAs(UnmanagedType.I1)] bool value);
+
// todo: void wasmtime_config_host_memory_creator_set(wasm_config_t *, wasmtime_memory_creator_t *)
}
diff --git a/src/Export.cs b/src/Export.cs
index 06e4b6f3..56dc99bb 100644
--- a/src/Export.cs
+++ b/src/Export.cs
@@ -23,19 +23,20 @@ public Export[] ToExportArray()
}
var exports = new Export[(int)this.size];
- for (int i = 0; i < (int)this.size; ++i)
+ for (var i = 0; i < (int)this.size; ++i)
{
var exportType = this.data[i];
var externType = Native.wasm_exporttype_type(exportType);
- exports[i] = (WasmExternKind)Native.wasm_externtype_kind(externType) switch
+ var kind = (WasmExternKind)Native.wasm_externtype_kind(externType);
+ exports[i] = kind switch
{
WasmExternKind.Func => new FunctionExport(exportType, externType),
WasmExternKind.Global => new GlobalExport(exportType, externType),
WasmExternKind.Table => new TableExport(exportType, externType),
WasmExternKind.Memory => new MemoryExport(exportType, externType),
-
- _ => throw new NotSupportedException("Unsupported export extern type.")
+ WasmExternKind.Tag => new TagExport(exportType, externType),
+ _ => throw new NotSupportedException($"Unsupported export extern type: {kind}.")
};
}
@@ -254,4 +255,45 @@ internal static class Native
public static extern IntPtr wasm_externtype_as_tabletype_const(IntPtr type);
}
}
-}
+
+ ///
+ /// Represents a tag exported from a WebAssembly module or instance.
+ ///
+ public class TagExport
+ : Export
+ {
+ ///
+ /// Parameter types of this tag
+ ///
+ public ValueKind[] Parameters { get; set; }
+
+ internal TagExport(IntPtr exportType, IntPtr externType) : base(exportType)
+ {
+ var tagType = Native.wasm_externtype_as_tagtype_const(externType);
+ if (tagType == IntPtr.Zero)
+ {
+ throw new InvalidOperationException();
+ }
+
+ var funcType = Native.wasm_tagtype_functype(tagType);
+ if (funcType == IntPtr.Zero)
+ {
+ throw new InvalidOperationException();
+ }
+
+ unsafe
+ {
+ Parameters = (*Function.Native.wasm_functype_params(funcType)).ToArray();
+ }
+ }
+
+ internal static class Native
+ {
+ [DllImport(Engine.LibraryName)]
+ public static extern IntPtr wasm_externtype_as_tagtype_const(IntPtr type);
+
+ [DllImport(Engine.LibraryName)]
+ public static extern IntPtr wasm_tagtype_functype(IntPtr tagType);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Import.cs b/src/Import.cs
index f21b3649..b35ac440 100644
--- a/src/Import.cs
+++ b/src/Import.cs
@@ -8,10 +8,11 @@ namespace Wasmtime
// in the Wasmtime API soon. The difference is the order of `Module` and `Instance`.
internal enum WasmExternKind : byte
{
- Func,
- Global,
- Table,
- Memory,
+ Func = 0,
+ Global = 1,
+ Table = 2,
+ Memory = 3,
+ Tag = 4,
}
[StructLayout(LayoutKind.Sequential)]
@@ -36,18 +37,20 @@ public Import[] ToImportArray()
}
var imports = new Import[(int)this.size];
- for (int i = 0; i < (int)this.size; ++i)
+ for (var i = 0; i < (int)this.size; ++i)
{
var importType = this.data[i];
var externType = Native.wasm_importtype_type(importType);
- imports[i] = (WasmExternKind)ExportTypeArray.Native.wasm_externtype_kind(externType) switch
+ var kind = (WasmExternKind)ExportTypeArray.Native.wasm_externtype_kind(externType);
+ imports[i] = kind switch
{
WasmExternKind.Func => new FunctionImport(importType, externType),
WasmExternKind.Global => new GlobalImport(importType, externType),
WasmExternKind.Table => new TableImport(importType, externType),
WasmExternKind.Memory => new MemoryImport(importType, externType),
- _ => throw new NotSupportedException("Unsupported import extern type.")
+ WasmExternKind.Tag => new TagImport(importType, externType),
+ _ => throw new NotSupportedException($"Unsupported import extern type: {kind}.")
};
}
return imports;
@@ -77,14 +80,9 @@ internal Import(IntPtr importType)
: Extensions.PtrToStringUTF8((IntPtr)moduleName->data, checked((int)moduleName->size));
var name = Native.wasm_importtype_name(importType);
- if (name is null || name->size == 0)
- {
- Name = String.Empty;
- }
- else
- {
- Name = Extensions.PtrToStringUTF8((IntPtr)name->data, checked((int)name->size));
- }
+ Name = name is null || name->size == 0
+ ? string.Empty
+ : Extensions.PtrToStringUTF8((IntPtr)name->data, checked((int)name->size));
}
}
@@ -260,4 +258,37 @@ internal TableImport(IntPtr importType, IntPtr externType) : base(importType)
///
public uint Maximum { get; private set; }
}
+
+ ///
+ /// Represents a tag imported to a WebAssembly module or instance.
+ ///
+ public class TagImport
+ : Import
+ {
+ ///
+ /// Parameter types of this tag
+ ///
+ public ValueKind[] Parameters { get; set; }
+
+ internal TagImport(IntPtr exportType, IntPtr externType)
+ : base(exportType)
+ {
+ var tagType = TagExport.Native.wasm_externtype_as_tagtype_const(externType);
+ if (tagType == IntPtr.Zero)
+ {
+ throw new InvalidOperationException();
+ }
+
+ var funcType = TagExport.Native.wasm_tagtype_functype(tagType);
+ if (funcType == IntPtr.Zero)
+ {
+ throw new InvalidOperationException();
+ }
+
+ unsafe
+ {
+ Parameters = (*Function.Native.wasm_functype_params(funcType)).ToArray();
+ }
+ }
+ }
}
diff --git a/tests/ExportTagsTests.cs b/tests/ExportTagsTests.cs
new file mode 100644
index 00000000..c07a351c
--- /dev/null
+++ b/tests/ExportTagsTests.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Linq;
+using Xunit;
+
+namespace Wasmtime.Tests;
+
+public class ExportTagsFixture
+ : ModuleFixture
+{
+ protected override string ModuleFileName => "ExportTags.wat";
+
+ public override Config GetEngineConfig()
+ {
+ return base.GetEngineConfig()
+ .WithExceptions(true);
+ }
+}
+
+public sealed class ExportTagsTests
+ : IClassFixture, IDisposable
+{
+ private ExportTagsFixture Fixture { get; set; }
+
+ private Store Store { get; set; }
+
+ private Linker Linker { get; set; }
+
+ public ExportTagsTests(ExportTagsFixture fixture)
+ {
+ Fixture = fixture;
+ Store = new Store(Fixture.Engine);
+ Linker = new Linker(Fixture.Engine);
+ }
+
+ public void Dispose()
+ {
+ Store.Dispose();
+ Linker.Dispose();
+ }
+
+ [Fact]
+ public void ItExportsTags()
+ {
+ Assert.Single(Fixture.Module.Exports);
+
+ var export = (TagExport)Fixture.Module.Exports.Single();
+
+ Assert.Equal("$export_tag", export.Name);
+
+ Assert.Single(export.Parameters);
+ Assert.Equal(ValueKind.Int32, export.Parameters.Single());
+ }
+
+ [Fact]
+ public void ItImportsTags()
+ {
+ Assert.Single(Fixture.Module.Imports);
+
+ var export = (TagImport)Fixture.Module.Imports.Single();
+
+ Assert.Equal("$import_tag", export.Name);
+
+ Assert.Single(export.Parameters);
+ Assert.Equal(ValueKind.Int32, export.Parameters.Single());
+ }
+}
\ No newline at end of file
diff --git a/tests/Modules/ExportTags.wat b/tests/Modules/ExportTags.wat
new file mode 100644
index 00000000..0c790f8d
--- /dev/null
+++ b/tests/Modules/ExportTags.wat
@@ -0,0 +1,10 @@
+(module
+ ;; import a tag from the host
+ (import "test" "$import_tag" (tag $import_tag (param i32)))
+
+ ;; Define a tag
+ (tag $export_tag (param i32))
+
+ ;; export the tag
+ (export "$export_tag" (tag $export_tag))
+)
\ No newline at end of file