Skip to content

Commit 0e84ace

Browse files
liamappelbecommit-bot@chromium.org
authored andcommitted
[wasm] Wrapper library to get import/export names
Since FFI doesn't support structs by value yet, this thin wrapper library just provides versions of the import/export name functions that return the name by pointer. Also, I've used these functions to allow looking up functions by name, and added a function that prints a module's imports and exports (which is handy for debugging). Change-Id: Iff386e0b843bd8ab3763c99d3dc445ffedb12d6a BUG: #37882 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/161765 Reviewed-by: Ryan Macnak <[email protected]> Commit-Queue: Liam Appelbe <[email protected]>
1 parent cdd1260 commit 0e84ace

File tree

8 files changed

+313
-23
lines changed

8 files changed

+313
-23
lines changed

build/rust/rust.gni

+3-3
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ template("rust_library") {
7474
} else {
7575
if (is_win) {
7676
output_file = "${invoker.lib_name}.lib"
77-
}else {
77+
} else {
7878
output_file = "lib${invoker.lib_name}.a"
7979
}
8080
}
@@ -89,15 +89,15 @@ template("rust_library") {
8989
config("${target_name}_cargo_config") {
9090
if (!shared) {
9191
libs = [ invoker.lib_name ]
92-
lib_dirs = [ out_dir ]
92+
lib_dirs = [ target_out_dir ]
9393
}
9494
}
9595

9696
# Cargo leaves the library in cargo_out_dir, which varies based on the target.
9797
# So we need to copy it to target_out_dir to make it easier for dependees to
9898
# locate the library.
9999
copy(target_name) {
100-
deps = [ ":${target_name}_cargo" ]
100+
public_deps = [ ":${target_name}_cargo" ]
101101
sources = [ "${cargo_out_dir}/${output_file}" ]
102102
outputs = [ "${target_out_dir}/${output_file}" ]
103103
}

pkg/wasm/lib/src/module.dart

+26-5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,24 @@ class WasmModule {
2222
WasmInstance instantiate(WasmImports imports) {
2323
return WasmInstance(_module, imports);
2424
}
25+
26+
/// Returns a description of all of the module's imports and exports, for
27+
/// debugging.
28+
String describe() {
29+
var description = StringBuffer();
30+
var runtime = WasmRuntime();
31+
var imports = runtime.importDescriptors(_module);
32+
for (var imp in imports) {
33+
var kind = wasmerImpExpKindName(imp.kind);
34+
description.write('import $kind: ${imp.moduleName}::${imp.name}\n');
35+
}
36+
var exports = runtime.exportDescriptors(_module);
37+
for (var exp in exports) {
38+
var kind = wasmerImpExpKindName(exp.kind);
39+
description.write('export $kind: ${exp.name}\n');
40+
}
41+
return description.toString();
42+
}
2543
}
2644

2745
/// WasmImports holds all the imports for a WasmInstance.
@@ -43,22 +61,25 @@ class WasmImports {
4361
class WasmInstance {
4462
Pointer<WasmerModule> _module;
4563
Pointer<WasmerInstance> _instance;
46-
List<WasmFunction> _functions;
64+
Map<String, WasmFunction> _functions;
4765

4866
WasmInstance(this._module, WasmImports imports) {
4967
var runtime = WasmRuntime();
5068
_instance = runtime.instantiate(_module, imports._imports, imports.length);
51-
_functions = [];
69+
_functions = {};
5270
var exps = runtime.exports(_instance);
5371
for (var e in exps) {
5472
var kind = runtime.exportKind(e);
73+
String name = runtime.exportName(e);
5574
if (kind == WasmerImpExpKindFunction) {
5675
var f = runtime.exportToFunction(e);
57-
_functions.add(
58-
WasmFunction(f, runtime.getArgTypes(f), runtime.getReturnType(f)));
76+
_functions[name] =
77+
WasmFunction(f, runtime.getArgTypes(f), runtime.getReturnType(f));
5978
}
6079
}
6180
}
6281

63-
List<dynamic> get functions => _functions;
82+
dynamic lookupFunction(String name) {
83+
return _functions[name];
84+
}
6485
}

pkg/wasm/lib/src/runtime.dart

+117-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@ import 'package:ffi/ffi.dart';
1010
import 'package:path/path.dart' as path;
1111
import 'wasmer_api.dart';
1212

13+
class WasmImportDescriptor {
14+
int kind;
15+
String moduleName;
16+
String name;
17+
WasmImportDescriptor(this.kind, this.moduleName, this.name);
18+
}
19+
20+
class WasmExportDescriptor {
21+
int kind;
22+
String name;
23+
WasmExportDescriptor(this.kind, this.name);
24+
}
25+
1326
class WasmRuntime {
1427
static WasmRuntime _inst;
1528

@@ -26,6 +39,20 @@ class WasmRuntime {
2639
WasmerExportFuncParamsArityFn _export_func_params_arity;
2740
WasmerExportFuncParamsFn _export_func_params;
2841
WasmerExportFuncCallFn _export_func_call;
42+
WasmerExportNamePtrFn _export_name_ptr;
43+
WasmerExportDescriptorsFn _export_descriptors;
44+
WasmerExportDescriptorsDestroyFn _export_descriptors_destroy;
45+
WasmerExportDescriptorsLenFn _export_descriptors_len;
46+
WasmerExportDescriptorsGetFn _export_descriptors_get;
47+
WasmerExportDescriptorKindFn _export_descriptor_kind;
48+
WasmerExportDescriptorNamePtrFn _export_descriptor_name_ptr;
49+
WasmerImportDescriptorModuleNamePtrFn _import_descriptor_module_name_ptr;
50+
WasmerImportDescriptorNamePtrFn _import_descriptor_name_ptr;
51+
WasmerImportDescriptorsFn _import_descriptors;
52+
WasmerImportDescriptorsDestroyFn _import_descriptors_destroy;
53+
WasmerImportDescriptorsLenFn _import_descriptors_len;
54+
WasmerImportDescriptorsGetFn _import_descriptors_get;
55+
WasmerImportDescriptorKindFn _import_descriptor_kind;
2956

3057
factory WasmRuntime() {
3158
if (_inst == null) {
@@ -35,8 +62,8 @@ class WasmRuntime {
3562
}
3663

3764
static String _getLibName() {
38-
if (Platform.isMacOS) return "libwasmer.dylib";
39-
if (Platform.isLinux) return "libwasmer.so";
65+
if (Platform.isMacOS) return "libwasmer_wrapper.dylib";
66+
if (Platform.isLinux) return "libwasmer_wrapper.so";
4067
throw Exception("Wasm not currently supported on this platform");
4168
}
4269

@@ -103,6 +130,47 @@ class WasmRuntime {
103130
WasmerExportFuncParamsFn>('wasmer_export_func_params');
104131
_export_func_call = _lib.lookupFunction<NativeWasmerExportFuncCallFn,
105132
WasmerExportFuncCallFn>('wasmer_export_func_call');
133+
_export_descriptors = _lib.lookupFunction<NativeWasmerExportDescriptorsFn,
134+
WasmerExportDescriptorsFn>('wasmer_export_descriptors');
135+
_export_descriptors_destroy = _lib.lookupFunction<
136+
NativeWasmerExportDescriptorsDestroyFn,
137+
WasmerExportDescriptorsDestroyFn>('wasmer_export_descriptors_destroy');
138+
_export_descriptors_len = _lib.lookupFunction<
139+
NativeWasmerExportDescriptorsLenFn,
140+
WasmerExportDescriptorsLenFn>('wasmer_export_descriptors_len');
141+
_export_descriptors_get = _lib.lookupFunction<
142+
NativeWasmerExportDescriptorsGetFn,
143+
WasmerExportDescriptorsGetFn>('wasmer_export_descriptors_get');
144+
_export_descriptor_kind = _lib.lookupFunction<
145+
NativeWasmerExportDescriptorKindFn,
146+
WasmerExportDescriptorKindFn>('wasmer_export_descriptor_kind');
147+
_export_name_ptr =
148+
_lib.lookupFunction<NativeWasmerExportNamePtrFn, WasmerExportNamePtrFn>(
149+
'wasmer_export_name_ptr');
150+
_export_descriptor_name_ptr = _lib.lookupFunction<
151+
NativeWasmerExportDescriptorNamePtrFn,
152+
WasmerExportDescriptorNamePtrFn>('wasmer_export_descriptor_name_ptr');
153+
_import_descriptors = _lib.lookupFunction<NativeWasmerImportDescriptorsFn,
154+
WasmerImportDescriptorsFn>('wasmer_import_descriptors');
155+
_import_descriptors_destroy = _lib.lookupFunction<
156+
NativeWasmerImportDescriptorsDestroyFn,
157+
WasmerImportDescriptorsDestroyFn>('wasmer_import_descriptors_destroy');
158+
_import_descriptors_len = _lib.lookupFunction<
159+
NativeWasmerImportDescriptorsLenFn,
160+
WasmerImportDescriptorsLenFn>('wasmer_import_descriptors_len');
161+
_import_descriptors_get = _lib.lookupFunction<
162+
NativeWasmerImportDescriptorsGetFn,
163+
WasmerImportDescriptorsGetFn>('wasmer_import_descriptors_get');
164+
_import_descriptor_kind = _lib.lookupFunction<
165+
NativeWasmerImportDescriptorKindFn,
166+
WasmerImportDescriptorKindFn>('wasmer_import_descriptor_kind');
167+
_import_descriptor_module_name_ptr = _lib.lookupFunction<
168+
NativeWasmerImportDescriptorModuleNamePtrFn,
169+
WasmerImportDescriptorModuleNamePtrFn>(
170+
'wasmer_import_descriptor_module_name_ptr');
171+
_import_descriptor_name_ptr = _lib.lookupFunction<
172+
NativeWasmerImportDescriptorNamePtrFn,
173+
WasmerImportDescriptorNamePtrFn>('wasmer_import_descriptor_name_ptr');
106174
}
107175

108176
Pointer<WasmerModule> compile(Uint8List data) {
@@ -125,6 +193,49 @@ class WasmRuntime {
125193
return modulePtr;
126194
}
127195

196+
String _callStringWrapperFunction(Function fn, dynamic arg) {
197+
var strPtr = allocate<WasmerByteArray>();
198+
fn(arg, strPtr);
199+
var str = strPtr.ref.string;
200+
free(strPtr);
201+
return str;
202+
}
203+
204+
List<WasmExportDescriptor> exportDescriptors(Pointer<WasmerModule> module) {
205+
var exportsPtrPtr = allocate<Pointer<WasmerExportDescriptors>>();
206+
_export_descriptors(module, exportsPtrPtr);
207+
Pointer<WasmerExportDescriptors> exportsPtr = exportsPtrPtr.value;
208+
free(exportsPtrPtr);
209+
var n = _export_descriptors_len(exportsPtr);
210+
var exps = <WasmExportDescriptor>[];
211+
for (var i = 0; i < n; ++i) {
212+
var exp = _export_descriptors_get(exportsPtr, i);
213+
exps.add(WasmExportDescriptor(_export_descriptor_kind(exp),
214+
_callStringWrapperFunction(_export_descriptor_name_ptr, exp)));
215+
}
216+
_export_descriptors_destroy(exportsPtr);
217+
return exps;
218+
}
219+
220+
List<WasmImportDescriptor> importDescriptors(Pointer<WasmerModule> module) {
221+
var importsPtrPtr = allocate<Pointer<WasmerImportDescriptors>>();
222+
_import_descriptors(module, importsPtrPtr);
223+
Pointer<WasmerImportDescriptors> importsPtr = importsPtrPtr.value;
224+
free(importsPtrPtr);
225+
226+
var n = _import_descriptors_len(importsPtr);
227+
var imps = <WasmImportDescriptor>[];
228+
for (var i = 0; i < n; ++i) {
229+
var imp = _import_descriptors_get(importsPtr, i);
230+
imps.add(WasmImportDescriptor(
231+
_import_descriptor_kind(imp),
232+
_callStringWrapperFunction(_import_descriptor_module_name_ptr, imp),
233+
_callStringWrapperFunction(_import_descriptor_name_ptr, imp)));
234+
}
235+
_import_descriptors_destroy(importsPtr);
236+
return imps;
237+
}
238+
128239
Pointer<WasmerInstance> instantiate(Pointer<WasmerModule> module,
129240
Pointer<WasmerImport> imports, int numImports) {
130241
var instancePtrPtr = allocate<Pointer<WasmerInstance>>();
@@ -157,6 +268,10 @@ class WasmRuntime {
157268
return _export_kind(export);
158269
}
159270

271+
String exportName(Pointer<WasmerExport> export) {
272+
return _callStringWrapperFunction(_export_name_ptr, export);
273+
}
274+
160275
Pointer<WasmerExportFunc> exportToFunction(Pointer<WasmerExport> export) {
161276
return _export_to_func(export);
162277
}

pkg/wasm/lib/src/wasmer_api.dart

+112-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:convert';
56
import 'dart:ffi';
67
import 'dart:typed_data';
78

@@ -24,6 +25,21 @@ const int WasmerImpExpKindGlobal = 1;
2425
const int WasmerImpExpKindMemory = 2;
2526
const int WasmerImpExpKindTable = 3;
2627

28+
String wasmerImpExpKindName(int kind) {
29+
switch (kind) {
30+
case WasmerImpExpKindFunction:
31+
return "function";
32+
case WasmerImpExpKindGlobal:
33+
return "global";
34+
case WasmerImpExpKindMemory:
35+
return "memory";
36+
case WasmerImpExpKindTable:
37+
return "table";
38+
default:
39+
return "unknown";
40+
}
41+
}
42+
2743
// wasmer_module_t
2844
class WasmerModule extends Struct {}
2945

@@ -36,9 +52,21 @@ class WasmerExports extends Struct {}
3652
// wasmer_export_t
3753
class WasmerExport extends Struct {}
3854

55+
// wasmer_export_descriptors_t
56+
class WasmerExportDescriptors extends Struct {}
57+
58+
// wasmer_export_descriptor_t
59+
class WasmerExportDescriptor extends Struct {}
60+
3961
// wasmer_export_func_t
4062
class WasmerExportFunc extends Struct {}
4163

64+
// wasmer_import_descriptors_t
65+
class WasmerImportDescriptors extends Struct {}
66+
67+
// wasmer_import_descriptor_t
68+
class WasmerImportDescriptor extends Struct {}
69+
4270
// wasmer_import_t
4371
class WasmerImport extends Struct {
4472
Pointer<Uint8> module_name;
@@ -69,6 +97,7 @@ class WasmerByteArray extends Struct {
6997
int length;
7098

7199
Uint8List get list => bytes.asTypedList(length);
100+
String get string => utf8.decode(list);
72101
}
73102

74103
// wasmer_value_t
@@ -130,10 +159,89 @@ typedef NativeWasmerExportsGetFn = Pointer<WasmerExport> Function(
130159
typedef WasmerExportsGetFn = Pointer<WasmerExport> Function(
131160
Pointer<WasmerExports>, int);
132161

133-
// wasmer_export_name
134-
typedef NativeWasmerExportNameFn = WasmerByteArray Function(
135-
Pointer<WasmerExport>);
136-
typedef WasmerExportNameFn = WasmerByteArray Function(Pointer<WasmerExport>);
162+
// wasmer_export_descriptors
163+
typedef NativeWasmerExportDescriptorsFn = Void Function(
164+
Pointer<WasmerModule>, Pointer<Pointer<WasmerExportDescriptors>>);
165+
typedef WasmerExportDescriptorsFn = void Function(
166+
Pointer<WasmerModule>, Pointer<Pointer<WasmerExportDescriptors>>);
167+
168+
// wasmer_export_descriptors_destroy
169+
typedef NativeWasmerExportDescriptorsDestroyFn = Void Function(
170+
Pointer<WasmerExportDescriptors>);
171+
typedef WasmerExportDescriptorsDestroyFn = void Function(
172+
Pointer<WasmerExportDescriptors>);
173+
174+
// wasmer_export_descriptors_len
175+
typedef NativeWasmerExportDescriptorsLenFn = Int32 Function(
176+
Pointer<WasmerExportDescriptors>);
177+
typedef WasmerExportDescriptorsLenFn = int Function(
178+
Pointer<WasmerExportDescriptors>);
179+
180+
// wasmer_export_descriptors_get
181+
typedef NativeWasmerExportDescriptorsGetFn = Pointer<WasmerExportDescriptor>
182+
Function(Pointer<WasmerExportDescriptors>, Int32);
183+
typedef WasmerExportDescriptorsGetFn = Pointer<WasmerExportDescriptor> Function(
184+
Pointer<WasmerExportDescriptors>, int);
185+
186+
// wasmer_export_descriptor_kind
187+
typedef NativeWasmerExportDescriptorKindFn = Uint32 Function(
188+
Pointer<WasmerExportDescriptor>);
189+
typedef WasmerExportDescriptorKindFn = int Function(
190+
Pointer<WasmerExportDescriptor>);
191+
192+
// wasmer_export_descriptor_name_ptr
193+
typedef NativeWasmerExportDescriptorNamePtrFn = Void Function(
194+
Pointer<WasmerExportDescriptor>, Pointer<WasmerByteArray>);
195+
typedef WasmerExportDescriptorNamePtrFn = void Function(
196+
Pointer<WasmerExportDescriptor>, Pointer<WasmerByteArray>);
197+
198+
// wasmer_import_descriptors
199+
typedef NativeWasmerImportDescriptorsFn = Void Function(
200+
Pointer<WasmerModule>, Pointer<Pointer<WasmerImportDescriptors>>);
201+
typedef WasmerImportDescriptorsFn = void Function(
202+
Pointer<WasmerModule>, Pointer<Pointer<WasmerImportDescriptors>>);
203+
204+
// wasmer_import_descriptors_destroy
205+
typedef NativeWasmerImportDescriptorsDestroyFn = Void Function(
206+
Pointer<WasmerImportDescriptors>);
207+
typedef WasmerImportDescriptorsDestroyFn = void Function(
208+
Pointer<WasmerImportDescriptors>);
209+
210+
// wasmer_import_descriptors_len
211+
typedef NativeWasmerImportDescriptorsLenFn = Int32 Function(
212+
Pointer<WasmerImportDescriptors>);
213+
typedef WasmerImportDescriptorsLenFn = int Function(
214+
Pointer<WasmerImportDescriptors>);
215+
216+
// wasmer_import_descriptors_get
217+
typedef NativeWasmerImportDescriptorsGetFn = Pointer<WasmerImportDescriptor>
218+
Function(Pointer<WasmerImportDescriptors>, Int32);
219+
typedef WasmerImportDescriptorsGetFn = Pointer<WasmerImportDescriptor> Function(
220+
Pointer<WasmerImportDescriptors>, int);
221+
222+
// wasmer_import_descriptor_kind
223+
typedef NativeWasmerImportDescriptorKindFn = Uint32 Function(
224+
Pointer<WasmerImportDescriptor>);
225+
typedef WasmerImportDescriptorKindFn = int Function(
226+
Pointer<WasmerImportDescriptor>);
227+
228+
// wasmer_import_descriptor_module_name_ptr
229+
typedef NativeWasmerImportDescriptorModuleNamePtrFn = Void Function(
230+
Pointer<WasmerImportDescriptor>, Pointer<WasmerByteArray>);
231+
typedef WasmerImportDescriptorModuleNamePtrFn = void Function(
232+
Pointer<WasmerImportDescriptor>, Pointer<WasmerByteArray>);
233+
234+
// wasmer_import_descriptor_name_ptr
235+
typedef NativeWasmerImportDescriptorNamePtrFn = Void Function(
236+
Pointer<WasmerImportDescriptor>, Pointer<WasmerByteArray>);
237+
typedef WasmerImportDescriptorNamePtrFn = void Function(
238+
Pointer<WasmerImportDescriptor>, Pointer<WasmerByteArray>);
239+
240+
// wasmer_export_name_ptr
241+
typedef NativeWasmerExportNamePtrFn = Void Function(
242+
Pointer<WasmerExport>, Pointer<WasmerByteArray>);
243+
typedef WasmerExportNamePtrFn = void Function(
244+
Pointer<WasmerExport>, Pointer<WasmerByteArray>);
137245

138246
// wasmer_export_kind
139247
typedef NativeWasmerExportKindFn = Uint32 Function(Pointer<WasmerExport>);

0 commit comments

Comments
 (0)