blob: 8cff32849638b3f3d7989aaf8f3d2b3236c88021 [file] [log] [blame]
// 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 'runtime.dart';
import 'wasmer_api.dart';
import 'dart:ffi';
import 'package:ffi/ffi.dart';
/// WasmFunction is a callable function from a WasmInstance.
class WasmFunction {
String _name;
Pointer<WasmerFunc> _func;
List<int> _argTypes;
int _returnType;
Pointer<WasmerValVec> _args = calloc<WasmerValVec>();
Pointer<WasmerValVec> _results = calloc<WasmerValVec>();
WasmFunction(this._name, this._func, this._argTypes, this._returnType) {
_args.ref.length = _argTypes.length;
_args.ref.data =
_argTypes.length == 0 ? nullptr : calloc<WasmerVal>(_argTypes.length);
_results.ref.length = _returnType == WasmerValKindVoid ? 0 : 1;
_results.ref.data =
_returnType == WasmerValKindVoid ? nullptr : calloc<WasmerVal>();
for (var i = 0; i < _argTypes.length; ++i) {
_args.ref.data[i].kind = _argTypes[i];
}
}
String toString() {
return WasmRuntime.getSignatureString(_name, _argTypes, _returnType);
}
bool _fillArg(dynamic arg, int i) {
switch (_argTypes[i]) {
case WasmerValKindI32:
if (arg is! int) return false;
_args.ref.data[i].i32 = arg;
return true;
case WasmerValKindI64:
if (arg is! int) return false;
_args.ref.data[i].i64 = arg;
return true;
case WasmerValKindF32:
if (arg is! num) return false;
_args.ref.data[i].f32 = arg;
return true;
case WasmerValKindF64:
if (arg is! num) return false;
_args.ref.data[i].f64 = arg;
return true;
}
return false;
}
dynamic apply(List<dynamic> args) {
if (args.length != _argTypes.length) {
throw ArgumentError("Wrong number arguments for WASM function: $this");
}
for (var i = 0; i < args.length; ++i) {
if (!_fillArg(args[i], i)) {
throw ArgumentError("Bad argument type for WASM function: $this");
}
}
WasmRuntime().call(_func, _args, _results, toString());
if (_returnType == WasmerValKindVoid) {
return null;
}
var result = _results.ref.data[0];
assert(_returnType == result.kind);
switch (_returnType) {
case WasmerValKindI32:
return result.i32;
case WasmerValKindI64:
return result.i64;
case WasmerValKindF32:
return result.f32;
case WasmerValKindF64:
return result.f64;
}
}
dynamic noSuchMethod(Invocation invocation) {
if (invocation.memberName == #call) {
return apply(invocation.positionalArguments);
}
return super.noSuchMethod(invocation);
}
}