diff --git a/Directory.Build.props b/Directory.Build.props
index 65eb7e5b..a0c461ff 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -6,4 +6,7 @@
$(WasmtimeVersion)$(WasmtimeDotnetVersion)-dev
$(WasmtimeVersion)$(WasmtimeDotnetVersion)
-
\ No newline at end of file
+
+ $(DefineConstants);WASMTIME_DEV
+
+
diff --git a/README.md b/README.md
index e0828d04..071fdc87 100644
--- a/README.md
+++ b/README.md
@@ -112,6 +112,18 @@ $ dotnet build Wasmtime.sln
This will download the latest development snapshot of Wasmtime for your
platform.
+By default, local builds set `DevBuild=true`, which uses the dev C API artifacts
+(`wasmtime-dev-*`) and enables a `WASMTIME_DEV` build define to match the dev
+ABI (value/trap layouts). To build against the stable Wasmtime release instead,
+override the flag:
+
+```
+$ dotnet build Wasmtime.sln -p:DevBuild=false
+```
+
+If you switch between `DevBuild=true` and `DevBuild=false`, you may need to
+delete `src/obj` to force the correct C API download.
+
### Testing
Use `dotnet` to run the unit tests:
diff --git a/src/TrapException.cs b/src/TrapException.cs
index a158dd0d..ede5f2ad 100644
--- a/src/TrapException.cs
+++ b/src/TrapException.cs
@@ -37,8 +37,112 @@ public enum TrapCode
Unreachable = 9,
/// The trap was the result of interrupting execution.
Interrupt = 10,
+#if WASMTIME_DEV
+ /// The trap was the result of running out of the configured fuel amount.
+ OutOfFuel = 11,
+ ///
+ /// The trap was the result of atomic wait operations on non-shared memory.
+ ///
+ AtomicWaitNonSharedMemory = 12,
+ ///
+ /// The trap was the result of a call to a null reference.
+ ///
+ NullReference = 13,
+ ///
+ /// The trap was the result of an attempt to access beyond the bounds of an array.
+ ///
+ ArrayOutOfBounds = 14,
+ ///
+ /// The trap was the result of an allocation that was too large to succeed.
+ ///
+ AllocationTooLarge = 15,
+ ///
+ /// The trap was the result of an attempt to cast a reference to a type that it is not an instance of.
+ ///
+ CastFailure = 16,
+ ///
+ /// The trap was the result of a component calling another component that would have violated the reentrance rules.
+ ///
+ CannotEnterComponent = 17,
+ ///
+ /// The trap was the result of an async-lifted export failing to return a valid async result.
+ ///
+ ///
+ /// An async-lifted export failed to produce a result by calling `task.return` before returning `STATUS_DONE`
+ /// and/or after all host tasks completed.
+ ///
+ NoAsyncResult = 18,
+ ///
+ /// The trap was the result of suspending to a tag for which there is no active handler.
+ ///
+ UnhandledTag = 19,
+ ///
+ /// The trap was the result of an attempt to resume a continuation twice.
+ ///
+ ContinuationAlreadyConsumed = 20,
+ ///
+ /// The trap was the result of a Pulley opcode executed at runtime when the opcode was disabled at compile time.
+ ///
+ DisabledOpCode = 21,
+ ///
+ /// The trap was the result of an async event loop deadlock.
+ ///
+ ///
+ /// The async event loop cannot make further progress given that all host tasks have completed
+ /// and any/all host-owned stream/future handles have been dropped.
+ ///
+ AsyncDeadlock = 22,
+ ///
+ /// The trap was the result of a component instance trying to call an import or intrinsic when not allowed.
+ ///
+ ///
+ /// When the component-model feature is enabled this trap represents a scenario where a component instance
+ /// tried to call an import or intrinsic when it wasn't allowed to, e.g. from a post-return function.
+ ///
+ CannotLeaveComponent = 23,
+ ///
+ /// The trap was the result of a synchronous task attempting to make a potentially blocking call prior to returning.
+ ///
+ CannotBlockSyncTask = 24,
+ ///
+ /// The trap was the result of a component trying to lift a char with an invalid bit pattern.
+ ///
+ InvalidChar = 25,
+ ///
+ /// Debug assertion generated for a fused adapter regarding the expected completion of a string encoding operation.
+ ///
+ DebugAssertStringEncodingFinished = 26,
+ ///
+ /// Debug assertion generated for a fused adapter regarding a string encoding operation.
+ ///
+ DebugAssertEqualCodeUnits = 27,
+ ///
+ /// Debug assertion generated for a fused adapter regarding the alignment of a pointer.
+ ///
+ DebugAssertPointerAligned = 28,
+ ///
+ /// Debug assertion generated for a fused adapter regarding the upper bits of a 64-bit value.
+ ///
+ DebugAssertUpperBitsUnset = 29,
+ ///
+ /// The trap was the result of a component trying to lift or lower a string past the end of its memory.
+ ///
+ StringOutOfBounds = 30,
+ ///
+ /// The trap was the result of a component trying to lift or lower a list past the end of its memory.
+ ///
+ ListOutOfBounds = 31,
+ ///
+ /// The trap was the result of a component using an invalid discriminant when lowering a variant value.
+ ///
+ InvalidDiscriminant = 32,
+ ///
+ /// The trap was the result of a component passing an unaligned pointer when lifting or lowering a value.
+ ///
+ UnalignedPointer = 33
+#else
///
- /// The trap was the result of executing a function that was `canon lift`'d, then `canonlower`'d, then called.
+ /// The trap was the result of executing a function that was `canon lift`'d, then `canonlower`'d, then called.
///
///
/// When the component model feature is enabled this trap represents a function that was `canon lift`'d,
@@ -84,6 +188,7 @@ public enum TrapCode
/// The trap was the result of a Pulley opcode executed at runtime when the opcode was disabled at compile time.
///
DisabledOpCode = 20
+#endif
}
///
diff --git a/src/Value.cs b/src/Value.cs
index eff55005..876b5f8a 100644
--- a/src/Value.cs
+++ b/src/Value.cs
@@ -212,9 +212,27 @@ private static class Native
/// .
///
///
+#if WASMTIME_DEV
+ [StructLayout(LayoutKind.Explicit, Size = 32)]
+ internal struct Value
+ {
+ static Value()
+ {
+ // Ensure the struct size matches the expected wasmtime_val_t size.
+ System.Diagnostics.Debug.Assert(Marshal.SizeOf(typeof(Value)) == 32,
+ $"Value struct size mismatch: expected 32, got {Marshal.SizeOf(typeof(Value))}");
+ }
+#else
[StructLayout(LayoutKind.Sequential)]
internal struct Value
{
+ static Value()
+ {
+ // Ensure the struct size matches the expected wasmtime_val_t size.
+ System.Diagnostics.Debug.Assert(Marshal.SizeOf(typeof(Value)) == 24,
+ $"Value struct size mismatch: expected 24, got {Marshal.SizeOf(typeof(Value))}");
+ }
+#endif
public void Release(Store store)
{
Native.wasmtime_val_unroot(store.Context.handle, this);
@@ -490,9 +508,16 @@ public static class Native
}
public static readonly Native.Finalizer Finalizer = (p) => GCHandle.FromIntPtr(p).Free();
+#if WASMTIME_DEV
+ [FieldOffset(0)]
+ private ValueKind kind;
+ [FieldOffset(8)]
+ private ValueUnion of;
+#else
private ValueKind kind;
private ValueUnion of;
+#endif
}
[StructLayout(LayoutKind.Explicit)]
@@ -523,9 +548,40 @@ internal unsafe struct ValueUnion
public V128 v128;
}
+#if WASMTIME_DEV
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct AnyRef
+ {
+ static AnyRef() => System.Diagnostics.Debug.Assert(Marshal.SizeOf(typeof(AnyRef)) == 24);
+
+ public ulong store;
+
+ private uint __private1;
+
+ private uint __private2;
+
+ private IntPtr __private3;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct ExternRef
+ {
+ static ExternRef() => System.Diagnostics.Debug.Assert(Marshal.SizeOf(typeof(ExternRef)) == 24);
+
+ public ulong store;
+
+ private uint __private1;
+
+ private uint __private2;
+
+ private IntPtr __private3;
+ }
+#else
[StructLayout(LayoutKind.Sequential)]
internal struct AnyRef
{
+ static AnyRef() => System.Diagnostics.Debug.Assert(Marshal.SizeOf(typeof(AnyRef)) == 16);
+
public ulong store;
private uint __private1;
@@ -536,10 +592,13 @@ internal struct AnyRef
[StructLayout(LayoutKind.Sequential)]
internal struct ExternRef
{
+ static ExternRef() => System.Diagnostics.Debug.Assert(Marshal.SizeOf(typeof(ExternRef)) == 16);
+
public ulong store;
private uint __private1;
private uint __private2;
}
+#endif
}