Add a wasmtime-specific wasmtime_wat2wasm C API (#1206)

* Add a wasmtime-specific `wasmtime_wat2wasm` C API

This commit implements a wasmtime-specific C API for converting the text
format to the binary format. An upstream spec issue exists for adding
this to the C API, but in the meantime we can experiment with our own
version of this API and use it in the C# extension, for example!

Closes #1000

* Reorder arguments

* Use wasm_byte_vec_t for input `*.wat`

* Mark wat input as const

* Return an error message and use `fixed`

* Actually include the error message

* Use `fixed` in `Module.cs` as well
This commit is contained in:
Alex Crichton
2020-03-03 10:29:20 -06:00
committed by GitHub
parent 732c646bec
commit 77e17d8f71
38 changed files with 118 additions and 30 deletions

View File

@@ -1,4 +1,6 @@
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace Wasmtime
{
@@ -40,6 +42,34 @@ namespace Wasmtime
return new Store(this);
}
/// <summary>
/// Converts the WebAssembly text format to the binary format
/// </summary>
/// <returns>Returns the binary-encoded wasm module.</returns>
public byte[] WatToWasm(string wat)
{
var watBytes = Encoding.UTF8.GetBytes(wat);
unsafe
{
fixed (byte *ptr = watBytes)
{
Interop.wasm_byte_vec_t watByteVec;
watByteVec.size = (UIntPtr)watBytes.Length;
watByteVec.data = ptr;
if (!Interop.wasmtime_wat2wasm(Handle, ref watByteVec, out var bytes, out var error)) {
var errorSpan = new ReadOnlySpan<byte>(error.data, checked((int)error.size));
var message = Encoding.UTF8.GetString(errorSpan);
Interop.wasm_byte_vec_delete(ref error);
throw new WasmtimeException("failed to parse input wat: " + message);
}
var byteSpan = new ReadOnlySpan<byte>(bytes.data, checked((int)bytes.size));
var ret = byteSpan.ToArray();
Interop.wasm_byte_vec_delete(ref bytes);
return ret;
}
}
}
/// <inheritdoc/>
public void Dispose()
{

View File

@@ -899,7 +899,7 @@ namespace Wasmtime
public static extern bool wasi_config_set_stdin_file(
WasiConfigHandle config,
[MarshalAs(UnmanagedType.LPUTF8Str)] string path
);
);
[DllImport(LibraryName)]
public static extern void wasi_config_inherit_stdin(WasiConfigHandle config);
@@ -909,7 +909,7 @@ namespace Wasmtime
public static extern bool wasi_config_set_stdout_file(
WasiConfigHandle config,
[MarshalAs(UnmanagedType.LPUTF8Str)] string path
);
);
[DllImport(LibraryName)]
public static extern void wasi_config_inherit_stdout(WasiConfigHandle config);
@@ -919,7 +919,7 @@ namespace Wasmtime
public static extern bool wasi_config_set_stderr_file(
WasiConfigHandle config,
[MarshalAs(UnmanagedType.LPUTF8Str)] string path
);
);
[DllImport(LibraryName)]
public static extern void wasi_config_inherit_stderr(WasiConfigHandle config);
@@ -974,5 +974,14 @@ namespace Wasmtime
[DllImport(LibraryName)]
public static extern void wasmtime_config_cranelift_opt_level_set(WasmConfigHandle config, wasmtime_opt_level_t level);
[DllImport(LibraryName, CharSet=CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool wasmtime_wat2wasm(
EngineHandle engine,
ref wasm_byte_vec_t wat,
out wasm_byte_vec_t vec,
out wasm_byte_vec_t error_message
);
}
}

View File

@@ -15,15 +15,13 @@ namespace Wasmtime
throw new ArgumentNullException(nameof(store));
}
var bytesHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
unsafe
{
unsafe
fixed (byte *ptr = bytes)
{
Interop.wasm_byte_vec_t vec;
vec.size = (UIntPtr)bytes.Length;
vec.data = (byte*)bytesHandle.AddrOfPinnedObject();
vec.data = ptr;
Handle = Interop.wasm_module_new(store.Handle, ref vec);
}
@@ -33,10 +31,6 @@ namespace Wasmtime
throw new WasmtimeException($"WebAssembly module '{name}' is not valid.");
}
}
finally
{
bytesHandle.Free();
}
Store = store;
Name = name;

View File

@@ -13,7 +13,9 @@ namespace Wasmtime.Tests
.WithReferenceTypes(true)
.Build();
Store = Engine.CreateStore();
Module = Store.CreateModule(Path.Combine("Modules", ModuleFileName));
var wat = Path.Combine("Modules", ModuleFileName);
var wasm = Engine.WatToWasm(File.ReadAllText(wat));
Module = Store.CreateModule(wat, wasm);
}
public void Dispose()

View File

@@ -8,7 +8,7 @@ namespace Wasmtime.Tests
{
public class FunctionExportsFixture : ModuleFixture
{
protected override string ModuleFileName => "FunctionExports.wasm";
protected override string ModuleFileName => "FunctionExports.wat";
}
public class FunctionExportsTests : IClassFixture<FunctionExportsFixture>

View File

@@ -8,7 +8,7 @@ namespace Wasmtime.Tests
{
public class FunctionImportsFixture : ModuleFixture
{
protected override string ModuleFileName => "FunctionImports.wasm";
protected override string ModuleFileName => "FunctionImports.wat";
}
public class FunctionImportsTests : IClassFixture<FunctionImportsFixture>

View File

@@ -7,7 +7,7 @@ namespace Wasmtime.Tests
{
public class FunctionThunkingFixture : ModuleFixture
{
protected override string ModuleFileName => "FunctionThunking.wasm";
protected override string ModuleFileName => "FunctionThunking.wat";
}
public class FunctionThunkingTests : IClassFixture<FunctionThunkingFixture>

View File

@@ -10,7 +10,7 @@ namespace Wasmtime.Tests
{
public class GlobalExportsFixture : ModuleFixture
{
protected override string ModuleFileName => "GlobalExports.wasm";
protected override string ModuleFileName => "GlobalExports.wat";
}
public class GlobalExportsTests : IClassFixture<GlobalExportsFixture>

View File

@@ -6,7 +6,7 @@ namespace Wasmtime.Tests
{
public class GlobalImportBindingFixture : ModuleFixture
{
protected override string ModuleFileName => "GlobalImportBindings.wasm";
protected override string ModuleFileName => "GlobalImportBindings.wat";
}
public class GlobalImportBindingTests : IClassFixture<GlobalImportBindingFixture>

View File

@@ -8,7 +8,7 @@ namespace Wasmtime.Tests
{
public class GlobalImportsFixture : ModuleFixture
{
protected override string ModuleFileName => "GlobalImports.wasm";
protected override string ModuleFileName => "GlobalImports.wat";
}
public class GlobalImportsTests : IClassFixture<GlobalImportsFixture>

View File

@@ -8,7 +8,7 @@ namespace Wasmtime.Tests
{
public class MemoryExportsFixture : ModuleFixture
{
protected override string ModuleFileName => "MemoryExports.wasm";
protected override string ModuleFileName => "MemoryExports.wat";
}
public class MemoryExportsTests : IClassFixture<MemoryExportsFixture>

View File

@@ -6,7 +6,7 @@ namespace Wasmtime.Tests
{
public class MemoryImportBindingFixture : ModuleFixture
{
protected override string ModuleFileName => "MemoryImportBinding.wasm";
protected override string ModuleFileName => "MemoryImportBinding.wat";
}
public class MemoryImportBindingTests : IClassFixture<MemoryImportBindingFixture>

View File

@@ -6,7 +6,7 @@ namespace Wasmtime.Tests
{
public class MemoryImportFromModuleFixture : ModuleFixture
{
protected override string ModuleFileName => "MemoryImportFromModule.wasm";
protected override string ModuleFileName => "MemoryImportFromModule.wat";
}
public class MemoryImportFromModuleTests : IClassFixture<MemoryImportFromModuleFixture>

View File

@@ -6,7 +6,7 @@ namespace Wasmtime.Tests
{
public class MemoryImportNoUpperBoundFixture : ModuleFixture
{
protected override string ModuleFileName => "MemoryImportNoUpperBound.wasm";
protected override string ModuleFileName => "MemoryImportNoUpperBound.wat";
}
public class MemoryImportNoUpperBoundTests : IClassFixture<MemoryImportNoUpperBoundFixture>

View File

@@ -6,7 +6,7 @@ namespace Wasmtime.Tests
{
public class MemoryImportWithUpperBoundFixture : ModuleFixture
{
protected override string ModuleFileName => "MemoryImportWithUpperBound.wasm";
protected override string ModuleFileName => "MemoryImportWithUpperBound.wat";
}
public class MemoryImportWithUpperBoundTests : IClassFixture<MemoryImportWithUpperBoundFixture>

View File

@@ -8,7 +8,7 @@ namespace Wasmtime.Tests
{
public class TableExportsFixture : ModuleFixture
{
protected override string ModuleFileName => "TableExports.wasm";
protected override string ModuleFileName => "TableExports.wat";
}
public class TableExportsTests : IClassFixture<TableExportsFixture>

View File

@@ -8,7 +8,7 @@ namespace Wasmtime.Tests
{
public class TableImportsFixture : ModuleFixture
{
protected override string ModuleFileName => "TableImports.wasm";
protected override string ModuleFileName => "TableImports.wat";
}
public class TableImportsTests : IClassFixture<TableImportsFixture>

View File

@@ -21,4 +21,4 @@ namespace Wasmtime.Tests
public string Path { get; private set; }
}
}
}

View File

@@ -9,7 +9,7 @@ namespace Wasmtime.Tests
{
public class WasiFixture : ModuleFixture
{
protected override string ModuleFileName => "Wasi.wasm";
protected override string ModuleFileName => "Wasi.wat";
}
public class WasiTests : IClassFixture<WasiFixture>

View File

@@ -27,7 +27,7 @@
</Target>
<ItemGroup>
<None Update="Modules/*.wasm" CopyToOutputDirectory="PreserveNewest" />
<None Update="Modules/*.wat" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>