diff --git a/pkg/wasm/lib/src/function.dart b/pkg/wasm/lib/src/function.dart index e9a23c5c5ef..4ac694e5b19 100644 --- a/pkg/wasm/lib/src/function.dart +++ b/pkg/wasm/lib/src/function.dart @@ -10,43 +10,35 @@ import 'package:ffi/ffi.dart'; /// WasmFunction is a callable function from a WasmInstance. class WasmFunction { String _name; - Pointer _func; + Pointer _func; List _argTypes; int _returnType; - Pointer _args; - Pointer _results; + Pointer _args; + Pointer _result; WasmFunction(this._name, this._func, this._argTypes, this._returnType) - : _args = _argTypes.length == 0 - ? nullptr - : allocate(count: _argTypes.length), - _results = - _returnType == WasmerValKindVoid ? nullptr : allocate() { + : _args = allocate(count: _argTypes.length), + _result = allocate() { for (var i = 0; i < _argTypes.length; ++i) { - _args[i].kind = _argTypes[i]; + _args[i].tag = _argTypes[i]; } } - String toString() { - return "${wasmerValKindName(_returnType)} $_name" + - "(${_argTypes.map(wasmerValKindName).join(", ")})"; - } - bool _fillArg(dynamic arg, int i) { switch (_argTypes[i]) { - case WasmerValKindI32: + case WasmerValueTagI32: if (arg is! int) return false; _args[i].i32 = arg; return true; - case WasmerValKindI64: + case WasmerValueTagI64: if (arg is! int) return false; _args[i].i64 = arg; return true; - case WasmerValKindF32: + case WasmerValueTagF32: if (arg is! num) return false; _args[i].f32 = arg; return true; - case WasmerValKindF64: + case WasmerValueTagF64: if (arg is! num) return false; _args[i].f64 = arg; return true; @@ -56,29 +48,29 @@ class WasmFunction { dynamic apply(List args) { if (args.length != _argTypes.length) { - throw ArgumentError("Wrong number arguments for WASM function: $this"); + throw ArgumentError("Wrong number arguments for WASM function: $_name"); } for (var i = 0; i < args.length; ++i) { if (!_fillArg(args[i], i)) { - throw ArgumentError("Bad argument type for WASM function: $this"); + throw ArgumentError("Bad argument type for WASM function: $_name"); } } - WasmRuntime().call(_func, _args, _results); + WasmRuntime().call(_func, _args, _argTypes.length, _result, + _returnType == WasmerValueTagVoid ? 0 : 1); - if (_returnType == WasmerValKindVoid) { + if (_returnType == WasmerValueTagVoid) { return null; } - var result = _results[0]; - assert(_returnType == result.kind); + assert(_returnType == _result.ref.tag); switch (_returnType) { - case WasmerValKindI32: - return result.i32; - case WasmerValKindI64: - return result.i64; - case WasmerValKindF32: - return result.f32; - case WasmerValKindF64: - return result.f64; + case WasmerValueTagI32: + return _result.ref.i32; + case WasmerValueTagI64: + return _result.ref.i64; + case WasmerValueTagF32: + return _result.ref.f32; + case WasmerValueTagF64: + return _result.ref.f64; } } diff --git a/pkg/wasm/lib/src/module.dart b/pkg/wasm/lib/src/module.dart index a2a9944d000..40139663bd3 100644 --- a/pkg/wasm/lib/src/module.dart +++ b/pkg/wasm/lib/src/module.dart @@ -11,23 +11,14 @@ import 'package:ffi/ffi.dart'; /// WasmModule is a compiled module that can be instantiated. class WasmModule { - Pointer _store; - late Pointer _module; + Pointer _module; /// Compile a module. - WasmModule(Uint8List data) : _store = WasmRuntime().newStore() { - _module = WasmRuntime().compile(_store, data); - } + WasmModule(Uint8List data) : _module = WasmRuntime().compile(data) {} /// Instantiate the module with the given imports. WasmInstance instantiate(WasmImports imports) { - return WasmInstance(_store, _module, imports); - } - - /// Create a new memory with the given number of initial pages, and optional - /// maximum number of pages. - WasmMemory createMemory(int pages, [int? maxPages]) { - return WasmMemory._create(_store, pages, maxPages); + return WasmInstance(_module, imports); } /// Returns a description of all of the module's imports and exports, for @@ -37,12 +28,12 @@ class WasmModule { var runtime = WasmRuntime(); var imports = runtime.importDescriptors(_module); for (var imp in imports) { - var kind = wasmerExternKindName(imp.kind); + var kind = wasmerImpExpKindName(imp.kind); description.write('import $kind: ${imp.moduleName}::${imp.name}\n'); } var exports = runtime.exportDescriptors(_module); for (var exp in exports) { - var kind = wasmerExternKindName(exp.kind); + var kind = wasmerImpExpKindName(exp.kind); description.write('export $kind: ${exp.name}\n'); } return description.toString(); @@ -51,13 +42,13 @@ class WasmModule { /// WasmImports holds all the imports for a WasmInstance. class WasmImports { - Pointer> _imports; + Pointer _imports; int _capacity; int _length; /// Create an imports object. WasmImports([this._capacity = 4]) - : _imports = allocate>(count: _capacity), + : _imports = allocate(count: _capacity), _length = 0 {} /// Returns the number of imports. @@ -66,31 +57,26 @@ class WasmImports { /// WasmInstance is an instantiated WasmModule. class WasmInstance { - Pointer _store; Pointer _module; Pointer _instance; Pointer? _exportedMemory; Map _functions = {}; - WasmInstance(this._store, this._module, WasmImports imports) + WasmInstance(this._module, WasmImports imports) : _instance = WasmRuntime() - .instantiate(_store, _module, imports._imports, imports.length) { + .instantiate(_module, imports._imports, imports.length) { var runtime = WasmRuntime(); - var exports = runtime.exports(_instance); - var exportDescs = runtime.exportDescriptors(_module); - assert(exports.ref.length == exportDescs.length); - for (var i = 0; i < exports.ref.length; ++i) { - var e = exports.ref.data[i]; - var kind = runtime.externKind(exports.ref.data[i]); - String name = exportDescs[i].name; - if (kind == WasmerExternKindFunction) { - var f = runtime.externToFunction(e); - var ft = exportDescs[i].funcType; + var exps = runtime.exports(_instance); + for (var e in exps) { + var kind = runtime.exportKind(e); + String name = runtime.exportName(e); + if (kind == WasmerImpExpKindFunction) { + var f = runtime.exportToFunction(e); _functions[name] = WasmFunction( - name, f, runtime.getArgTypes(ft), runtime.getReturnType(ft)); - } else if (kind == WasmerExternKindMemory) { + name, f, runtime.getArgTypes(f), runtime.getReturnType(f)); + } else if (kind == WasmerImpExpKindMemory) { // WASM currently allows only one memory per module. - _exportedMemory = runtime.externToMemory(e); + _exportedMemory = runtime.exportToMemory(e); } } } @@ -121,8 +107,8 @@ class WasmMemory { /// Create a new memory with the given number of initial pages, and optional /// maximum number of pages. - WasmMemory._create(Pointer store, int pages, int? maxPages) - : _mem = WasmRuntime().newMemory(store, pages, maxPages) { + WasmMemory(int pages, [int? maxPages]) + : _mem = WasmRuntime().newMemory(pages, maxPages) { _view = WasmRuntime().memoryView(_mem); } diff --git a/pkg/wasm/lib/src/runtime.dart b/pkg/wasm/lib/src/runtime.dart index 6f092083d6c..4ddec1dc025 100644 --- a/pkg/wasm/lib/src/runtime.dart +++ b/pkg/wasm/lib/src/runtime.dart @@ -2,10 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// This file has been automatically generated. Please do not edit it manually. -// To regenerate the file, use the following command -// "generate_ffi_boilerplate.py". - import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; @@ -18,92 +14,62 @@ class WasmImportDescriptor { int kind; String moduleName; String name; - Pointer funcType; - WasmImportDescriptor(this.kind, this.moduleName, this.name, this.funcType); + WasmImportDescriptor(this.kind, this.moduleName, this.name); } class WasmExportDescriptor { int kind; String name; - Pointer funcType; - WasmExportDescriptor(this.kind, this.name, this.funcType); + WasmExportDescriptor(this.kind, this.name); } class WasmRuntime { static WasmRuntime? _inst; DynamicLibrary _lib; - late Pointer _engine; - late WasmerByteVecDeleteFn _byte_vec_delete; - late WasmerByteVecNewFn _byte_vec_new; - late WasmerByteVecNewEmptyFn _byte_vec_new_empty; - late WasmerByteVecNewUninitializedFn _byte_vec_new_uninitialized; - late WasmerEngineDeleteFn _engine_delete; - late WasmerEngineNewFn _engine_new; - late WasmerExporttypeNameFn _exporttype_name; - late WasmerExporttypeTypeFn _exporttype_type; - late WasmerExporttypeVecDeleteFn _exporttype_vec_delete; - late WasmerExporttypeVecNewFn _exporttype_vec_new; - late WasmerExporttypeVecNewEmptyFn _exporttype_vec_new_empty; - late WasmerExporttypeVecNewUninitializedFn _exporttype_vec_new_uninitialized; - late WasmerExternAsFuncFn _extern_as_func; - late WasmerExternAsMemoryFn _extern_as_memory; - late WasmerExternDeleteFn _extern_delete; - late WasmerExternKindFn _extern_kind; - late WasmerExternVecDeleteFn _extern_vec_delete; - late WasmerExternVecNewFn _extern_vec_new; - late WasmerExternVecNewEmptyFn _extern_vec_new_empty; - late WasmerExternVecNewUninitializedFn _extern_vec_new_uninitialized; - late WasmerExterntypeAsFunctypeFn _externtype_as_functype; - late WasmerExterntypeDeleteFn _externtype_delete; - late WasmerExterntypeKindFn _externtype_kind; - late WasmerFuncCallFn _func_call; - late WasmerFuncDeleteFn _func_delete; - late WasmerFunctypeDeleteFn _functype_delete; - late WasmerFunctypeParamsFn _functype_params; - late WasmerFunctypeResultsFn _functype_results; - late WasmerImporttypeModuleFn _importtype_module; - late WasmerImporttypeNameFn _importtype_name; - late WasmerImporttypeTypeFn _importtype_type; - late WasmerImporttypeVecDeleteFn _importtype_vec_delete; - late WasmerImporttypeVecNewFn _importtype_vec_new; - late WasmerImporttypeVecNewEmptyFn _importtype_vec_new_empty; - late WasmerImporttypeVecNewUninitializedFn _importtype_vec_new_uninitialized; - late WasmerInstanceDeleteFn _instance_delete; + late WasmerCompileFn _compile; + late WasmerInstantiateFn _instantiate; late WasmerInstanceExportsFn _instance_exports; - late WasmerInstanceNewFn _instance_new; - late WasmerMemoryDataFn _memory_data; - late WasmerMemoryDataSizeFn _memory_data_size; - late WasmerMemoryDeleteFn _memory_delete; + late WasmerExportsLenFn _exports_len; + late WasmerExportsGetFn _exports_get; + late WasmerExportKindFn _export_kind; + late WasmerExportToFuncFn _export_to_func; + late WasmerExportFuncReturnsArityFn _export_func_returns_arity; + late WasmerExportFuncReturnsFn _export_func_returns; + late WasmerExportFuncParamsArityFn _export_func_params_arity; + late WasmerExportFuncParamsFn _export_func_params; + late WasmerExportFuncCallFn _export_func_call; + late WasmerExportNamePtrFn _export_name_ptr; + late WasmerExportDescriptorsFn _export_descriptors; + late WasmerExportDescriptorsDestroyFn _export_descriptors_destroy; + late WasmerExportDescriptorsLenFn _export_descriptors_len; + late WasmerExportDescriptorsGetFn _export_descriptors_get; + late WasmerExportDescriptorKindFn _export_descriptor_kind; + late WasmerExportDescriptorNamePtrFn _export_descriptor_name_ptr; + late WasmerImportDescriptorModuleNamePtrFn _import_descriptor_module_name_ptr; + late WasmerImportDescriptorNamePtrFn _import_descriptor_name_ptr; + late WasmerImportDescriptorsFn _import_descriptors; + late WasmerImportDescriptorsDestroyFn _import_descriptors_destroy; + late WasmerImportDescriptorsLenFn _import_descriptors_len; + late WasmerImportDescriptorsGetFn _import_descriptors_get; + late WasmerImportDescriptorKindFn _import_descriptor_kind; + late WasmerExportToMemoryFn _export_to_memory; + late WasmerMemoryNewPtrFn _memory_new_ptr; late WasmerMemoryGrowFn _memory_grow; - late WasmerMemoryNewFn _memory_new; - late WasmerMemorySizeFn _memory_size; - late WasmerMemorytypeDeleteFn _memorytype_delete; - late WasmerMemorytypeNewFn _memorytype_new; - late WasmerModuleDeleteFn _module_delete; - late WasmerModuleExportsFn _module_exports; - late WasmerModuleImportsFn _module_imports; - late WasmerModuleNewFn _module_new; - late WasmerStoreDeleteFn _store_delete; - late WasmerStoreNewFn _store_new; - late WasmerTrapDeleteFn _trap_delete; - late WasmerValtypeDeleteFn _valtype_delete; - late WasmerValtypeKindFn _valtype_kind; - late WasmerValtypeVecDeleteFn _valtype_vec_delete; - late WasmerValtypeVecNewFn _valtype_vec_new; - late WasmerValtypeVecNewEmptyFn _valtype_vec_new_empty; - late WasmerValtypeVecNewUninitializedFn _valtype_vec_new_uninitialized; + late WasmerMemoryLengthFn _memory_length; + late WasmerMemoryDataFn _memory_data; + late WasmerMemoryDataLengthFn _memory_data_length; factory WasmRuntime() { - WasmRuntime inst = _inst ?? WasmRuntime._init(); - _inst = inst; - return inst; + if (_inst == null) { + _inst = WasmRuntime._init(); + } + return _inst as WasmRuntime; } static String _getLibName() { - if (Platform.isMacOS) return "libwasmer.dylib"; - if (Platform.isLinux) return "libwasmer.so"; - // TODO(dartbug.com/37882): Support more platforms. + if (Platform.isMacOS) return "libwasmer_wrapper.dylib"; + if (Platform.isLinux) return "libwasmer_wrapper.so"; throw Exception("Wasm not currently supported on this platform"); } @@ -138,322 +104,296 @@ class WasmRuntime { WasmRuntime._init() : _lib = DynamicLibrary.open(path.join(_getLibDir(), _getLibName())) { - _byte_vec_delete = - _lib.lookupFunction( - 'wasm_byte_vec_delete'); - _byte_vec_new = - _lib.lookupFunction( - 'wasm_byte_vec_new'); - _byte_vec_new_empty = _lib.lookupFunction('wasm_byte_vec_new_empty'); - _byte_vec_new_uninitialized = _lib.lookupFunction< - NativeWasmerByteVecNewUninitializedFn, - WasmerByteVecNewUninitializedFn>('wasm_byte_vec_new_uninitialized'); - _engine_delete = - _lib.lookupFunction( - 'wasm_engine_delete'); - _engine_new = - _lib.lookupFunction( - 'wasm_engine_new'); - _exporttype_name = _lib.lookupFunction('wasm_exporttype_name'); - _exporttype_type = _lib.lookupFunction('wasm_exporttype_type'); - _exporttype_vec_delete = _lib.lookupFunction< - NativeWasmerExporttypeVecDeleteFn, - WasmerExporttypeVecDeleteFn>('wasm_exporttype_vec_delete'); - _exporttype_vec_new = _lib.lookupFunction('wasm_exporttype_vec_new'); - _exporttype_vec_new_empty = _lib.lookupFunction< - NativeWasmerExporttypeVecNewEmptyFn, - WasmerExporttypeVecNewEmptyFn>('wasm_exporttype_vec_new_empty'); - _exporttype_vec_new_uninitialized = _lib.lookupFunction< - NativeWasmerExporttypeVecNewUninitializedFn, - WasmerExporttypeVecNewUninitializedFn>( - 'wasm_exporttype_vec_new_uninitialized'); - _extern_as_func = - _lib.lookupFunction( - 'wasm_extern_as_func'); - _extern_as_memory = _lib.lookupFunction('wasm_extern_as_memory'); - _extern_delete = - _lib.lookupFunction( - 'wasm_extern_delete'); - _extern_kind = - _lib.lookupFunction( - 'wasm_extern_kind'); - _extern_vec_delete = _lib.lookupFunction('wasm_extern_vec_delete'); - _extern_vec_new = - _lib.lookupFunction( - 'wasm_extern_vec_new'); - _extern_vec_new_empty = _lib.lookupFunction('wasm_extern_vec_new_empty'); - _extern_vec_new_uninitialized = _lib.lookupFunction< - NativeWasmerExternVecNewUninitializedFn, - WasmerExternVecNewUninitializedFn>('wasm_extern_vec_new_uninitialized'); - _externtype_as_functype = _lib.lookupFunction< - NativeWasmerExterntypeAsFunctypeFn, - WasmerExterntypeAsFunctypeFn>('wasm_externtype_as_functype'); - _externtype_delete = _lib.lookupFunction('wasm_externtype_delete'); - _externtype_kind = _lib.lookupFunction('wasm_externtype_kind'); - _func_call = _lib.lookupFunction( - 'wasm_func_call'); - _func_delete = - _lib.lookupFunction( - 'wasm_func_delete'); - _functype_delete = _lib.lookupFunction('wasm_functype_delete'); - _functype_params = _lib.lookupFunction('wasm_functype_params'); - _functype_results = _lib.lookupFunction('wasm_functype_results'); - _importtype_module = _lib.lookupFunction('wasm_importtype_module'); - _importtype_name = _lib.lookupFunction('wasm_importtype_name'); - _importtype_type = _lib.lookupFunction('wasm_importtype_type'); - _importtype_vec_delete = _lib.lookupFunction< - NativeWasmerImporttypeVecDeleteFn, - WasmerImporttypeVecDeleteFn>('wasm_importtype_vec_delete'); - _importtype_vec_new = _lib.lookupFunction('wasm_importtype_vec_new'); - _importtype_vec_new_empty = _lib.lookupFunction< - NativeWasmerImporttypeVecNewEmptyFn, - WasmerImporttypeVecNewEmptyFn>('wasm_importtype_vec_new_empty'); - _importtype_vec_new_uninitialized = _lib.lookupFunction< - NativeWasmerImporttypeVecNewUninitializedFn, - WasmerImporttypeVecNewUninitializedFn>( - 'wasm_importtype_vec_new_uninitialized'); - _instance_delete = _lib.lookupFunction('wasm_instance_delete'); + _compile = _lib.lookupFunction( + 'wasmer_compile'); + _instantiate = + _lib.lookupFunction( + 'wasmer_module_instantiate'); _instance_exports = _lib.lookupFunction('wasm_instance_exports'); - _instance_new = - _lib.lookupFunction( - 'wasm_instance_new'); - _memory_data = - _lib.lookupFunction( - 'wasm_memory_data'); - _memory_data_size = _lib.lookupFunction('wasm_memory_data_size'); - _memory_delete = - _lib.lookupFunction( - 'wasm_memory_delete'); + WasmerInstanceExportsFn>('wasmer_instance_exports'); + _exports_len = + _lib.lookupFunction( + 'wasmer_exports_len'); + _exports_get = + _lib.lookupFunction( + 'wasmer_exports_get'); + _export_kind = + _lib.lookupFunction( + 'wasmer_export_kind'); + _export_to_func = + _lib.lookupFunction( + 'wasmer_export_to_func'); + _export_func_returns_arity = _lib.lookupFunction< + NativeWasmerExportFuncReturnsArityFn, + WasmerExportFuncReturnsArityFn>('wasmer_export_func_returns_arity'); + _export_func_returns = _lib.lookupFunction('wasmer_export_func_returns'); + _export_func_params_arity = _lib.lookupFunction< + NativeWasmerExportFuncParamsArityFn, + WasmerExportFuncParamsArityFn>('wasmer_export_func_params_arity'); + _export_func_params = _lib.lookupFunction('wasmer_export_func_params'); + _export_func_call = _lib.lookupFunction('wasmer_export_func_call'); + _export_descriptors = _lib.lookupFunction('wasmer_export_descriptors'); + _export_descriptors_destroy = _lib.lookupFunction< + NativeWasmerExportDescriptorsDestroyFn, + WasmerExportDescriptorsDestroyFn>('wasmer_export_descriptors_destroy'); + _export_descriptors_len = _lib.lookupFunction< + NativeWasmerExportDescriptorsLenFn, + WasmerExportDescriptorsLenFn>('wasmer_export_descriptors_len'); + _export_descriptors_get = _lib.lookupFunction< + NativeWasmerExportDescriptorsGetFn, + WasmerExportDescriptorsGetFn>('wasmer_export_descriptors_get'); + _export_descriptor_kind = _lib.lookupFunction< + NativeWasmerExportDescriptorKindFn, + WasmerExportDescriptorKindFn>('wasmer_export_descriptor_kind'); + _export_name_ptr = + _lib.lookupFunction( + 'wasmer_export_name_ptr'); + _export_descriptor_name_ptr = _lib.lookupFunction< + NativeWasmerExportDescriptorNamePtrFn, + WasmerExportDescriptorNamePtrFn>('wasmer_export_descriptor_name_ptr'); + _import_descriptors = _lib.lookupFunction('wasmer_import_descriptors'); + _import_descriptors_destroy = _lib.lookupFunction< + NativeWasmerImportDescriptorsDestroyFn, + WasmerImportDescriptorsDestroyFn>('wasmer_import_descriptors_destroy'); + _import_descriptors_len = _lib.lookupFunction< + NativeWasmerImportDescriptorsLenFn, + WasmerImportDescriptorsLenFn>('wasmer_import_descriptors_len'); + _import_descriptors_get = _lib.lookupFunction< + NativeWasmerImportDescriptorsGetFn, + WasmerImportDescriptorsGetFn>('wasmer_import_descriptors_get'); + _import_descriptor_kind = _lib.lookupFunction< + NativeWasmerImportDescriptorKindFn, + WasmerImportDescriptorKindFn>('wasmer_import_descriptor_kind'); + _import_descriptor_module_name_ptr = _lib.lookupFunction< + NativeWasmerImportDescriptorModuleNamePtrFn, + WasmerImportDescriptorModuleNamePtrFn>( + 'wasmer_import_descriptor_module_name_ptr'); + _import_descriptor_name_ptr = _lib.lookupFunction< + NativeWasmerImportDescriptorNamePtrFn, + WasmerImportDescriptorNamePtrFn>('wasmer_import_descriptor_name_ptr'); + _export_to_memory = _lib.lookupFunction('wasmer_export_to_memory'); + _memory_new_ptr = + _lib.lookupFunction( + 'wasmer_memory_new_ptr'); _memory_grow = _lib.lookupFunction( - 'wasm_memory_grow'); - _memory_new = - _lib.lookupFunction( - 'wasm_memory_new'); - _memory_size = - _lib.lookupFunction( - 'wasm_memory_size'); - _memorytype_delete = _lib.lookupFunction('wasm_memorytype_delete'); - _memorytype_new = - _lib.lookupFunction( - 'wasm_memorytype_new'); - _module_delete = - _lib.lookupFunction( - 'wasm_module_delete'); - _module_exports = - _lib.lookupFunction( - 'wasm_module_exports'); - _module_imports = - _lib.lookupFunction( - 'wasm_module_imports'); - _module_new = - _lib.lookupFunction( - 'wasm_module_new'); - _store_delete = - _lib.lookupFunction( - 'wasm_store_delete'); - _store_new = _lib.lookupFunction( - 'wasm_store_new'); - _trap_delete = - _lib.lookupFunction( - 'wasm_trap_delete'); - _valtype_delete = - _lib.lookupFunction( - 'wasm_valtype_delete'); - _valtype_kind = - _lib.lookupFunction( - 'wasm_valtype_kind'); - _valtype_vec_delete = _lib.lookupFunction('wasm_valtype_vec_delete'); - _valtype_vec_new = - _lib.lookupFunction( - 'wasm_valtype_vec_new'); - _valtype_vec_new_empty = _lib.lookupFunction< - NativeWasmerValtypeVecNewEmptyFn, - WasmerValtypeVecNewEmptyFn>('wasm_valtype_vec_new_empty'); - _valtype_vec_new_uninitialized = _lib.lookupFunction< - NativeWasmerValtypeVecNewUninitializedFn, - WasmerValtypeVecNewUninitializedFn>( - 'wasm_valtype_vec_new_uninitialized'); - - _engine = _engine_new(); + 'wasmer_memory_grow'); + _memory_length = + _lib.lookupFunction( + 'wasmer_memory_length'); + _memory_data = + _lib.lookupFunction( + 'wasmer_memory_data'); + _memory_data_length = _lib.lookupFunction('wasmer_memory_data_length'); } - Pointer newStore() { - return _store_new(_engine); - } - - Pointer compile(Pointer store, Uint8List data) { + Pointer compile(Uint8List data) { var dataPtr = allocate(count: data.length); for (int i = 0; i < data.length; ++i) { dataPtr[i] = data[i]; } - var dataVec = allocate(); - dataVec.ref.data = dataPtr; - dataVec.ref.length = data.length; - var modulePtr = _module_new(store, dataVec); + var modulePtrPtr = allocate>(); + int result = _compile(modulePtrPtr, dataPtr, data.length); + Pointer modulePtr = modulePtrPtr.value; + free(modulePtrPtr); free(dataPtr); - free(dataVec); - if (modulePtr == nullptr) { + if (result != WasmerResultOk) { throw Exception("Wasm module compile failed"); } return modulePtr; } + String _callStringWrapperFunction(Function fn, dynamic arg) { + var strPtr = allocate(); + fn(arg, strPtr); + var str = strPtr.ref.string; + free(strPtr); + return str; + } + List exportDescriptors(Pointer module) { - var exportsVec = allocate(); - _module_exports(module, exportsVec); + var exportsPtrPtr = allocate>(); + _export_descriptors(module, exportsPtrPtr); + Pointer exportsPtr = exportsPtrPtr.value; + free(exportsPtrPtr); + var n = _export_descriptors_len(exportsPtr); var exps = []; - for (var i = 0; i < exportsVec.ref.length; ++i) { - var exp = exportsVec.ref.data[i]; - var extern = _exporttype_type(exp); - var kind = _externtype_kind(extern); - var fnType = kind == WasmerExternKindFunction - ? _externtype_as_functype(extern) - : nullptr; - exps.add(WasmExportDescriptor( - kind, _exporttype_name(exp).ref.toString(), fnType)); + for (var i = 0; i < n; ++i) { + var exp = _export_descriptors_get(exportsPtr, i); + exps.add(WasmExportDescriptor(_export_descriptor_kind(exp), + _callStringWrapperFunction(_export_descriptor_name_ptr, exp))); } - free(exportsVec); + _export_descriptors_destroy(exportsPtr); return exps; } List importDescriptors(Pointer module) { - var importsVec = allocate(); - _module_imports(module, importsVec); + var importsPtrPtr = allocate>(); + _import_descriptors(module, importsPtrPtr); + Pointer importsPtr = importsPtrPtr.value; + free(importsPtrPtr); + + var n = _import_descriptors_len(importsPtr); var imps = []; - for (var i = 0; i < importsVec.ref.length; ++i) { - var imp = importsVec.ref.data[i]; - var extern = _importtype_type(imp); - var kind = _externtype_kind(extern); - var fnType = kind == WasmerExternKindFunction - ? _externtype_as_functype(extern) - : nullptr; + for (var i = 0; i < n; ++i) { + var imp = _import_descriptors_get(importsPtr, i); imps.add(WasmImportDescriptor( - kind, - _importtype_module(imp).ref.toString(), - _importtype_name(imp).ref.toString(), - fnType)); + _import_descriptor_kind(imp), + _callStringWrapperFunction(_import_descriptor_module_name_ptr, imp), + _callStringWrapperFunction(_import_descriptor_name_ptr, imp))); } - free(importsVec); + _import_descriptors_destroy(importsPtr); return imps; } - Pointer instantiate( - Pointer store, - Pointer module, - Pointer> imports, - int numImports) { - var importsVec = allocate(); - _module_imports(module, importsVec); - if (importsVec.ref.length != numImports) { - throw Exception( - "Wrong number of imports. Expected ${importsVec.ref.length} but " + - "found $numImports."); - } - free(importsVec); + Pointer instantiate(Pointer module, + Pointer imports, int numImports) { + var instancePtrPtr = allocate>(); + int result = _instantiate(module, instancePtrPtr, imports, numImports); + Pointer instancePtr = instancePtrPtr.value; + free(instancePtrPtr); - var instancePtr = _instance_new(store, module, imports, nullptr); - if (instancePtr == nullptr) { + if (result != WasmerResultOk) { throw Exception("Wasm module instantiation failed"); } return instancePtr; } - Pointer exports(Pointer instancePtr) { - var exports = allocate(); - _instance_exports(instancePtr, exports); - return exports; - } + List> exports(Pointer instancePtr) { + var exportsPtrPtr = allocate>(); + _instance_exports(instancePtr, exportsPtrPtr); + Pointer exportsPtr = exportsPtrPtr.value; + free(exportsPtrPtr); - int externKind(Pointer extern) { - return _extern_kind(extern); - } - - Pointer externToFunction(Pointer extern) { - return _extern_as_func(extern); - } - - List getArgTypes(Pointer funcType) { - var types = []; - var args = _functype_params(funcType); - for (var i = 0; i < args.ref.length; ++i) { - types.add(_valtype_kind(args.ref.data[i])); + var n = _exports_len(exportsPtr); + var exps = >[]; + for (var i = 0; i < n; ++i) { + exps.add(_exports_get(exportsPtr, i)); } + return exps; + } + + int exportKind(Pointer export) { + return _export_kind(export); + } + + String exportName(Pointer export) { + return _callStringWrapperFunction(_export_name_ptr, export); + } + + Pointer exportToFunction(Pointer export) { + return _export_to_func(export); + } + + List getArgTypes(Pointer func) { + var types = []; + var nPtr = allocate(); + var result = _export_func_params_arity(func, nPtr); + if (result != WasmerResultOk) { + free(nPtr); + throw Exception("Failed to get number of WASM function args"); + } + var n = nPtr.value; + free(nPtr); + var argsPtr = allocate(count: n); + result = _export_func_params(func, argsPtr, n); + if (result != WasmerResultOk) { + free(argsPtr); + throw Exception("Failed to get WASM function args"); + } + for (var i = 0; i < n; ++i) { + types.add(argsPtr[i]); + } + free(argsPtr); return types; } - int getReturnType(Pointer funcType) { - var rets = _functype_results(funcType); - if (rets.ref.length == 0) { - return WasmerValKindVoid; - } else if (rets.ref.length > 1) { + int getReturnType(Pointer func) { + var nPtr = allocate(); + var result = _export_func_returns_arity(func, nPtr); + if (result != WasmerResultOk) { + free(nPtr); + throw Exception("Failed to get number of WASM function returns"); + } + var n = nPtr.value; + free(nPtr); + if (n == 0) { + return WasmerValueTagVoid; + } else if (n > 1) { throw Exception("Multiple return values are not supported"); } - return _valtype_kind(rets.ref.data[0]); + var returnsPtr = allocate(); + result = _export_func_returns(func, returnsPtr, 1); + if (result != WasmerResultOk) { + free(returnsPtr); + throw Exception("Failed to get WASM function args"); + } + var type = returnsPtr.value; + free(returnsPtr); + return type; } - void call(Pointer func, Pointer args, - Pointer results) { - _func_call(func, args, results); + void call(Pointer func, Pointer args, + int numArgs, Pointer results, int numResults) { + var result = _export_func_call(func, args, numArgs, results, numArgs); + if (result != WasmerResultOk) { + throw Exception("Failed to call WASM function"); + } } - Pointer externToMemory(Pointer extern) { - return _extern_as_memory(extern); + Pointer exportToMemory(Pointer export) { + var memPtrPtr = allocate>(); + var result = _export_to_memory(export, memPtrPtr); + if (result != WasmerResultOk) { + free(memPtrPtr); + throw Exception("Failed to get exported memory"); + } + Pointer memPtr = memPtrPtr.value; + free(memPtrPtr); + return memPtr; } - Pointer newMemory( - Pointer store, int pages, int? maxPages) { + Pointer newMemory(int pages, int? maxPages) { + var memPtrPtr = allocate>(); var limPtr = allocate(); limPtr.ref.min = pages; - limPtr.ref.max = maxPages ?? wasm_limits_max_default; - var memType = _memorytype_new(limPtr); + limPtr.ref.has_max = maxPages != null ? 1 : 0; + limPtr.ref.max = maxPages ?? 0; + var result = _memory_new_ptr(memPtrPtr, limPtr); free(limPtr); - Pointer memPtr = _memory_new(store, memType); - - if (memPtr == nullptr) { + if (result != WasmerResultOk) { + free(memPtrPtr); throw Exception("Failed to create memory"); } + Pointer memPtr = memPtrPtr.value; + free(memPtrPtr); return memPtr; } void growMemory(Pointer memory, int deltaPages) { var result = _memory_grow(memory, deltaPages); - if (result == 0) { + if (result != WasmerResultOk) { throw Exception("Failed to grow memory"); } } int memoryLength(Pointer memory) { - return _memory_size(memory); + return _memory_length(memory); } Uint8List memoryView(Pointer memory) { - return _memory_data(memory).asTypedList(_memory_data_size(memory)); + return _memory_data(memory).asTypedList(_memory_data_length(memory)); } } diff --git a/pkg/wasm/lib/src/tools/generate_ffi_boilerplate.py b/pkg/wasm/lib/src/tools/generate_ffi_boilerplate.py deleted file mode 100755 index cf9621c4adb..00000000000 --- a/pkg/wasm/lib/src/tools/generate_ffi_boilerplate.py +++ /dev/null @@ -1,340 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file -# for details. All rights reserved. Use of this source code is governed by a -# BSD-style license that can be found in the LICENSE file. - -# This is an ad-hoc script that generates FFI boilderplate for the Wasmer API. -# The relevant functions from wasm.h have been copied below, and are parsed to -# figure out the FFI boilerplate. The results are inserted into -# wasmer_api_template.dart and runtime_template.dart to generate wasmer_api.dart -# and runtime.dart. - -# Usage: -# generate_ffi_boilerplate.py && dartfmt -w ../runtime.dart ../wasmer_api.dart - -import os -import re - -predefTypes = {} -opaqueTypes = set() -vecTypes = {} -fns = [] -unusedFns = set() - - -def camel(t): - return ''.join([s[0].upper() + s[1:] for s in t.split('_')]) - - -def ptrWrap(t, n): - for i in range(n): - t = 'Pointer<%s>' % t - return t - - -def getDartType(t, i): - if t in predefTypes: - t = predefTypes[t][i] - else: - assert (t.startswith('wasm_') and t.endswith('_t')) - t = 'Wasmer' + camel(t[5:-2]) - return t - - -def dartArgType(a, i): - n, t = a - j = i if n == 0 else 0 - return ptrWrap(getDartType(t, j), n) - - -def dartFnType(r, a, i): - return '%s Function(%s)' % (dartArgType(r, i), ', '.join( - [dartArgType(t, i) for t in a])) - - -def dartFnTypeName(n): - assert (n.startswith('wasm_')) - return camel(n[5:]) - - -def dartFnMembName(n): - assert (n.startswith('wasm_')) - return n[4:] - - -def nativeTypeToFfi(n): - return getDartType(n, 0) - - -def nativeTypeToDart(n): - return getDartType(n, 1) - - -def getFns(): - for name, retType, args in sorted(fns): - if name not in unusedFns: - yield name, retType, args - - -opaqueTypeTemplate = '''// wasm_%s_t -class Wasmer%s extends Struct {}''' - -vecTypeTemplate = '''// wasm_%s_vec_t -class Wasmer%sVec extends Struct { - @Uint64() - external int length; - - external Pointer<%s> data; - - %s -}''' - -byteVecToStringTemplate = ''' - Uint8List get list => data.asTypedList(length); - String toString() => utf8.decode(list); -''' - -fnApiTemplate = ''' -// %s -typedef NativeWasmer%sFn = %s; -typedef Wasmer%sFn = %s;''' - - -def getWasmerApi(): - return ('\n\n'.join([ - opaqueTypeTemplate % (t, camel(t)) for t in sorted(opaqueTypes) - ]) + '\n\n' + '\n\n'.join([ - vecTypeTemplate % - (t, camel(t), - ('Pointer<%s>' if ptr else '%s') % nativeTypeToFfi('wasm_%s_t' % t), - (byteVecToStringTemplate if t == 'byte' else '')) - for t, ptr in sorted(vecTypes.items()) - ]) + '\n' + '\n'.join([ - fnApiTemplate % - (name, dartFnTypeName(name), dartFnType(retType, args, 0), - dartFnTypeName(name), dartFnType(retType, args, 1)) - for name, retType, args in getFns() - ])) - - -def getRuntimeMemb(): - return '\n'.join([ - " late Wasmer%sFn %s;" % (dartFnTypeName(name), dartFnMembName(name)) - for name, _, _ in getFns() - ]) - - -def getRuntimeLoad(): - return '\n'.join([ - " %s = _lib.lookupFunction('%s');" % - (dartFnMembName(name), dartFnTypeName(name), dartFnTypeName(name), name) - for name, _, _ in getFns() - ]) - - -def predefinedType(nativeType, ffiType, dartType): - predefTypes[nativeType] = (ffiType, dartType) - - -def match(r, s): - return r.fullmatch(s).groups() - - -reReplace = [(re.compile('\\b%s\\b' % k), v) for k, v in [ - ('const', ''), - ('own', ''), - ('WASM_API_EXTERN', ''), - ('wasm_name_t', 'wasm_byte_vec_t'), - ('wasm_memory_pages_t', 'uint32_t'), - ('wasm_externkind_t', 'uint8_t'), - ('wasm_valkind_t', 'uint8_t'), -]] -reWord = re.compile(r'\b\w+\b') - - -def parseType(s): - for r, t in reReplace: - s = r.sub(t, s) - s = s.strip() - numWords = len(reWord.findall(s)) - assert (numWords == 1 or numWords == 2) - if numWords == 2: - i = 0 - - def lastWordRepl(m): - nonlocal i - i += 1 - return '' if i == numWords else m.group(0) - - s = reWord.sub(lastWordRepl, s) - numPtr = 0 - while True: - s = s.strip() - if s.endswith('*'): - s = s[:-1] - elif s.endswith('[]'): - s = s[:-2] - else: - break - numPtr += 1 - return (numPtr, s) - - -reFnSig = re.compile(r'(.*) ([^ ]*)\((.*)\);?') - - -def addFn(sig): - ret, name, argpack = match(reFnSig, sig) - retType = parseType(ret) - args = [parseType(a) for a in argpack.split(',') if len(a.strip()) > 0] - for _, t in args + [retType]: - if t not in predefTypes and t[5:-2] not in opaqueTypes and t[ - 5:-6] not in vecTypes: - print('Missing type: ' + t) - fns.append((name, retType, args)) - - -def declareOwn(name): - opaqueTypes.add(name) - addFn('void wasm_%s_delete(wasm_%s_t*)' % (name, name)) - - -def declareVec(name, storePtr): - vecTypes[name] = storePtr - addFn('void wasm_%s_vec_new_empty(wasm_%s_vec_t* out)' % (name, name)) - addFn('void wasm_%s_vec_new_uninitialized(wasm_%s_vec_t* out, size_t)' % - (name, name)) - addFn('void wasm_%s_vec_new(wasm_%s_vec_t* out, size_t, wasm_%s_t %s[])' % - (name, name, name, '*' if storePtr else '')) - addFn('void wasm_%s_vec_copy(wasm_%s_vec_t* out, const wasm_%s_vec_t*)' % - (name, name, name)) - addFn('void wasm_%s_vec_delete(wasm_%s_vec_t*)' % (name, name)) - - -def declareType(name, withCopy=True): - declareOwn(name) - declareVec(name, True) - if withCopy: - addFn('wasm_%s_t* wasm_%s_copy(wasm_%s_t*)' % (name, name, name)) - - -predefinedType('void', 'Void', 'void') -predefinedType('bool', 'Uint8', 'int') -predefinedType('byte_t', 'Uint8', 'int') -predefinedType('wasm_byte_t', 'Uint8', 'int') -predefinedType('uint8_t', 'Uint8', 'int') -predefinedType('uint16_t', 'Uint16', 'int') -predefinedType('uint32_t', 'Uint32', 'int') -predefinedType('uint64_t', 'Uint64', 'int') -predefinedType('size_t', 'Uint64', 'int') -predefinedType('int8_t', 'Int8', 'int') -predefinedType('int16_t', 'Int16', 'int') -predefinedType('int32_t', 'Int32', 'int') -predefinedType('int64_t', 'Int64', 'int') -predefinedType('float32_t', 'Float32', 'double') -predefinedType('float64_t', 'Float64', 'double') -predefinedType('wasm_limits_t', 'WasmerLimits', 'WasmerLimits') -predefinedType('wasm_val_t', 'WasmerVal', 'WasmerVal') - -declareOwn('engine') -declareOwn('store') -declareVec('byte', False) -declareVec('val', False) -declareType('importtype') -declareType('exporttype') -declareType('valtype') -declareType('extern', False) - -# These are actually DECLARE_TYPE, but we don't need the vec or copy stuff. -declareOwn('memorytype') -declareOwn('externtype') -declareOwn('functype') - -# These are actually DECLARE_SHARABLE_REF, but we don't need the ref stuff. -declareOwn('module') - -# These are actually DECLARE_REF, but we don't need the ref stuff. -declareOwn('memory') -declareOwn('trap') -declareOwn('instance') -declareOwn('func') - -rawFns = ''' -WASM_API_EXTERN own wasm_engine_t* wasm_engine_new(); -WASM_API_EXTERN own wasm_store_t* wasm_store_new(wasm_engine_t*); -WASM_API_EXTERN own wasm_memorytype_t* wasm_memorytype_new(const wasm_limits_t*); -WASM_API_EXTERN own wasm_module_t* wasm_module_new(wasm_store_t*, const wasm_byte_vec_t* binary); -WASM_API_EXTERN void wasm_module_imports(const wasm_module_t*, own wasm_importtype_vec_t* out); -WASM_API_EXTERN const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*); -WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*); -WASM_API_EXTERN const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*); -WASM_API_EXTERN wasm_functype_t* wasm_externtype_as_functype(wasm_externtype_t*); -WASM_API_EXTERN void wasm_module_exports(const wasm_module_t*, own wasm_exporttype_vec_t* out); -WASM_API_EXTERN const wasm_name_t* wasm_exporttype_name(const wasm_exporttype_t*); -WASM_API_EXTERN const wasm_externtype_t* wasm_exporttype_type(const wasm_exporttype_t*); -WASM_API_EXTERN wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t*); -WASM_API_EXTERN own wasm_instance_t* wasm_instance_new(wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[], own wasm_trap_t**); -WASM_API_EXTERN void wasm_instance_exports(const wasm_instance_t*, own wasm_extern_vec_t* out); -WASM_API_EXTERN own wasm_memory_t* wasm_memory_new(wasm_store_t*, const wasm_memorytype_t*); -WASM_API_EXTERN byte_t* wasm_memory_data(wasm_memory_t*); -WASM_API_EXTERN size_t wasm_memory_data_size(const wasm_memory_t*); -WASM_API_EXTERN wasm_memory_pages_t wasm_memory_size(const wasm_memory_t*); -WASM_API_EXTERN bool wasm_memory_grow(wasm_memory_t*, wasm_memory_pages_t delta); -WASM_API_EXTERN wasm_externkind_t wasm_extern_kind(const wasm_extern_t*); -WASM_API_EXTERN wasm_func_t* wasm_extern_as_func(wasm_extern_t*); -WASM_API_EXTERN wasm_memory_t* wasm_extern_as_memory(wasm_extern_t*); -WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_params(const wasm_functype_t*); -WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_results(const wasm_functype_t*); -WASM_API_EXTERN own wasm_trap_t* wasm_func_call(const wasm_func_t*, const wasm_val_t args[], wasm_val_t results[]); -WASM_API_EXTERN wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t*); -''' -for f in rawFns.split('\n'): - if len(f.strip()) > 0: - addFn(f) - -unusedFns = { - 'wasm_byte_vec_copy', - 'wasm_exporttype_delete', - 'wasm_exporttype_copy', - 'wasm_exporttype_vec_copy', - 'wasm_extern_vec_copy', - 'wasm_importtype_delete', - 'wasm_importtype_copy', - 'wasm_importtype_vec_copy', - 'wasm_val_vec_copy', - 'wasm_val_vec_delete', - 'wasm_val_vec_new', - 'wasm_val_vec_new_empty', - 'wasm_val_vec_new_uninitialized', - 'wasm_valtype_copy', - 'wasm_valtype_vec_copy', -} - -genDoc = '''// This file has been automatically generated. Please do not edit it manually. -// To regenerate the file, use the following command -// "generate_ffi_boilerplate.py".''' - -thisDir = os.path.dirname(os.path.abspath(__file__)) - - -def readFile(filename): - with open(os.path.abspath(os.path.join(thisDir, filename)), 'r') as f: - return f.read() - - -def writeFile(filename, content): - with open(os.path.abspath(os.path.join(thisDir, '..', filename)), 'w') as f: - f.write(content) - - -wasmerApiText = readFile('wasmer_api_template.dart') -wasmerApiText = wasmerApiText.replace('/* */', getWasmerApi()) -wasmerApiText = wasmerApiText.replace('/* */', genDoc) -writeFile('wasmer_api.dart', wasmerApiText) - -runtimeText = readFile('runtime_template.dart') -runtimeText = runtimeText.replace('/* */', getRuntimeMemb()) -runtimeText = runtimeText.replace('/* */', getRuntimeLoad()) -runtimeText = runtimeText.replace('/* */', genDoc) -writeFile('runtime.dart', runtimeText) diff --git a/pkg/wasm/lib/src/tools/runtime_template.dart b/pkg/wasm/lib/src/tools/runtime_template.dart deleted file mode 100644 index d40388200a1..00000000000 --- a/pkg/wasm/lib/src/tools/runtime_template.dart +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/* */ - -import 'dart:convert'; -import 'dart:ffi'; -import 'dart:io'; -import 'dart:typed_data'; -import 'package:ffi/ffi.dart'; -import 'package:path/path.dart' as path; -import 'wasmer_api.dart'; - -class WasmImportDescriptor { - int kind; - String moduleName; - String name; - Pointer funcType; - WasmImportDescriptor(this.kind, this.moduleName, this.name, this.funcType); -} - -class WasmExportDescriptor { - int kind; - String name; - Pointer funcType; - WasmExportDescriptor(this.kind, this.name, this.funcType); -} - -class WasmRuntime { - static WasmRuntime? _inst; - - DynamicLibrary _lib; - late Pointer _engine; -/* */ - - factory WasmRuntime() { - WasmRuntime inst = _inst ?? WasmRuntime._init(); - _inst = inst; - return inst; - } - - static String _getLibName() { - if (Platform.isMacOS) return "libwasmer.dylib"; - if (Platform.isLinux) return "libwasmer.so"; - // TODO(dartbug.com/37882): Support more platforms. - throw Exception("Wasm not currently supported on this platform"); - } - - static String _getLibDir() { - // The common case, and how cli_util.dart computes the Dart SDK directory, - // path.dirname called twice on Platform.resolvedExecutable. - var commonLibDir = path.join( - path.absolute(path.dirname(path.dirname(Platform.resolvedExecutable))), - 'bin', - 'third_party', - 'wasmer'); - if (Directory(commonLibDir).existsSync()) { - return commonLibDir; - } - - // This is the less common case where the user is in the checked out Dart - // SDK, and is executing dart via: - // ./out/ReleaseX64/dart ... - var checkedOutLibDir = path.join( - path.absolute(path.dirname(Platform.resolvedExecutable)), - 'dart-sdk', - 'bin', - 'third_party', - 'wasmer'); - if (Directory(checkedOutLibDir).existsSync()) { - return checkedOutLibDir; - } - - // If neither returned above, we return the common case: - return commonLibDir; - } - - WasmRuntime._init() - : _lib = DynamicLibrary.open(path.join(_getLibDir(), _getLibName())) { -/* */ - - _engine = _engine_new(); - } - - Pointer newStore() { - return _store_new(_engine); - } - - Pointer compile(Pointer store, Uint8List data) { - var dataPtr = allocate(count: data.length); - for (int i = 0; i < data.length; ++i) { - dataPtr[i] = data[i]; - } - var dataVec = allocate(); - dataVec.ref.data = dataPtr; - dataVec.ref.length = data.length; - - var modulePtr = _module_new(store, dataVec); - - free(dataPtr); - free(dataVec); - - if (modulePtr == nullptr) { - throw Exception("Wasm module compile failed"); - } - - return modulePtr; - } - - List exportDescriptors(Pointer module) { - var exportsVec = allocate(); - _module_exports(module, exportsVec); - var exps = []; - for (var i = 0; i < exportsVec.ref.length; ++i) { - var exp = exportsVec.ref.data[i]; - var extern = _exporttype_type(exp); - var kind = _externtype_kind(extern); - var fnType = kind == WasmerExternKindFunction - ? _externtype_as_functype(extern) - : nullptr; - exps.add(WasmExportDescriptor( - kind, _exporttype_name(exp).ref.toString(), fnType)); - } - free(exportsVec); - return exps; - } - - List importDescriptors(Pointer module) { - var importsVec = allocate(); - _module_imports(module, importsVec); - var imps = []; - for (var i = 0; i < importsVec.ref.length; ++i) { - var imp = importsVec.ref.data[i]; - var extern = _importtype_type(imp); - var kind = _externtype_kind(extern); - var fnType = kind == WasmerExternKindFunction - ? _externtype_as_functype(extern) - : nullptr; - imps.add(WasmImportDescriptor( - kind, - _importtype_module(imp).ref.toString(), - _importtype_name(imp).ref.toString(), - fnType)); - } - free(importsVec); - return imps; - } - - Pointer instantiate( - Pointer store, - Pointer module, - Pointer> imports, - int numImports) { - var importsVec = allocate(); - _module_imports(module, importsVec); - if (importsVec.ref.length != numImports) { - throw Exception( - "Wrong number of imports. Expected ${importsVec.ref.length} but " + - "found $numImports."); - } - free(importsVec); - - var instancePtr = _instance_new(store, module, imports, nullptr); - if (instancePtr == nullptr) { - throw Exception("Wasm module instantiation failed"); - } - - return instancePtr; - } - - Pointer exports(Pointer instancePtr) { - var exports = allocate(); - _instance_exports(instancePtr, exports); - return exports; - } - - int externKind(Pointer extern) { - return _extern_kind(extern); - } - - Pointer externToFunction(Pointer extern) { - return _extern_as_func(extern); - } - - List getArgTypes(Pointer funcType) { - var types = []; - var args = _functype_params(funcType); - for (var i = 0; i < args.ref.length; ++i) { - types.add(_valtype_kind(args.ref.data[i])); - } - return types; - } - - int getReturnType(Pointer funcType) { - var rets = _functype_results(funcType); - if (rets.ref.length == 0) { - return WasmerValKindVoid; - } else if (rets.ref.length > 1) { - throw Exception("Multiple return values are not supported"); - } - return _valtype_kind(rets.ref.data[0]); - } - - void call(Pointer func, Pointer args, - Pointer results) { - _func_call(func, args, results); - } - - Pointer externToMemory(Pointer extern) { - return _extern_as_memory(extern); - } - - Pointer newMemory( - Pointer store, int pages, int? maxPages) { - var limPtr = allocate(); - limPtr.ref.min = pages; - limPtr.ref.max = maxPages ?? wasm_limits_max_default; - var memType = _memorytype_new(limPtr); - free(limPtr); - Pointer memPtr = _memory_new(store, memType); - - if (memPtr == nullptr) { - throw Exception("Failed to create memory"); - } - return memPtr; - } - - void growMemory(Pointer memory, int deltaPages) { - var result = _memory_grow(memory, deltaPages); - if (result == 0) { - throw Exception("Failed to grow memory"); - } - } - - int memoryLength(Pointer memory) { - return _memory_size(memory); - } - - Uint8List memoryView(Pointer memory) { - return _memory_data(memory).asTypedList(_memory_data_size(memory)); - } -} diff --git a/pkg/wasm/lib/src/tools/wasmer_api_template.dart b/pkg/wasm/lib/src/tools/wasmer_api_template.dart deleted file mode 100644 index 6a7717151ed..00000000000 --- a/pkg/wasm/lib/src/tools/wasmer_api_template.dart +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/* */ - -import 'dart:convert'; -import 'dart:ffi'; -import 'dart:typed_data'; - -// wasm_valkind_enum -const int WasmerValKindI32 = 0; -const int WasmerValKindI64 = 1; -const int WasmerValKindF32 = 2; -const int WasmerValKindF64 = 3; -// The void tag is not part of the C API. It's used to represent the return type -// of a void function. -const int WasmerValKindVoid = -1; - -// wasm_externkind_enum -const int WasmerExternKindFunction = 0; -const int WasmerExternKindGlobal = 1; -const int WasmerExternKindTable = 2; -const int WasmerExternKindMemory = 3; - -String wasmerExternKindName(int kind) { - switch (kind) { - case WasmerExternKindFunction: - return "function"; - case WasmerExternKindGlobal: - return "global"; - case WasmerExternKindTable: - return "table"; - case WasmerExternKindMemory: - return "memory"; - default: - return "unknown"; - } -} - -String wasmerValKindName(int kind) { - switch (kind) { - case WasmerValKindI32: - return "int32"; - case WasmerValKindI64: - return "int64"; - case WasmerValKindF32: - return "float32"; - case WasmerValKindF64: - return "float64"; - case WasmerValKindVoid: - return "void"; - default: - return "unknown"; - } -} - -// wasm_val_t -class WasmerVal extends Struct { - // wasm_valkind_t - @Uint8() - external int kind; - - // This is a union of int32_t, int64_t, float, and double. The kind determines - // which type it is. It's declared as an int64_t because that's large enough - // to hold all the types. We use ByteData to get the other types. - @Int64() - external int value; - - int get _off32 => Endian.host == Endian.little ? 0 : 4; - int get i64 => value; - ByteData get _getterBytes => ByteData(8)..setInt64(0, value, Endian.host); - int get i32 => _getterBytes.getInt32(_off32, Endian.host); - double get f32 => _getterBytes.getFloat32(_off32, Endian.host); - double get f64 => _getterBytes.getFloat64(0, Endian.host); - - set i64(int val) => value = val; - set _val(ByteData bytes) => value = bytes.getInt64(0, Endian.host); - set i32(int val) => _val = ByteData(8)..setInt32(_off32, val, Endian.host); - set f32(num val) => - _val = ByteData(8)..setFloat32(_off32, val as double, Endian.host); - set f64(num val) => - _val = ByteData(8)..setFloat64(0, val as double, Endian.host); - - bool get isI32 => kind == WasmerValKindI32; - bool get isI64 => kind == WasmerValKindI64; - bool get isF32 => kind == WasmerValKindF32; - bool get isF64 => kind == WasmerValKindF64; -} - -// wasmer_limits_t -class WasmerLimits extends Struct { - @Uint32() - external int min; - - @Uint32() - external int max; -} - -// Default maximum, which indicates no upper limit. -const int wasm_limits_max_default = 0xffffffff; - -/* */ diff --git a/pkg/wasm/lib/src/wasmer_api.dart b/pkg/wasm/lib/src/wasmer_api.dart index ad8219dbaeb..94dd651ae09 100644 --- a/pkg/wasm/lib/src/wasmer_api.dart +++ b/pkg/wasm/lib/src/wasmer_api.dart @@ -2,70 +2,116 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// This file has been automatically generated. Please do not edit it manually. -// To regenerate the file, use the following command -// "generate_ffi_boilerplate.py". - import 'dart:convert'; import 'dart:ffi'; import 'dart:typed_data'; -// wasm_valkind_enum -const int WasmerValKindI32 = 0; -const int WasmerValKindI64 = 1; -const int WasmerValKindF32 = 2; -const int WasmerValKindF64 = 3; +// wasmer_result_t +const int WasmerResultOk = 1; +const int WasmerResultError = 2; + +// wasmer_value_tag +const int WasmerValueTagI32 = 0; +const int WasmerValueTagI64 = 1; +const int WasmerValueTagF32 = 2; +const int WasmerValueTagF64 = 3; // The void tag is not part of the C API. It's used to represent the return type // of a void function. -const int WasmerValKindVoid = -1; +const int WasmerValueTagVoid = -1; -// wasm_externkind_enum -const int WasmerExternKindFunction = 0; -const int WasmerExternKindGlobal = 1; -const int WasmerExternKindTable = 2; -const int WasmerExternKindMemory = 3; +// wasmer_import_export_kind +const int WasmerImpExpKindFunction = 0; +const int WasmerImpExpKindGlobal = 1; +const int WasmerImpExpKindMemory = 2; +const int WasmerImpExpKindTable = 3; -String wasmerExternKindName(int kind) { +String wasmerImpExpKindName(int kind) { switch (kind) { - case WasmerExternKindFunction: + case WasmerImpExpKindFunction: return "function"; - case WasmerExternKindGlobal: + case WasmerImpExpKindGlobal: return "global"; - case WasmerExternKindTable: - return "table"; - case WasmerExternKindMemory: + case WasmerImpExpKindMemory: return "memory"; + case WasmerImpExpKindTable: + return "table"; default: return "unknown"; } } -String wasmerValKindName(int kind) { - switch (kind) { - case WasmerValKindI32: - return "int32"; - case WasmerValKindI64: - return "int64"; - case WasmerValKindF32: - return "float32"; - case WasmerValKindF64: - return "float64"; - case WasmerValKindVoid: - return "void"; - default: - return "unknown"; - } +// wasmer_module_t +class WasmerModule extends Struct {} + +// wasmer_instance_t +class WasmerInstance extends Struct {} + +// wasmer_exports_t +class WasmerExports extends Struct {} + +// wasmer_export_t +class WasmerExport extends Struct {} + +// wasmer_export_descriptors_t +class WasmerExportDescriptors extends Struct {} + +// wasmer_export_descriptor_t +class WasmerExportDescriptor extends Struct {} + +// wasmer_export_func_t +class WasmerExportFunc extends Struct {} + +// wasmer_import_descriptors_t +class WasmerImportDescriptors extends Struct {} + +// wasmer_import_descriptor_t +class WasmerImportDescriptor extends Struct {} + +// wasmer_memory_t +class WasmerMemory extends Struct {} + +// wasmer_import_t +class WasmerImport extends Struct { + external Pointer module_name; + + @Uint32() + external int module_name_length; + + external Pointer import_name; + + @Uint32() + external int import_name_length; + + // wasmer_import_export_kind + @Uint32() + external int tag; + + // wasmer_import_export_value, which is a union of wasmer_import_func_t*, + // wasmer_table_t*, wasmer_memory_t*, and wasmer_global_t*. The tag determines + // which type it is. + external Pointer value; } -// wasm_val_t -class WasmerVal extends Struct { - // wasm_valkind_t - @Uint8() - external int kind; +// wasmer_byte_array +class WasmerByteArray extends Struct { + external Pointer bytes; - // This is a union of int32_t, int64_t, float, and double. The kind determines - // which type it is. It's declared as an int64_t because that's large enough - // to hold all the types. We use ByteData to get the other types. + @Uint32() + external int length; + + Uint8List get list => bytes.asTypedList(length); + String get string => utf8.decode(list); +} + +// wasmer_value_t +class WasmerValue extends Struct { + // wasmer_value_tag + @Uint32() + external int tag; + + // wasmer_value, which is a union of int32_t, int64_t, float, and double. The + // tag determines which type it is. It's declared as an int64_t because that's + // large enough to hold all the types. We use ByteData to get the other types. @Int64() external int value; @@ -84,10 +130,10 @@ class WasmerVal extends Struct { set f64(num val) => _val = ByteData(8)..setFloat64(0, val as double, Endian.host); - bool get isI32 => kind == WasmerValKindI32; - bool get isI64 => kind == WasmerValKindI64; - bool get isF32 => kind == WasmerValKindF32; - bool get isF64 => kind == WasmerValKindF64; + bool get isI32 => tag == WasmerValueTagI32; + bool get isI64 => tag == WasmerValueTagI64; + bool get isF32 => tag == WasmerValueTagF32; + bool get isF64 => tag == WasmerValueTagF64; } // wasmer_limits_t @@ -95,417 +141,196 @@ class WasmerLimits extends Struct { @Uint32() external int min; + // bool + @Uint8() + external int has_max; + @Uint32() external int max; } -// Default maximum, which indicates no upper limit. -const int wasm_limits_max_default = 0xffffffff; +// wasmer_compile +typedef NativeWasmerCompileFn = Uint32 Function( + Pointer>, Pointer, Uint32); +typedef WasmerCompileFn = int Function( + Pointer>, Pointer, int); -// wasm_engine_t -class WasmerEngine extends Struct {} +// wasmer_module_instantiate +typedef NativeWasmerInstantiateFn = Uint32 Function(Pointer, + Pointer>, Pointer, Int32); +typedef WasmerInstantiateFn = int Function(Pointer, + Pointer>, Pointer, int); -// wasm_exporttype_t -class WasmerExporttype extends Struct {} - -// wasm_extern_t -class WasmerExtern extends Struct {} - -// wasm_externtype_t -class WasmerExterntype extends Struct {} - -// wasm_func_t -class WasmerFunc extends Struct {} - -// wasm_functype_t -class WasmerFunctype extends Struct {} - -// wasm_importtype_t -class WasmerImporttype extends Struct {} - -// wasm_instance_t -class WasmerInstance extends Struct {} - -// wasm_memory_t -class WasmerMemory extends Struct {} - -// wasm_memorytype_t -class WasmerMemorytype extends Struct {} - -// wasm_module_t -class WasmerModule extends Struct {} - -// wasm_store_t -class WasmerStore extends Struct {} - -// wasm_trap_t -class WasmerTrap extends Struct {} - -// wasm_valtype_t -class WasmerValtype extends Struct {} - -// wasm_byte_vec_t -class WasmerByteVec extends Struct { - @Uint64() - external int length; - - external Pointer data; - - Uint8List get list => data.asTypedList(length); - String toString() => utf8.decode(list); -} - -// wasm_exporttype_vec_t -class WasmerExporttypeVec extends Struct { - @Uint64() - external int length; - - external Pointer> data; -} - -// wasm_extern_vec_t -class WasmerExternVec extends Struct { - @Uint64() - external int length; - - external Pointer> data; -} - -// wasm_importtype_vec_t -class WasmerImporttypeVec extends Struct { - @Uint64() - external int length; - - external Pointer> data; -} - -// wasm_val_vec_t -class WasmerValVec extends Struct { - @Uint64() - external int length; - - external Pointer data; -} - -// wasm_valtype_vec_t -class WasmerValtypeVec extends Struct { - @Uint64() - external int length; - - external Pointer> data; -} - -// wasm_byte_vec_delete -typedef NativeWasmerByteVecDeleteFn = Void Function(Pointer); -typedef WasmerByteVecDeleteFn = void Function(Pointer); - -// wasm_byte_vec_new -typedef NativeWasmerByteVecNewFn = Void Function( - Pointer, Uint64, Pointer); -typedef WasmerByteVecNewFn = void Function( - Pointer, int, Pointer); - -// wasm_byte_vec_new_empty -typedef NativeWasmerByteVecNewEmptyFn = Void Function(Pointer); -typedef WasmerByteVecNewEmptyFn = void Function(Pointer); - -// wasm_byte_vec_new_uninitialized -typedef NativeWasmerByteVecNewUninitializedFn = Void Function( - Pointer, Uint64); -typedef WasmerByteVecNewUninitializedFn = void Function( - Pointer, int); - -// wasm_engine_delete -typedef NativeWasmerEngineDeleteFn = Void Function(Pointer); -typedef WasmerEngineDeleteFn = void Function(Pointer); - -// wasm_engine_new -typedef NativeWasmerEngineNewFn = Pointer Function(); -typedef WasmerEngineNewFn = Pointer Function(); - -// wasm_exporttype_name -typedef NativeWasmerExporttypeNameFn = Pointer Function( - Pointer); -typedef WasmerExporttypeNameFn = Pointer Function( - Pointer); - -// wasm_exporttype_type -typedef NativeWasmerExporttypeTypeFn = Pointer Function( - Pointer); -typedef WasmerExporttypeTypeFn = Pointer Function( - Pointer); - -// wasm_exporttype_vec_delete -typedef NativeWasmerExporttypeVecDeleteFn = Void Function( - Pointer); -typedef WasmerExporttypeVecDeleteFn = void Function( - Pointer); - -// wasm_exporttype_vec_new -typedef NativeWasmerExporttypeVecNewFn = Void Function( - Pointer, Uint64, Pointer>); -typedef WasmerExporttypeVecNewFn = void Function( - Pointer, int, Pointer>); - -// wasm_exporttype_vec_new_empty -typedef NativeWasmerExporttypeVecNewEmptyFn = Void Function( - Pointer); -typedef WasmerExporttypeVecNewEmptyFn = void Function( - Pointer); - -// wasm_exporttype_vec_new_uninitialized -typedef NativeWasmerExporttypeVecNewUninitializedFn = Void Function( - Pointer, Uint64); -typedef WasmerExporttypeVecNewUninitializedFn = void Function( - Pointer, int); - -// wasm_extern_as_func -typedef NativeWasmerExternAsFuncFn = Pointer Function( - Pointer); -typedef WasmerExternAsFuncFn = Pointer Function( - Pointer); - -// wasm_extern_as_memory -typedef NativeWasmerExternAsMemoryFn = Pointer Function( - Pointer); -typedef WasmerExternAsMemoryFn = Pointer Function( - Pointer); - -// wasm_extern_delete -typedef NativeWasmerExternDeleteFn = Void Function(Pointer); -typedef WasmerExternDeleteFn = void Function(Pointer); - -// wasm_extern_kind -typedef NativeWasmerExternKindFn = Uint8 Function(Pointer); -typedef WasmerExternKindFn = int Function(Pointer); - -// wasm_extern_vec_delete -typedef NativeWasmerExternVecDeleteFn = Void Function(Pointer); -typedef WasmerExternVecDeleteFn = void Function(Pointer); - -// wasm_extern_vec_new -typedef NativeWasmerExternVecNewFn = Void Function( - Pointer, Uint64, Pointer>); -typedef WasmerExternVecNewFn = void Function( - Pointer, int, Pointer>); - -// wasm_extern_vec_new_empty -typedef NativeWasmerExternVecNewEmptyFn = Void Function( - Pointer); -typedef WasmerExternVecNewEmptyFn = void Function(Pointer); - -// wasm_extern_vec_new_uninitialized -typedef NativeWasmerExternVecNewUninitializedFn = Void Function( - Pointer, Uint64); -typedef WasmerExternVecNewUninitializedFn = void Function( - Pointer, int); - -// wasm_externtype_as_functype -typedef NativeWasmerExterntypeAsFunctypeFn = Pointer Function( - Pointer); -typedef WasmerExterntypeAsFunctypeFn = Pointer Function( - Pointer); - -// wasm_externtype_delete -typedef NativeWasmerExterntypeDeleteFn = Void Function( - Pointer); -typedef WasmerExterntypeDeleteFn = void Function(Pointer); - -// wasm_externtype_kind -typedef NativeWasmerExterntypeKindFn = Uint8 Function( - Pointer); -typedef WasmerExterntypeKindFn = int Function(Pointer); - -// wasm_func_call -typedef NativeWasmerFuncCallFn = Pointer Function( - Pointer, Pointer, Pointer); -typedef WasmerFuncCallFn = Pointer Function( - Pointer, Pointer, Pointer); - -// wasm_func_delete -typedef NativeWasmerFuncDeleteFn = Void Function(Pointer); -typedef WasmerFuncDeleteFn = void Function(Pointer); - -// wasm_functype_delete -typedef NativeWasmerFunctypeDeleteFn = Void Function(Pointer); -typedef WasmerFunctypeDeleteFn = void Function(Pointer); - -// wasm_functype_params -typedef NativeWasmerFunctypeParamsFn = Pointer Function( - Pointer); -typedef WasmerFunctypeParamsFn = Pointer Function( - Pointer); - -// wasm_functype_results -typedef NativeWasmerFunctypeResultsFn = Pointer Function( - Pointer); -typedef WasmerFunctypeResultsFn = Pointer Function( - Pointer); - -// wasm_importtype_module -typedef NativeWasmerImporttypeModuleFn = Pointer Function( - Pointer); -typedef WasmerImporttypeModuleFn = Pointer Function( - Pointer); - -// wasm_importtype_name -typedef NativeWasmerImporttypeNameFn = Pointer Function( - Pointer); -typedef WasmerImporttypeNameFn = Pointer Function( - Pointer); - -// wasm_importtype_type -typedef NativeWasmerImporttypeTypeFn = Pointer Function( - Pointer); -typedef WasmerImporttypeTypeFn = Pointer Function( - Pointer); - -// wasm_importtype_vec_delete -typedef NativeWasmerImporttypeVecDeleteFn = Void Function( - Pointer); -typedef WasmerImporttypeVecDeleteFn = void Function( - Pointer); - -// wasm_importtype_vec_new -typedef NativeWasmerImporttypeVecNewFn = Void Function( - Pointer, Uint64, Pointer>); -typedef WasmerImporttypeVecNewFn = void Function( - Pointer, int, Pointer>); - -// wasm_importtype_vec_new_empty -typedef NativeWasmerImporttypeVecNewEmptyFn = Void Function( - Pointer); -typedef WasmerImporttypeVecNewEmptyFn = void Function( - Pointer); - -// wasm_importtype_vec_new_uninitialized -typedef NativeWasmerImporttypeVecNewUninitializedFn = Void Function( - Pointer, Uint64); -typedef WasmerImporttypeVecNewUninitializedFn = void Function( - Pointer, int); - -// wasm_instance_delete -typedef NativeWasmerInstanceDeleteFn = Void Function(Pointer); -typedef WasmerInstanceDeleteFn = void Function(Pointer); - -// wasm_instance_exports +// wasmer_instance_exports typedef NativeWasmerInstanceExportsFn = Void Function( - Pointer, Pointer); + Pointer, Pointer>); typedef WasmerInstanceExportsFn = void Function( - Pointer, Pointer); + Pointer, Pointer>); -// wasm_instance_new -typedef NativeWasmerInstanceNewFn = Pointer Function( - Pointer, - Pointer, - Pointer>, - Pointer>); -typedef WasmerInstanceNewFn = Pointer Function( - Pointer, - Pointer, - Pointer>, - Pointer>); +// wasmer_exports_len +typedef NativeWasmerExportsLenFn = Int32 Function(Pointer); +typedef WasmerExportsLenFn = int Function(Pointer); -// wasm_memory_data +// wasmer_exports_get +typedef NativeWasmerExportsGetFn = Pointer Function( + Pointer, Int32); +typedef WasmerExportsGetFn = Pointer Function( + Pointer, int); + +// wasmer_export_descriptors +typedef NativeWasmerExportDescriptorsFn = Void Function( + Pointer, Pointer>); +typedef WasmerExportDescriptorsFn = void Function( + Pointer, Pointer>); + +// wasmer_export_descriptors_destroy +typedef NativeWasmerExportDescriptorsDestroyFn = Void Function( + Pointer); +typedef WasmerExportDescriptorsDestroyFn = void Function( + Pointer); + +// wasmer_export_descriptors_len +typedef NativeWasmerExportDescriptorsLenFn = Int32 Function( + Pointer); +typedef WasmerExportDescriptorsLenFn = int Function( + Pointer); + +// wasmer_export_descriptors_get +typedef NativeWasmerExportDescriptorsGetFn = Pointer + Function(Pointer, Int32); +typedef WasmerExportDescriptorsGetFn = Pointer Function( + Pointer, int); + +// wasmer_export_descriptor_kind +typedef NativeWasmerExportDescriptorKindFn = Uint32 Function( + Pointer); +typedef WasmerExportDescriptorKindFn = int Function( + Pointer); + +// wasmer_export_descriptor_name_ptr +typedef NativeWasmerExportDescriptorNamePtrFn = Void Function( + Pointer, Pointer); +typedef WasmerExportDescriptorNamePtrFn = void Function( + Pointer, Pointer); + +// wasmer_import_descriptors +typedef NativeWasmerImportDescriptorsFn = Void Function( + Pointer, Pointer>); +typedef WasmerImportDescriptorsFn = void Function( + Pointer, Pointer>); + +// wasmer_import_descriptors_destroy +typedef NativeWasmerImportDescriptorsDestroyFn = Void Function( + Pointer); +typedef WasmerImportDescriptorsDestroyFn = void Function( + Pointer); + +// wasmer_import_descriptors_len +typedef NativeWasmerImportDescriptorsLenFn = Int32 Function( + Pointer); +typedef WasmerImportDescriptorsLenFn = int Function( + Pointer); + +// wasmer_import_descriptors_get +typedef NativeWasmerImportDescriptorsGetFn = Pointer + Function(Pointer, Int32); +typedef WasmerImportDescriptorsGetFn = Pointer Function( + Pointer, int); + +// wasmer_import_descriptor_kind +typedef NativeWasmerImportDescriptorKindFn = Uint32 Function( + Pointer); +typedef WasmerImportDescriptorKindFn = int Function( + Pointer); + +// wasmer_import_descriptor_module_name_ptr +typedef NativeWasmerImportDescriptorModuleNamePtrFn = Void Function( + Pointer, Pointer); +typedef WasmerImportDescriptorModuleNamePtrFn = void Function( + Pointer, Pointer); + +// wasmer_import_descriptor_name_ptr +typedef NativeWasmerImportDescriptorNamePtrFn = Void Function( + Pointer, Pointer); +typedef WasmerImportDescriptorNamePtrFn = void Function( + Pointer, Pointer); + +// wasmer_export_name_ptr +typedef NativeWasmerExportNamePtrFn = Void Function( + Pointer, Pointer); +typedef WasmerExportNamePtrFn = void Function( + Pointer, Pointer); + +// wasmer_export_kind +typedef NativeWasmerExportKindFn = Uint32 Function(Pointer); +typedef WasmerExportKindFn = int Function(Pointer); + +// wasmer_export_to_func +typedef NativeWasmerExportToFuncFn = Pointer Function( + Pointer); +typedef WasmerExportToFuncFn = Pointer Function( + Pointer); + +// wasmer_export_func_returns_arity +typedef NativeWasmerExportFuncReturnsArityFn = Uint32 Function( + Pointer, Pointer); +typedef WasmerExportFuncReturnsArityFn = int Function( + Pointer, Pointer); + +// wasmer_export_func_returns +typedef NativeWasmerExportFuncReturnsFn = Uint32 Function( + Pointer, Pointer, Uint32); +typedef WasmerExportFuncReturnsFn = int Function( + Pointer, Pointer, int); + +// wasmer_export_func_params_arity +typedef NativeWasmerExportFuncParamsArityFn = Uint32 Function( + Pointer, Pointer); +typedef WasmerExportFuncParamsArityFn = int Function( + Pointer, Pointer); + +// wasmer_export_func_params +typedef NativeWasmerExportFuncParamsFn = Uint32 Function( + Pointer, Pointer, Uint32); +typedef WasmerExportFuncParamsFn = int Function( + Pointer, Pointer, int); + +// wasmer_export_func_call +typedef NativeWasmerExportFuncCallFn = Uint32 Function( + Pointer, + Pointer, + Uint32, + Pointer, + Uint32); +typedef WasmerExportFuncCallFn = int Function(Pointer, + Pointer, int, Pointer, int); + +// wasmer_export_to_memory +typedef NativeWasmerExportToMemoryFn = Uint32 Function( + Pointer, Pointer>); +typedef WasmerExportToMemoryFn = int Function( + Pointer, Pointer>); + +// wasmer_memory_new_ptr +typedef NativeWasmerMemoryNewPtrFn = Uint32 Function( + Pointer>, Pointer); +typedef WasmerMemoryNewPtrFn = int Function( + Pointer>, Pointer); + +// wasmer_memory_grow +typedef NativeWasmerMemoryGrowFn = Uint32 Function( + Pointer, Uint32); +typedef WasmerMemoryGrowFn = int Function(Pointer, int); + +// wasmer_memory_length +typedef NativeWasmerMemoryLengthFn = Uint32 Function(Pointer); +typedef WasmerMemoryLengthFn = int Function(Pointer); + +// wasmer_memory_data typedef NativeWasmerMemoryDataFn = Pointer Function( Pointer); typedef WasmerMemoryDataFn = Pointer Function(Pointer); -// wasm_memory_data_size -typedef NativeWasmerMemoryDataSizeFn = Uint64 Function(Pointer); -typedef WasmerMemoryDataSizeFn = int Function(Pointer); - -// wasm_memory_delete -typedef NativeWasmerMemoryDeleteFn = Void Function(Pointer); -typedef WasmerMemoryDeleteFn = void Function(Pointer); - -// wasm_memory_grow -typedef NativeWasmerMemoryGrowFn = Uint8 Function( - Pointer, Uint32); -typedef WasmerMemoryGrowFn = int Function(Pointer, int); - -// wasm_memory_new -typedef NativeWasmerMemoryNewFn = Pointer Function( - Pointer, Pointer); -typedef WasmerMemoryNewFn = Pointer Function( - Pointer, Pointer); - -// wasm_memory_size -typedef NativeWasmerMemorySizeFn = Uint32 Function(Pointer); -typedef WasmerMemorySizeFn = int Function(Pointer); - -// wasm_memorytype_delete -typedef NativeWasmerMemorytypeDeleteFn = Void Function( - Pointer); -typedef WasmerMemorytypeDeleteFn = void Function(Pointer); - -// wasm_memorytype_new -typedef NativeWasmerMemorytypeNewFn = Pointer Function( - Pointer); -typedef WasmerMemorytypeNewFn = Pointer Function( - Pointer); - -// wasm_module_delete -typedef NativeWasmerModuleDeleteFn = Void Function(Pointer); -typedef WasmerModuleDeleteFn = void Function(Pointer); - -// wasm_module_exports -typedef NativeWasmerModuleExportsFn = Void Function( - Pointer, Pointer); -typedef WasmerModuleExportsFn = void Function( - Pointer, Pointer); - -// wasm_module_imports -typedef NativeWasmerModuleImportsFn = Void Function( - Pointer, Pointer); -typedef WasmerModuleImportsFn = void Function( - Pointer, Pointer); - -// wasm_module_new -typedef NativeWasmerModuleNewFn = Pointer Function( - Pointer, Pointer); -typedef WasmerModuleNewFn = Pointer Function( - Pointer, Pointer); - -// wasm_store_delete -typedef NativeWasmerStoreDeleteFn = Void Function(Pointer); -typedef WasmerStoreDeleteFn = void Function(Pointer); - -// wasm_store_new -typedef NativeWasmerStoreNewFn = Pointer Function( - Pointer); -typedef WasmerStoreNewFn = Pointer Function(Pointer); - -// wasm_trap_delete -typedef NativeWasmerTrapDeleteFn = Void Function(Pointer); -typedef WasmerTrapDeleteFn = void Function(Pointer); - -// wasm_valtype_delete -typedef NativeWasmerValtypeDeleteFn = Void Function(Pointer); -typedef WasmerValtypeDeleteFn = void Function(Pointer); - -// wasm_valtype_kind -typedef NativeWasmerValtypeKindFn = Uint8 Function(Pointer); -typedef WasmerValtypeKindFn = int Function(Pointer); - -// wasm_valtype_vec_delete -typedef NativeWasmerValtypeVecDeleteFn = Void Function( - Pointer); -typedef WasmerValtypeVecDeleteFn = void Function(Pointer); - -// wasm_valtype_vec_new -typedef NativeWasmerValtypeVecNewFn = Void Function( - Pointer, Uint64, Pointer>); -typedef WasmerValtypeVecNewFn = void Function( - Pointer, int, Pointer>); - -// wasm_valtype_vec_new_empty -typedef NativeWasmerValtypeVecNewEmptyFn = Void Function( - Pointer); -typedef WasmerValtypeVecNewEmptyFn = void Function(Pointer); - -// wasm_valtype_vec_new_uninitialized -typedef NativeWasmerValtypeVecNewUninitializedFn = Void Function( - Pointer, Uint64); -typedef WasmerValtypeVecNewUninitializedFn = void Function( - Pointer, int); +// wasmer_memory_data_length +typedef NativeWasmerMemoryDataLengthFn = Uint32 Function(Pointer); +typedef WasmerMemoryDataLengthFn = int Function(Pointer); diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index 392c905101d..9444e509210 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -586,17 +586,16 @@ copy("copy_wasmer") { visibility = [ ":create_common_sdk" ] deps = [ ":copy_libraries", - "../third_party/wasmer:wasmer", + "../third_party/wasmer:wasmer_wrapper", ] outputs = [ "$root_out_dir/dart-sdk/bin/third_party/wasmer/{{source_file_part}}" ] if (is_win) { - sources = [ "$target_out_dir/../third_party/wasmer/wasmer.dll" ] + sources = [ "$root_out_dir/wasmer_wrapper.dll" ] } else if (is_mac) { - sources = [ "$target_out_dir/../third_party/wasmer/libwasmer.dylib" ] + sources = [ "$root_out_dir/libwasmer_wrapper.dylib" ] } else { - # TODO(dartbug.com/37882): Support Fuchsia. - sources = [ "$target_out_dir/../third_party/wasmer/libwasmer.so" ] + sources = [ "$root_out_dir/libwasmer_wrapper.so" ] } } diff --git a/tests/lib/wasm/memory_error_test.dart b/tests/lib/wasm/memory_error_test.dart index f02dc6c9bcf..3a172d82b6e 100644 --- a/tests/lib/wasm/memory_error_test.dart +++ b/tests/lib/wasm/memory_error_test.dart @@ -9,14 +9,9 @@ import "package:wasm/wasm.dart"; import "dart:typed_data"; void main() { - // Empty wasm module. - var data = Uint8List.fromList( - [0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00]); - var module = WasmModule(data); - - Expect.throws(() => module.createMemory(1000000000)); - var mem = module.createMemory(100); + Expect.throws(() => WasmMemory(1000000000)); + var mem = WasmMemory(100); Expect.throws(() => mem.grow(1000000000)); - mem = module.createMemory(100, 200); + mem = WasmMemory(100, 200); Expect.throws(() => mem.grow(300)); } diff --git a/tests/lib/wasm/memory_test.dart b/tests/lib/wasm/memory_test.dart index 544c6a1ec65..ecaf43306c0 100644 --- a/tests/lib/wasm/memory_test.dart +++ b/tests/lib/wasm/memory_test.dart @@ -9,12 +9,7 @@ import "package:wasm/wasm.dart"; import "dart:typed_data"; void main() { - // Empty wasm module. - var data = Uint8List.fromList( - [0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00]); - var module = WasmModule(data); - - var mem = module.createMemory(100); + var mem = WasmMemory(100); Expect.equals(100, mem.lengthInPages); Expect.equals(100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes); diff --git a/tests/lib_2/wasm/basic_test.dart b/tests/lib_2/wasm/basic_test.dart index da2fb9a0c2a..72f4c6c68e2 100644 --- a/tests/lib_2/wasm/basic_test.dart +++ b/tests/lib_2/wasm/basic_test.dart @@ -22,7 +22,7 @@ void main() { var inst = WasmModule(data).instantiate(WasmImports()); var fn = inst.lookupFunction("square"); - int n = fn(1234); + int n = fn.call(1234); Expect.equals(1234 * 1234, n); diff --git a/tests/lib_2/wasm/memory_error_test.dart b/tests/lib_2/wasm/memory_error_test.dart index f02dc6c9bcf..3a172d82b6e 100644 --- a/tests/lib_2/wasm/memory_error_test.dart +++ b/tests/lib_2/wasm/memory_error_test.dart @@ -9,14 +9,9 @@ import "package:wasm/wasm.dart"; import "dart:typed_data"; void main() { - // Empty wasm module. - var data = Uint8List.fromList( - [0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00]); - var module = WasmModule(data); - - Expect.throws(() => module.createMemory(1000000000)); - var mem = module.createMemory(100); + Expect.throws(() => WasmMemory(1000000000)); + var mem = WasmMemory(100); Expect.throws(() => mem.grow(1000000000)); - mem = module.createMemory(100, 200); + mem = WasmMemory(100, 200); Expect.throws(() => mem.grow(300)); } diff --git a/tests/lib_2/wasm/memory_test.dart b/tests/lib_2/wasm/memory_test.dart index 544c6a1ec65..ecaf43306c0 100644 --- a/tests/lib_2/wasm/memory_test.dart +++ b/tests/lib_2/wasm/memory_test.dart @@ -9,12 +9,7 @@ import "package:wasm/wasm.dart"; import "dart:typed_data"; void main() { - // Empty wasm module. - var data = Uint8List.fromList( - [0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00]); - var module = WasmModule(data); - - var mem = module.createMemory(100); + var mem = WasmMemory(100); Expect.equals(100, mem.lengthInPages); Expect.equals(100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes); diff --git a/third_party/wasmer/BUILD.gn b/third_party/wasmer/BUILD.gn index f3398f5e29e..afd36a8859b 100644 --- a/third_party/wasmer/BUILD.gn +++ b/third_party/wasmer/BUILD.gn @@ -1,6 +1,17 @@ import("../../build/rust/rust.gni") -rust_library("wasmer") { - lib_name = "wasmer" - shared = true +shared_library("wasmer_wrapper") { + sources = [ + "wasmer.hh", + "wasmer_wrapper.cc", + ] + deps = [ ":wasmer_lib" ] + if (is_linux) { + libs = [ "rt" ] + } + ldflags = [ "-Wl,--no-as-needed" ] # Force linking of all wasmer symbols. +} + +rust_library("wasmer_lib") { + lib_name = "wasmer" } diff --git a/third_party/wasmer/Cargo.toml b/third_party/wasmer/Cargo.toml index bc52adad6a4..bfe61724256 100644 --- a/third_party/wasmer/Cargo.toml +++ b/third_party/wasmer/Cargo.toml @@ -1,13 +1,11 @@ [package] name = "wasmer" -version = "1.0.0-alpha3" +version = "0.17.1" [lib] name = "wasmer" -crate-type = ["dylib"] +crate-type = ["staticlib"] path = "wasmer.rs" -[dependencies.wasmer-c-api] -version = "1.0.0-alpha3" -default-features = false -features = ["jit", "cranelift", "wasi"] +[dependencies] +wasmer-runtime-c-api = "0.17.1" diff --git a/third_party/wasmer/LICENSE b/third_party/wasmer/LICENSE new file mode 100644 index 00000000000..62bb543eb9e --- /dev/null +++ b/third_party/wasmer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019-present Wasmer, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/wasmer/README.google b/third_party/wasmer/README.google new file mode 100644 index 00000000000..aec18966f3e --- /dev/null +++ b/third_party/wasmer/README.google @@ -0,0 +1,11 @@ +Name: Wasmer Runtime C API +Short Name: wasmer +URL: https://github.com/wasmerio/wasmer/tree/master/lib/runtime-c-api +Version: 0.6.0 +Date: August 16, 2019 +License: MIT + +Description: +This directory contains an unmodified copy of wasmer.hh from the Wasmer Runtime +C API (and README.md and LICENCE). Other files in this directory are added to +build the corresponding rust library. diff --git a/third_party/wasmer/README.md b/third_party/wasmer/README.md new file mode 100644 index 00000000000..d1475b7fdea --- /dev/null +++ b/third_party/wasmer/README.md @@ -0,0 +1,140 @@ +

+ + Wasmer logo + +

+ +

+ + Build Status + + + License + + + Join the Wasmer Community + + + Number of downloads from crates.io + + + Wasmer C API Documentation + +

+ +# Wasmer Runtime C API + +Wasmer is a standalone JIT WebAssembly runtime, aiming to be fully +compatible with WASI, Emscripten, Rust and Go. [Learn +more](https://github.com/wasmerio/wasmer). + +This crate exposes a C and a C++ API for the Wasmer runtime. + +# Usage + +The C and C++ header files can be found in the source tree of this +crate, respectively [`wasmer.h`][wasmer_h] and +[`wasmer.hh`][wasmer_hh]. They are automatically generated, and always +up-to-date in this repository. +The runtime shared library (so, dll, dylib) can also be downloaded in Wasmer [release page](https://github.com/wasmerio/wasmer/releases). + +You can find the full C API documentation here: +https://wasmerio.github.io/wasmer/c/runtime-c-api/ + +Here is a simple example to use the C API: + +```c +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + // Read the Wasm file bytes. + FILE *file = fopen("sum.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + // Prepare the imports. + wasmer_import_t imports[] = {}; + + // Instantiate! + wasmer_instance_t *instance = NULL; + wasmer_result_t instantiation_result = wasmer_instantiate(&instance, bytes, len, imports, 0); + + assert(instantiation_result == WASMER_OK); + + // Let's call a function. + // Start by preparing the arguments. + + // Value of argument #1 is `7i32`. + wasmer_value_t argument_one; + argument_one.tag = WASM_I32; + argument_one.value.I32 = 7; + + // Value of argument #2 is `8i32`. + wasmer_value_t argument_two; + argument_two.tag = WASM_I32; + argument_two.value.I32 = 8; + + // Prepare the arguments. + wasmer_value_t arguments[] = {argument_one, argument_two}; + + // Prepare the return value. + wasmer_value_t result_one; + wasmer_value_t results[] = {result_one}; + + // Call the `sum` function with the prepared arguments and the return value. + wasmer_result_t call_result = wasmer_instance_call(instance, "sum", arguments, 2, results, 1); + + // Let's display the result. + printf("Call result: %d\n", call_result); + printf("Result: %d\n", results[0].value.I32); + + // `sum(7, 8) == 15`. + assert(results[0].value.I32 == 15); + assert(call_result == WASMER_OK); + + wasmer_instance_destroy(instance); + + return 0; +} +``` + +# Testing + +Tests are run using the release build of the library. If you make +changes or compile with non-default features, please ensure you +rebuild in release mode for the tests to see the changes. + +The tests can be run via `cargo test`, such as: + +```sh +$ cargo test --release -- --nocapture +``` + +To run tests manually, enter the `lib/runtime-c-api/tests` directory +and run the following commands: + +```sh +$ cmake . +$ make +$ make test +``` + + +# License + +Wasmer is primarily distributed under the terms of the [MIT +license][mit-license] ([LICENSE][license]). + + +[wasmer_h]: ./wasmer.h +[wasmer_hh]: ./wasmer.hh +[mit-license]: http://opensource.org/licenses/MIT +[license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE diff --git a/third_party/wasmer/wasmer.hh b/third_party/wasmer/wasmer.hh new file mode 100644 index 00000000000..647e637d03f --- /dev/null +++ b/third_party/wasmer/wasmer.hh @@ -0,0 +1,1273 @@ + +#if !defined(WASMER_H_MACROS) + +#define WASMER_H_MACROS + +// Define the `ARCH_X86_X64` constant. +#if defined(MSVC) && defined(_M_AMD64) +# define ARCH_X86_64 +#elif (defined(GCC) || defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__) +# define ARCH_X86_64 +#endif + +// Compatibility with non-Clang compilers. +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif + +// Compatibility with non-Clang compilers. +#if !defined(__has_declspec_attribute) +# define __has_declspec_attribute(x) 0 +#endif + +// Define the `DEPRECATED` macro. +#if defined(GCC) || defined(__GNUC__) || __has_attribute(deprecated) +# define DEPRECATED(message) __attribute__((deprecated(message))) +#elif defined(MSVC) || __has_declspec_attribute(deprecated) +# define DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#define WASMER_WASI_ENABLED +#endif // WASMER_H_MACROS + + +#ifndef WASMER_H +#define WASMER_H + +#include +#include +#include +#include + +#if defined(WASMER_WASI_ENABLED) +enum class Version : uint8_t { + /// Version cannot be detected or is unknown. + Unknown = 0, + /// Latest version. See `wasmer_wasi::WasiVersion::Latest` to + /// learn more. + Latest = 1, + /// `wasi_unstable`. + Snapshot0 = 2, + /// `wasi_snapshot_preview1`. + Snapshot1 = 3, +}; +#endif + +/// List of export/import kinds. +enum class wasmer_import_export_kind : uint32_t { + /// The export/import is a function. + WASM_FUNCTION = 0, + /// The export/import is a global. + WASM_GLOBAL = 1, + /// The export/import is a memory. + WASM_MEMORY = 2, + /// The export/import is a table. + WASM_TABLE = 3, +}; + +/// The `wasmer_result_t` enum is a type that represents either a +/// success, or a failure. +enum class wasmer_result_t { + /// Represents a success. + WASMER_OK = 1, + /// Represents a failure. + WASMER_ERROR = 2, +}; + +/// Represents all possibles WebAssembly value types. +/// +/// See `wasmer_value_t` to get a complete example. +enum class wasmer_value_tag : uint32_t { + /// Represents the `i32` WebAssembly type. + WASM_I32, + /// Represents the `i64` WebAssembly type. + WASM_I64, + /// Represents the `f32` WebAssembly type. + WASM_F32, + /// Represents the `f64` WebAssembly type. + WASM_F64, +}; + +struct wasmer_module_t { + +}; + +/// Opaque pointer to a `wasmer_runtime::Instance` value in Rust. +/// +/// A `wasmer_runtime::Instance` represents a WebAssembly instance. It +/// is generally generated by the `wasmer_instantiate()` function, or by +/// the `wasmer_module_instantiate()` function for the most common paths. +struct wasmer_instance_t { + +}; + +struct wasmer_byte_array { + const uint8_t *bytes; + uint32_t bytes_len; +}; + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Type used to construct an import_object_t with Emscripten imports. +struct wasmer_emscripten_globals_t { + +}; +#endif + +struct wasmer_import_object_t { + +}; + +/// Opaque pointer to `NamedExportDescriptor`. +struct wasmer_export_descriptor_t { + +}; + +/// Opaque pointer to `NamedExportDescriptors`. +struct wasmer_export_descriptors_t { + +}; + +/// Opaque pointer to `wasmer_export_t`. +struct wasmer_export_func_t { + +}; + +/// Represents a WebAssembly value. +/// +/// This is a [Rust union][rust-union], which is equivalent to the C +/// union. See `wasmer_value_t` to get a complete example. +/// +/// [rust-union]: https://doc.rust-lang.org/reference/items/unions.html +union wasmer_value { + int32_t I32; + int64_t I64; + float F32; + double F64; +}; + +/// Represents a WebAssembly type and value pair, +/// i.e. `wasmer_value_tag` and `wasmer_value`. Since the latter is an +/// union, it's the safe way to read or write a WebAssembly value in +/// C. +/// +/// Example: +/// +/// ```c +/// // Create a WebAssembly value. +/// wasmer_value_t wasm_value = { +/// .tag = WASM_I32, +/// .value.I32 = 42, +/// }; +/// +/// // Read a WebAssembly value. +/// if (wasm_value.tag == WASM_I32) { +/// int32_t x = wasm_value.value.I32; +/// // … +/// } +/// ``` +struct wasmer_value_t { + /// The value type. + wasmer_value_tag tag; + /// The value. + wasmer_value value; +}; + +/// Opaque pointer to `NamedExport`. +struct wasmer_export_t { + +}; + +/// Opaque pointer to a `wasmer_runtime::Memory` value in Rust. +/// +/// A `wasmer_runtime::Memory` represents a WebAssembly memory. It is +/// possible to create one with `wasmer_memory_new()` and pass it as +/// imports of an instance, or to read it from exports of an instance +/// with `wasmer_export_to_memory()`. +struct wasmer_memory_t { + +}; + +/// Opaque pointer to the opaque structure `crate::NamedExports`, +/// which is a wrapper around a vector of the opaque structure +/// `crate::NamedExport`. +/// +/// Check the `wasmer_instance_exports()` function to learn more. +struct wasmer_exports_t { + +}; + +struct wasmer_global_t { + +}; + +struct wasmer_global_descriptor_t { + bool mutable_; + wasmer_value_tag kind; +}; + +struct wasmer_import_descriptor_t { + +}; + +struct wasmer_import_descriptors_t { + +}; + +struct wasmer_import_func_t { + +}; + +struct wasmer_table_t { + +}; + +/// Union of import/export value. +union wasmer_import_export_value { + const wasmer_import_func_t *func; + const wasmer_table_t *table; + const wasmer_memory_t *memory; + const wasmer_global_t *global; +}; + +struct wasmer_import_t { + wasmer_byte_array module_name; + wasmer_byte_array import_name; + wasmer_import_export_kind tag; + wasmer_import_export_value value; +}; + +struct wasmer_import_object_iter_t { + +}; + +/// Opaque pointer to a `wasmer_runtime::Ctx` value in Rust. +/// +/// An instance context is passed to any host function (aka imported +/// function) as the first argument. It is necessary to read the +/// instance data or the memory, respectively with the +/// `wasmer_instance_context_data_get()` function, and the +/// `wasmer_instance_context_memory()` function. +/// +/// It is also possible to get the instance context outside a host +/// function by using the `wasmer_instance_context_get()` +/// function. See also `wasmer_instance_context_data_set()` to set the +/// instance context data. +/// +/// Example: +/// +/// ```c +/// // A host function that prints data from the WebAssembly memory to +/// // the standard output. +/// void print(wasmer_instance_context_t *context, int32_t pointer, int32_t length) { +/// // Use `wasmer_instance_context` to get back the first instance memory. +/// const wasmer_memory_t *memory = wasmer_instance_context_memory(context, 0); +/// +/// // Continue… +/// } +/// ``` +struct wasmer_instance_context_t { + +}; + +/// The `wasmer_limit_option_t` struct represents an optional limit +/// for `wasmer_limits_t`. +struct wasmer_limit_option_t { + /// Whether the limit is set. + bool has_some; + /// The limit value. + uint32_t some; +}; + +/// The `wasmer_limits_t` struct is a type that describes a memory +/// options. See the `wasmer_memory_t` struct or the +/// `wasmer_memory_new()` function to get more information. +struct wasmer_limits_t { + /// The minimum number of allowed pages. + uint32_t min; + /// The maximum number of allowed pages. + wasmer_limit_option_t max; +}; + +struct wasmer_serialized_module_t { + +}; + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +struct wasmer_trampoline_buffer_builder_t { + +}; +#endif + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +struct wasmer_trampoline_callable_t { + +}; +#endif + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +struct wasmer_trampoline_buffer_t { + +}; +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Opens a directory that's visible to the WASI module as `alias` but +/// is backed by the host file at `host_file_path` +struct wasmer_wasi_map_dir_entry_t { + /// What the WASI module will see in its virtual root + wasmer_byte_array alias; + /// The backing file that the WASI module will interact with via the alias + wasmer_byte_array host_file_path; +}; +#endif + +extern "C" { + +/// Creates a new Module from the given wasm bytes. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_compile(wasmer_module_t **module, + uint8_t *wasm_bytes, + uint32_t wasm_bytes_len); + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Convenience function for setting up arguments and calling the Emscripten +/// main function. +/// +/// WARNING: +/// +/// Do not call this function on untrusted code when operating without +/// additional sandboxing in place. +/// Emscripten has access to many host system calls and therefore may do very +/// bad things. +wasmer_result_t wasmer_emscripten_call_main(wasmer_instance_t *instance, + const wasmer_byte_array *args, + unsigned int args_len); +#endif + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Destroy `wasmer_emscrpten_globals_t` created by +/// `wasmer_emscripten_get_emscripten_globals`. +void wasmer_emscripten_destroy_globals(wasmer_emscripten_globals_t *globals); +#endif + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Create a `wasmer_import_object_t` with Emscripten imports, use +/// `wasmer_emscripten_get_emscripten_globals` to get a +/// `wasmer_emscripten_globals_t` from a `wasmer_module_t`. +/// +/// WARNING: +/// +/// This `import_object_t` contains thin-wrappers around host system calls. +/// Do not use this to execute untrusted code without additional sandboxing. +wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscripten_globals_t *globals); +#endif + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Create a `wasmer_emscripten_globals_t` from a Wasm module. +wasmer_emscripten_globals_t *wasmer_emscripten_get_globals(const wasmer_module_t *module); +#endif + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Execute global constructors (required if the module is compiled from C++) +/// and sets up the internal environment. +/// +/// This function sets the data pointer in the same way that +/// [`wasmer_instance_context_data_set`] does. +wasmer_result_t wasmer_emscripten_set_up(wasmer_instance_t *instance, + wasmer_emscripten_globals_t *globals); +#endif + +/// Gets export descriptor kind +wasmer_import_export_kind wasmer_export_descriptor_kind(wasmer_export_descriptor_t *export_); + +/// Gets name for the export descriptor +wasmer_byte_array wasmer_export_descriptor_name(wasmer_export_descriptor_t *export_descriptor); + +/// Gets export descriptors for the given module +/// +/// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. +void wasmer_export_descriptors(const wasmer_module_t *module, + wasmer_export_descriptors_t **export_descriptors); + +/// Frees the memory for the given export descriptors +void wasmer_export_descriptors_destroy(wasmer_export_descriptors_t *export_descriptors); + +/// Gets export descriptor by index +wasmer_export_descriptor_t *wasmer_export_descriptors_get(wasmer_export_descriptors_t *export_descriptors, + int idx); + +/// Gets the length of the export descriptors +int wasmer_export_descriptors_len(wasmer_export_descriptors_t *exports); + +/// Calls a `func` with the provided parameters. +/// Results are set using the provided `results` pointer. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_call(const wasmer_export_func_t *func, + const wasmer_value_t *params, + unsigned int params_len, + wasmer_value_t *results, + unsigned int results_len); + +/// Sets the params buffer to the parameter types of the given wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_params(const wasmer_export_func_t *func, + wasmer_value_tag *params, + uint32_t params_len); + +/// Sets the result parameter to the arity of the params of the wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_params_arity(const wasmer_export_func_t *func, uint32_t *result); + +/// Sets the returns buffer to the parameter types of the given wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_returns(const wasmer_export_func_t *func, + wasmer_value_tag *returns, + uint32_t returns_len); + +/// Sets the result parameter to the arity of the returns of the wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_returns_arity(const wasmer_export_func_t *func, + uint32_t *result); + +/// Gets wasmer_export kind +wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); + +/// Gets name from wasmer_export +wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); + +/// Gets export func from export +const wasmer_export_func_t *wasmer_export_to_func(const wasmer_export_t *export_); + +/// Gets a memory pointer from an export pointer. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_to_memory(const wasmer_export_t *export_, wasmer_memory_t **memory); + +/// Frees the memory for the given exports. +/// +/// Check the `wasmer_instance_exports()` function to get a complete +/// example. +/// +/// If `exports` is a null pointer, this function does nothing. +/// +/// Example: +/// +/// ```c +/// // Get some exports. +/// wasmer_exports_t *exports = NULL; +/// wasmer_instance_exports(instance, &exports); +/// +/// // Destroy the exports. +/// wasmer_exports_destroy(exports); +/// ``` +void wasmer_exports_destroy(wasmer_exports_t *exports); + +/// Gets wasmer_export by index +wasmer_export_t *wasmer_exports_get(wasmer_exports_t *exports, int idx); + +/// Gets the length of the exports +int wasmer_exports_len(wasmer_exports_t *exports); + +/// Frees memory for the given Global +void wasmer_global_destroy(wasmer_global_t *global); + +/// Gets the value stored by the given Global +wasmer_value_t wasmer_global_get(wasmer_global_t *global); + +/// Returns a descriptor (type, mutability) of the given Global +wasmer_global_descriptor_t wasmer_global_get_descriptor(wasmer_global_t *global); + +/// Creates a new Global and returns a pointer to it. +/// The caller owns the object and should call `wasmer_global_destroy` to free it. +wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); + +/// Sets the value stored by the given Global +void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); + +/// Gets export descriptor kind +wasmer_import_export_kind wasmer_import_descriptor_kind(wasmer_import_descriptor_t *export_); + +/// Gets module name for the import descriptor +wasmer_byte_array wasmer_import_descriptor_module_name(wasmer_import_descriptor_t *import_descriptor); + +/// Gets name for the import descriptor +wasmer_byte_array wasmer_import_descriptor_name(wasmer_import_descriptor_t *import_descriptor); + +/// Gets import descriptors for the given module +/// +/// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. +void wasmer_import_descriptors(const wasmer_module_t *module, + wasmer_import_descriptors_t **import_descriptors); + +/// Frees the memory for the given import descriptors +void wasmer_import_descriptors_destroy(wasmer_import_descriptors_t *import_descriptors); + +/// Gets import descriptor by index +wasmer_import_descriptor_t *wasmer_import_descriptors_get(wasmer_import_descriptors_t *import_descriptors, + unsigned int idx); + +/// Gets the length of the import descriptors +unsigned int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports); + +/// Frees memory for the given Func +void wasmer_import_func_destroy(wasmer_import_func_t *func); + +/// Creates new host function, aka imported function. `func` is a +/// function pointer, where the first argument is the famous `vm::Ctx` +/// (in Rust), or `wasmer_instance_context_t` (in C). All arguments +/// must be typed with compatible WebAssembly native types: +/// +/// | WebAssembly type | C/C++ type | +/// | ---------------- | ---------- | +/// | `i32` | `int32_t` | +/// | `i64` | `int64_t` | +/// | `f32` | `float` | +/// | `f64` | `double` | +/// +/// The function pointer must have a lifetime greater than the +/// WebAssembly instance lifetime. +/// +/// The caller owns the object and should call +/// `wasmer_import_func_destroy` to free it. +wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), + const wasmer_value_tag *params, + unsigned int params_len, + const wasmer_value_tag *returns, + unsigned int returns_len); + +/// Sets the params buffer to the parameter types of the given wasmer_import_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_import_func_params(const wasmer_import_func_t *func, + wasmer_value_tag *params, + unsigned int params_len); + +/// Sets the result parameter to the arity of the params of the wasmer_import_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_import_func_params_arity(const wasmer_import_func_t *func, uint32_t *result); + +/// Sets the returns buffer to the parameter types of the given wasmer_import_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_import_func_returns(const wasmer_import_func_t *func, + wasmer_value_tag *returns, + unsigned int returns_len); + +/// Sets the result parameter to the arity of the returns of the wasmer_import_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *func, + uint32_t *result); + +/// Frees memory of the given ImportObject +void wasmer_import_object_destroy(wasmer_import_object_t *import_object); + +/// Extends an existing import object with new imports +wasmer_result_t wasmer_import_object_extend(wasmer_import_object_t *import_object, + const wasmer_import_t *imports, + unsigned int imports_len); + +/// Gets an entry from an ImportObject at the name and namespace. +/// Stores `name`, `namespace`, and `import_export_value` in `import`. +/// Thus these must remain valid for the lifetime of `import`. +/// +/// The caller owns all data involved. +/// `import_export_value` will be written to based on `tag`. +wasmer_result_t wasmer_import_object_get_import(const wasmer_import_object_t *import_object, + wasmer_byte_array namespace_, + wasmer_byte_array name, + wasmer_import_t *import, + wasmer_import_export_value *import_export_value, + uint32_t tag); + +/// Frees the memory allocated in `wasmer_import_object_iter_next` +/// +/// This function does not free the memory in `wasmer_import_object_t`; +/// it only frees memory allocated while querying a `wasmer_import_object_t`. +void wasmer_import_object_imports_destroy(wasmer_import_t *imports, uint32_t imports_len); + +/// Returns true if further calls to `wasmer_import_object_iter_next` will +/// not return any new data +bool wasmer_import_object_iter_at_end(wasmer_import_object_iter_t *import_object_iter); + +/// Frees the memory allocated by `wasmer_import_object_iterate_functions` +void wasmer_import_object_iter_destroy(wasmer_import_object_iter_t *import_object_iter); + +/// Writes the next value to `import`. `WASMER_ERROR` is returned if there +/// was an error or there's nothing left to return. +/// +/// To free the memory allocated here, pass the import to `wasmer_import_object_imports_destroy`. +/// To check if the iterator is done, use `wasmer_import_object_iter_at_end`. +wasmer_result_t wasmer_import_object_iter_next(wasmer_import_object_iter_t *import_object_iter, + wasmer_import_t *import); + +/// Create an iterator over the functions in the import object. +/// Get the next import with `wasmer_import_object_iter_next` +/// Free the iterator with `wasmer_import_object_iter_destroy` +wasmer_import_object_iter_t *wasmer_import_object_iterate_functions(const wasmer_import_object_t *import_object); + +/// Creates a new empty import object. +/// See also `wasmer_import_object_append` +wasmer_import_object_t *wasmer_import_object_new(); + +/// Calls an exported function of a WebAssembly instance by `name` +/// with the provided parameters. The exported function results are +/// stored on the provided `results` pointer. +/// +/// This function returns `wasmer_result_t::WASMER_OK` upon success, +/// `wasmer_result_t::WASMER_ERROR` otherwise. You can use +/// `wasmer_last_error_message()` to get the generated error message. +/// +/// Potential errors are the following: +/// +/// * `instance` is a null pointer, +/// * `name` is a null pointer, +/// * `params` is a null pointer. +/// +/// Example of calling an exported function that needs two parameters, and returns one value: +/// +/// ```c +/// // First argument. +/// wasmer_value_t argument_one = { +/// .tag = WASM_I32, +/// .value.I32 = 3, +/// }; +/// +/// // Second argument. +/// wasmer_value_t argument_two = { +/// .tag = WASM_I32, +/// .value.I32 = 4, +/// }; +/// +/// // First result. +/// wasmer_value_t result_one; +/// +/// // All arguments and results. +/// wasmer_value_t arguments[] = {argument_one, argument_two}; +/// wasmer_value_t results[] = {result_one}; +/// +/// wasmer_result_t call_result = wasmer_instance_call( +/// instance, // instance pointer +/// "sum", // the exported function name +/// arguments, // the arguments +/// 2, // the number of arguments +/// results, // the results +/// 1 // the number of results +/// ); +/// +/// if (call_result == WASMER_OK) { +/// printf("Result is: %d\n", results[0].value.I32); +/// } +/// ``` +wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, + const char *name, + const wasmer_value_t *params, + uint32_t params_len, + wasmer_value_t *results, + uint32_t results_len); + +/// Gets the data that can be hold by an instance. +/// +/// This function is complementary of +/// `wasmer_instance_context_data_set()`. Please read its +/// documentation. You can also read the documentation of +/// `wasmer_instance_context_t` to get other examples. +/// +/// This function returns nothing if `ctx` is a null pointer. +void *wasmer_instance_context_data_get(const wasmer_instance_context_t *ctx); + +/// Sets the data that can be hold by an instance context. +/// +/// An instance context (represented by the opaque +/// `wasmer_instance_context_t` structure) can hold user-defined +/// data. This function sets the data. This function is complementary +/// of `wasmer_instance_context_data_get()`. +/// +/// This function does nothing if `instance` is a null pointer. +/// +/// Example: +/// +/// ```c +/// // Define your own data. +/// typedef struct { +/// // … +/// } my_data; +/// +/// // Allocate them and set them on the given instance. +/// my_data *data = malloc(sizeof(my_data)); +/// data->… = …; +/// wasmer_instance_context_data_set(instance, (void*) data); +/// +/// // You can read your data. +/// { +/// my_data *data = (my_data*) wasmer_instance_context_data_get(wasmer_instance_context_get(instance)); +/// // … +/// } +/// ``` +void wasmer_instance_context_data_set(wasmer_instance_t *instance, + void *data_ptr); + +/// Returns the instance context. Learn more by looking at the +/// `wasmer_instance_context_t` struct. +/// +/// This function returns `null` if `instance` is a null pointer. +/// +/// Example: +/// +/// ```c +/// const wasmer_instance_context_get *context = wasmer_instance_context_get(instance); +/// my_data *data = (my_data *) wasmer_instance_context_data_get(context); +/// // Do something with `my_data`. +/// ``` +/// +/// It is often useful with `wasmer_instance_context_data_set()`. +const wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance); + +/// Gets the `memory_idx`th memory of the instance. +/// +/// Note that the index is always `0` until multiple memories are supported. +/// +/// This function is mostly used inside host functions (aka imported +/// functions) to read the instance memory. +/// +/// Example of a _host function_ that reads and prints a string based on a pointer and a length: +/// +/// ```c +/// void print_string(const wasmer_instance_context_t *context, int32_t pointer, int32_t length) { +/// // Get the 0th memory. +/// const wasmer_memory_t *memory = wasmer_instance_context_memory(context, 0); +/// +/// // Get the memory data as a pointer. +/// uint8_t *memory_bytes = wasmer_memory_data(memory); +/// +/// // Print what we assumed to be a string! +/// printf("%.*s", length, memory_bytes + pointer); +/// } +/// ``` +const wasmer_memory_t *wasmer_instance_context_memory(const wasmer_instance_context_t *ctx, + uint32_t _memory_idx); + +/// Frees memory for the given `wasmer_instance_t`. +/// +/// Check the `wasmer_instantiate()` function to get a complete +/// example. +/// +/// If `instance` is a null pointer, this function does nothing. +/// +/// Example: +/// +/// ```c +/// // Get an instance. +/// wasmer_instance_t *instance = NULL; +/// wasmer_instantiate(&instance, bytes, bytes_length, imports, 0); +/// +/// // Destroy the instance. +/// wasmer_instance_destroy(instance); +/// ``` +void wasmer_instance_destroy(wasmer_instance_t *instance); + +/// Gets all the exports of the given WebAssembly instance. +/// +/// This function stores a Rust vector of exports into `exports` as an +/// opaque pointer of kind `wasmer_exports_t`. +/// +/// As is, you can do anything with `exports` except using the +/// companion functions, like `wasmer_exports_len()`, +/// `wasmer_exports_get()` or `wasmer_export_kind()`. See the example below. +/// +/// **Warning**: The caller owns the object and should call +/// `wasmer_exports_destroy()` to free it. +/// +/// Example: +/// +/// ```c +/// // Get the exports. +/// wasmer_exports_t *exports = NULL; +/// wasmer_instance_exports(instance, &exports); +/// +/// // Get the number of exports. +/// int exports_length = wasmer_exports_len(exports); +/// printf("Number of exports: %d\n", exports_length); +/// +/// // Read the first export. +/// wasmer_export_t *export = wasmer_exports_get(exports, 0); +/// +/// // Get the kind of the export. +/// wasmer_import_export_kind export_kind = wasmer_export_kind(export); +/// +/// // Assert it is a function (why not). +/// assert(export_kind == WASM_FUNCTION); +/// +/// // Read the export name. +/// wasmer_byte_array name_bytes = wasmer_export_name(export); +/// +/// assert(name_bytes.bytes_len == sizeof("sum") - 1); +/// assert(memcmp(name_bytes.bytes, "sum", sizeof("sum") - 1) == 0); +/// +/// // Destroy the exports. +/// wasmer_exports_destroy(exports); +/// ``` +void wasmer_instance_exports(wasmer_instance_t *instance, wasmer_exports_t **exports); + +/// Creates a new WebAssembly instance from the given bytes and imports. +/// +/// The result is stored in the first argument `instance` if +/// successful, i.e. when the function returns +/// `wasmer_result_t::WASMER_OK`. Otherwise +/// `wasmer_result_t::WASMER_ERROR` is returned, and +/// `wasmer_last_error_length()` with `wasmer_last_error_message()` must +/// be used to read the error message. +/// +/// The caller is responsible to free the instance with +/// `wasmer_instance_destroy()`. +/// +/// Example: +/// +/// ```c +/// // 1. Read a WebAssembly module from a file. +/// FILE *file = fopen("sum.wasm", "r"); +/// fseek(file, 0, SEEK_END); +/// long bytes_length = ftell(file); +/// uint8_t *bytes = malloc(bytes_length); +/// fseek(file, 0, SEEK_SET); +/// fread(bytes, 1, bytes_length, file); +/// fclose(file); +/// +/// // 2. Declare the imports (here, none). +/// wasmer_import_t imports[] = {}; +/// +/// // 3. Instantiate the WebAssembly module. +/// wasmer_instance_t *instance = NULL; +/// wasmer_result_t result = wasmer_instantiate(&instance, bytes, bytes_length, imports, 0); +/// +/// // 4. Check for errors. +/// if (result != WASMER_OK) { +/// int error_length = wasmer_last_error_length(); +/// char *error = malloc(error_length); +/// wasmer_last_error_message(error, error_length); +/// // Do something with `error`… +/// } +/// +/// // 5. Free the memory! +/// wasmer_instance_destroy(instance); +/// ``` +wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, + uint8_t *wasm_bytes, + uint32_t wasm_bytes_len, + wasmer_import_t *imports, + int imports_len); + +/// Gets the length in bytes of the last error if any. +/// +/// This can be used to dynamically allocate a buffer with the correct number of +/// bytes needed to store a message. +/// +/// See `wasmer_last_error_message()` to get a full example. +int wasmer_last_error_length(); + +/// Gets the last error message if any into the provided buffer +/// `buffer` up to the given `length`. +/// +/// The `length` parameter must be large enough to store the last +/// error message. Ideally, the value should come from +/// `wasmer_last_error_length()`. +/// +/// The function returns the length of the string in bytes, `-1` if an +/// error occurs. Potential errors are: +/// +/// * The buffer is a null pointer, +/// * The buffer is too smal to hold the error message. +/// +/// Note: The error message always has a trailing null character. +/// +/// Example: +/// +/// ```c +/// int error_length = wasmer_last_error_length(); +/// +/// if (error_length > 0) { +/// char *error_message = malloc(error_length); +/// wasmer_last_error_message(error_message, error_length); +/// printf("Error message: `%s`\n", error_message); +/// } else { +/// printf("No error message\n"); +/// } +/// ``` +int wasmer_last_error_message(char *buffer, int length); + +/// Gets a pointer to the beginning of the contiguous memory data +/// bytes. +/// +/// The function returns `NULL` if `memory` is a null pointer. +/// +/// Note that when the memory grows, it can be reallocated, and thus +/// the returned pointer can be invalidated. +/// +/// Example: +/// +/// ```c +/// uint8_t *memory_data = wasmer_memory_data(memory); +/// char *str = (char*) malloc(sizeof(char) * 7); +/// +/// for (uint32_t nth = 0; nth < 7; ++nth) { +/// str[nth] = (char) memory_data[nth]; +/// } +/// ``` +uint8_t *wasmer_memory_data(const wasmer_memory_t *memory); + +/// Gets the size in bytes of the memory data. +/// +/// This function returns 0 if `memory` is a null pointer. +/// +/// Example: +/// +/// ```c +/// uint32_t memory_data_length = wasmer_memory_data_length(memory); +/// ``` +uint32_t wasmer_memory_data_length(const wasmer_memory_t *memory); + +/// Frees memory for the given `wasmer_memory_t`. +/// +/// Check the `wasmer_memory_new()` function to get a complete +/// example. +/// +/// If `memory` is a null pointer, this function does nothing. +/// +/// Example: +/// +/// ```c +/// // Get a memory. +/// wasmer_memory_t *memory = NULL; +/// wasmer_result_t result = wasmer_memory_new(&memory, memory_descriptor); +/// +/// // Destroy the memory. +/// wasmer_memory_destroy(memory); +/// ``` +void wasmer_memory_destroy(wasmer_memory_t *memory); + +/// Grows a memory by the given number of pages (of 65Kb each). +/// +/// The functions return `wasmer_result_t::WASMER_OK` upon success, +/// `wasmer_result_t::WASMER_ERROR` otherwise. Use +/// `wasmer_last_error_length()` with `wasmer_last_error_message()` to +/// read the error message. +/// +/// Example: +/// +/// ```c +/// wasmer_result_t result = wasmer_memory_grow(memory, 10); +/// +/// if (result != WASMER_OK) { +/// // … +/// } +/// ``` +wasmer_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); + +/// Reads the current length (in pages) of the given memory. +/// +/// The function returns zero if `memory` is a null pointer. +/// +/// Example: +/// +/// ```c +/// uint32_t memory_length = wasmer_memory_length(memory); +/// +/// printf("Memory pages length: %d\n", memory_length); +/// ``` +uint32_t wasmer_memory_length(const wasmer_memory_t *memory); + +/// Creates a new empty WebAssembly memory for the given descriptor. +/// +/// The result is stored in the first argument `memory` if successful, +/// i.e. when the function returns +/// `wasmer_result_t::WASMER_OK`. Otherwise, +/// `wasmer_result_t::WASMER_ERROR` is returned, and +/// `wasmer_last_error_length()` with `wasmer_last_error_message()` +/// must be used to read the error message. +/// +/// The caller owns the memory and is responsible to free it with +/// `wasmer_memory_destroy()`. +/// +/// Example: +/// +/// ```c +/// // 1. The memory object. +/// wasmer_memory_t *memory = NULL; +/// +/// // 2. The memory descriptor. +/// wasmer_limits_t memory_descriptor = { +/// .min = 10, +/// .max = { +/// .has_some = true, +/// .some = 15, +/// }, +/// }; +/// +/// // 3. Initialize the memory. +/// wasmer_result_t result = wasmer_memory_new(&memory, memory_descriptor); +/// +/// if (result != WASMER_OK) { +/// int error_length = wasmer_last_error_length(); +/// char *error = malloc(error_length); +/// wasmer_last_error_message(error, error_length); +/// // Do something with `error`… +/// } +/// +/// // 4. Free the memory! +/// wasmer_memory_destroy(memory); +/// ``` +wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); + +/// Deserialize the given serialized module. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module, + const wasmer_serialized_module_t *serialized_module); + +/// Frees memory for the given Module +void wasmer_module_destroy(wasmer_module_t *module); + +/// Given: +/// * A prepared `wasmer` import-object +/// * A compiled wasmer module +/// +/// Instantiates a wasmer instance +wasmer_result_t wasmer_module_import_instantiate(wasmer_instance_t **instance, + const wasmer_module_t *module, + const wasmer_import_object_t *import_object); + +/// Creates a new Instance from the given module and imports. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module, + wasmer_instance_t **instance, + wasmer_import_t *imports, + int imports_len); + +/// Serialize the given Module. +/// +/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module, + const wasmer_module_t *module); + +/// Get bytes of the serialized module. +wasmer_byte_array wasmer_serialized_module_bytes(const wasmer_serialized_module_t *serialized_module); + +/// Frees memory for the given serialized Module. +void wasmer_serialized_module_destroy(wasmer_serialized_module_t *serialized_module); + +/// Transform a sequence of bytes into a serialized module. +/// +/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_serialized_module_from_bytes(wasmer_serialized_module_t **serialized_module, + const uint8_t *serialized_module_bytes, + uint32_t serialized_module_bytes_length); + +/// Frees memory for the given Table +void wasmer_table_destroy(wasmer_table_t *table); + +/// Grows a Table by the given number of elements. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); + +/// Returns the current length of the given Table +uint32_t wasmer_table_length(wasmer_table_t *table); + +/// Creates a new Table for the given descriptor and initializes the given +/// pointer to pointer to a pointer to the new Table. +/// +/// The caller owns the object and should call `wasmer_table_destroy` to free it. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +/// Adds a callinfo trampoline to the builder. +/// +/// Deprecated. In a future version `DynamicFunc::new` will be exposed to the C API and should be used instead of this function. +uintptr_t wasmer_trampoline_buffer_builder_add_callinfo_trampoline(wasmer_trampoline_buffer_builder_t *builder, + const wasmer_trampoline_callable_t *func, + const void *ctx, + uint32_t num_params); +#endif + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +/// Adds a context trampoline to the builder. +uintptr_t wasmer_trampoline_buffer_builder_add_context_trampoline(wasmer_trampoline_buffer_builder_t *builder, + const wasmer_trampoline_callable_t *func, + const void *ctx); +#endif + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +/// Finalizes the trampoline builder into an executable buffer. +wasmer_trampoline_buffer_t *wasmer_trampoline_buffer_builder_build(wasmer_trampoline_buffer_builder_t *builder); +#endif + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +/// Creates a new trampoline builder. +wasmer_trampoline_buffer_builder_t *wasmer_trampoline_buffer_builder_new(); +#endif + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +/// Destroys the trampoline buffer if not null. +void wasmer_trampoline_buffer_destroy(wasmer_trampoline_buffer_t *buffer); +#endif + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +/// Returns the callable pointer for the trampoline with index `idx`. +const wasmer_trampoline_callable_t *wasmer_trampoline_buffer_get_trampoline(const wasmer_trampoline_buffer_t *buffer, + uintptr_t idx); +#endif + +#if (!defined(_WIN32) && defined(ARCH_X86_64)) +/// Returns the context added by `add_context_trampoline`, from within the callee function. +void *wasmer_trampoline_get_context(); +#endif + +/// Stop the execution of a host function, aka imported function. The +/// function must be used _only_ inside a host function. +/// +/// The pointer to `wasmer_instance_context_t` is received by the host +/// function as its first argument. Just passing it to `ctx` is fine. +/// +/// The error message must have a greater lifetime than the host +/// function itself since the error is read outside the host function +/// with `wasmer_last_error_message`. +/// +/// This function returns `wasmer_result_t::WASMER_ERROR` if `ctx` or +/// `error_message` are null. +/// +/// This function never returns otherwise. +wasmer_result_t wasmer_trap(const wasmer_instance_context_t *ctx, const char *error_message); + +/// Validates a sequence of bytes hoping it represents a valid WebAssembly module. +/// +/// The function returns true if the bytes are valid, false otherwise. +/// +/// Example: +/// +/// ```c +/// bool result = wasmer_validate(bytes, bytes_length); +/// +/// if (false == result) { +/// // Do something… +/// } +/// ``` +bool wasmer_validate(const uint8_t *wasm_bytes, uint32_t wasm_bytes_len); + +#if defined(WASMER_WASI_ENABLED) +/// Convenience function that creates a WASI import object with no arguments, +/// environment variables, preopened files, or mapped directories. +/// +/// This function is the same as calling [`wasmer_wasi_generate_import_object`] with all +/// empty values. +wasmer_import_object_t *wasmer_wasi_generate_default_import_object(); +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Creates a WASI import object. +/// +/// This function treats null pointers as empty collections. +/// For example, passing null for a string in `args`, will lead to a zero +/// length argument in that position. +wasmer_import_object_t *wasmer_wasi_generate_import_object(const wasmer_byte_array *args, + unsigned int args_len, + const wasmer_byte_array *envs, + unsigned int envs_len, + const wasmer_byte_array *preopened_files, + unsigned int preopened_files_len, + const wasmer_wasi_map_dir_entry_t *mapped_dirs, + unsigned int mapped_dirs_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Creates a WASI import object for a specific version. +/// +/// This function is similar to `wasmer_wasi_generate_import_object` +/// except that the first argument describes the WASI version. +/// +/// The version is expected to be of kind `Version`. +wasmer_import_object_t *wasmer_wasi_generate_import_object_for_version(unsigned char version, + const wasmer_byte_array *args, + unsigned int args_len, + const wasmer_byte_array *envs, + unsigned int envs_len, + const wasmer_byte_array *preopened_files, + unsigned int preopened_files_len, + const wasmer_wasi_map_dir_entry_t *mapped_dirs, + unsigned int mapped_dirs_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Find the version of WASI used by the module. +/// +/// In case of error, the returned version is `Version::Unknown`. +Version wasmer_wasi_get_version(const wasmer_module_t *module); +#endif + +} // extern "C" + +#endif // WASMER_H diff --git a/third_party/wasmer/wasmer.rs b/third_party/wasmer/wasmer.rs index c4bd6e5fcca..fdcb27a1d5a 100644 --- a/third_party/wasmer/wasmer.rs +++ b/third_party/wasmer/wasmer.rs @@ -1 +1 @@ -pub extern crate wasmer_c_api; +pub extern crate wasmer_runtime_c_api; diff --git a/third_party/wasmer/wasmer_wrapper.cc b/third_party/wasmer/wasmer_wrapper.cc new file mode 100644 index 00000000000..cdfaa690e07 --- /dev/null +++ b/third_party/wasmer/wasmer_wrapper.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Wraps several functions from wasmer.hh, so that they take and return all +// structs by pointer, rather than by value. This is necessary because Dart FFI +// doesn't support passing structs by value yet (once it does, we can delete +// this wrapper). + +#include "wasmer.hh" + +extern "C" { +// Wraps wasmer_export_name. +void wasmer_export_name_ptr(wasmer_export_t* export_, + wasmer_byte_array* out_name) { + *out_name = wasmer_export_name(export_); +} + +// Wraps wasmer_export_descriptor_name. +void wasmer_export_descriptor_name_ptr( + wasmer_export_descriptor_t* export_descriptor, + wasmer_byte_array* out_name) { + *out_name = wasmer_export_descriptor_name(export_descriptor); +} + +// Wraps wasmer_import_descriptor_module_name. +void wasmer_import_descriptor_module_name_ptr( + wasmer_import_descriptor_t* import_descriptor, + wasmer_byte_array* out_name) { + *out_name = wasmer_import_descriptor_module_name(import_descriptor); +} + +// Wraps wasmer_import_descriptor_name. +void wasmer_import_descriptor_name_ptr( + wasmer_import_descriptor_t* import_descriptor, + wasmer_byte_array* out_name) { + *out_name = wasmer_import_descriptor_name(import_descriptor); +} + +// Wraps wasmer_memory_new. +wasmer_result_t wasmer_memory_new_ptr(wasmer_memory_t** memory, + wasmer_limits_t* limits) { + return wasmer_memory_new(memory, *limits); +} +}