blob: 9acc0b25a157cafc26e5cec6e0e9be38a24caf40 [file] [log] [blame]
// Copyright (c) 2022, 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.
library dart._wasm;
import 'dart:js_interop';
// A collection a special Dart types that are mapped directly to Wasm types
// by the dart2wasm compiler. These types have a number of constraints:
//
// - They can only be used directly as types of local variables, fields, or
// parameter/return of static functions. No other uses of the types are valid.
// - They are not assignable to or from any ordinary Dart types.
// - The integer and float types can't be nullable.
// - Their instance methods cannot be called virtually or dynamically.
//
// TODO(askesc): Give an error message if any of these constraints are violated.
@pragma("wasm:entry-point")
abstract class _WasmBase {
const _WasmBase();
}
/// The Wasm `anyref` type.
@pragma("wasm:entry-point")
class WasmAnyRef extends _WasmBase {
/// Dummy constructor to silence error about missing superclass constructor.
const WasmAnyRef._();
/// Upcast Dart object to `anyref`.
external factory WasmAnyRef.fromObject(Object o);
/// Whether this reference is a Dart object.
external bool get isObject;
/// Downcast `anyref` to a Dart object.
///
/// Will throw if the reference is not a Dart object.
external Object toObject();
}
extension ExternalizeNonNullable on WasmAnyRef {
WasmExternRef externalize() => _externalizeNonNullable(this);
}
extension ExternalizeNullable on WasmAnyRef? {
WasmExternRef? externalize() => _externalizeNullable(this);
}
/// The Wasm `externref` type.
@pragma("wasm:entry-point")
class WasmExternRef extends _WasmBase {
// To avoid conflating the null externref with Dart's null, we provide a
// special getter for the null externref.
external static WasmExternRef? get nullRef;
}
extension InternalizeNonNullable on WasmExternRef {
WasmAnyRef internalize() => _internalizeNonNullable(this);
}
extension InternalizeNullable on WasmExternRef? {
bool get isNull => _wasmExternRefIsNull(this);
WasmAnyRef? internalize() => _internalizeNullable(this);
}
external WasmExternRef _externalizeNonNullable(WasmAnyRef ref);
external WasmExternRef? _externalizeNullable(WasmAnyRef? ref);
external WasmAnyRef _internalizeNonNullable(WasmExternRef ref);
external WasmAnyRef? _internalizeNullable(WasmExternRef? ref);
external bool _wasmExternRefIsNull(WasmExternRef? ref);
/// The Wasm `funcref` type.
@pragma("wasm:entry-point")
class WasmFuncRef extends _WasmBase {
/// Upcast typed function reference to `funcref`
external factory WasmFuncRef.fromWasmFunction(WasmFunction<Function> fun);
}
/// The Wasm `eqref` type.
@pragma("wasm:entry-point")
class WasmEqRef extends WasmAnyRef {
/// Dummy constructor to silence error about missing superclass constructor.
const WasmEqRef._() : super._();
/// Upcast Dart object to `eqref`.
external factory WasmEqRef.fromObject(Object o);
}
/// The Wasm `structref` type.
@pragma("wasm:entry-point")
class WasmStructRef extends WasmEqRef {
/// Upcast Dart object to `structref`.
external factory WasmStructRef.fromObject(Object o);
}
/// The Wasm `arrayref` type.
@pragma("wasm:entry-point")
class WasmArrayRef extends WasmEqRef {
/// Dummy constructor to silence error about missing superclass constructor.
const WasmArrayRef._() : super._();
/// Length of array.
external int get length;
}
/// The Wasm `i8` storage type.
@pragma("wasm:entry-point")
class WasmI8 extends _WasmBase {}
/// The Wasm `i16` storage type.
@pragma("wasm:entry-point")
class WasmI16 extends _WasmBase {}
/// The Wasm `i32` type.
@pragma("wasm:entry-point")
class WasmI32 extends _WasmBase {
/// Dummy value field to contain the value for constant instances.
final int _value;
/// Constructor for constant instances.
const WasmI32(this._value);
external factory WasmI32.fromInt(int value);
external factory WasmI32.int8FromInt(int value);
external factory WasmI32.uint8FromInt(int value);
external factory WasmI32.int16FromInt(int value);
external factory WasmI32.uint16FromInt(int value);
external factory WasmI32.fromBool(bool value);
external int toIntSigned();
external int toIntUnsigned();
external bool toBool();
}
/// The Wasm `i64` type.
@pragma("wasm:entry-point")
class WasmI64 extends _WasmBase {
/// Dummy value field to contain the value for constant instances.
final int _value;
/// Constructor for constant instances.
const WasmI64(this._value);
external factory WasmI64.fromInt(int value);
external int toInt();
/// `i64.le_u`.
external bool leU(WasmI64 other);
/// `i64.lt_u`.
external bool ltU(WasmI64 other);
}
/// The Wasm `f32` type.
@pragma("wasm:entry-point")
class WasmF32 extends _WasmBase {
/// Dummy value field to contain the value for constant instances.
final double _value;
/// Constructor for constant instances.
const WasmF32(this._value);
external factory WasmF32.fromDouble(double value);
external double toDouble();
}
/// The Wasm `f64` type.
@pragma("wasm:entry-point")
class WasmF64 extends _WasmBase {
/// Dummy value field to contain the value for constant instances.
final double _value;
/// Constructor for constant instances.
const WasmF64(this._value);
external factory WasmF64.fromDouble(double value);
external double toDouble();
/// `i64.trunc_sat_f64_s`.
external WasmI64 truncSatS();
}
/// A Wasm array.
@pragma("wasm:entry-point")
class WasmArray<T> extends WasmArrayRef {
/// Dummy value field to contain the value for constant instances.
@pragma("wasm:entry-point")
final List<Object?> _value;
external factory WasmArray(int length);
external factory WasmArray.filled(int length, T value);
const WasmArray.literal(this._value) : super._();
}
extension WasmArrayExt<T> on WasmArray<T> {
external T operator [](int index);
external void operator []=(int index, T value);
external void copy(
int offset, WasmArray<T> source, int sourceOffset, int size);
external void fill(int offset, T value, int size);
external WasmArray<T> clone();
}
extension I8ArrayExt on WasmArray<WasmI8> {
external int readSigned(int index);
external int readUnsigned(int index);
external void write(int index, int value);
}
extension I16ArrayExt on WasmArray<WasmI16> {
external int readSigned(int index);
external int readUnsigned(int index);
external void write(int index, int value);
}
extension I32ArrayExt on WasmArray<WasmI32> {
external int readSigned(int index);
external int readUnsigned(int index);
external void write(int index, int value);
}
extension I64ArrayExt on WasmArray<WasmI64> {
external int read(int index);
external void write(int index, int value);
}
extension F32ArrayExt on WasmArray<WasmF32> {
external double read(int index);
external void write(int index, double value);
}
extension F64ArrayExt on WasmArray<WasmF64> {
external double read(int index);
external void write(int index, double value);
}
/// Wasm typed function reference.
@pragma("wasm:entry-point")
class WasmFunction<F extends Function> extends WasmFuncRef {
/// Create a typed function reference referring to the given function.
///
/// The argument must directly name a static function with no optional
/// parameters and no type parameters.
external factory WasmFunction.fromFunction(F f);
/// Downcast `funcref` to a typed function reference.
///
/// Will throw if the reference is not a function with the expected signature.
external factory WasmFunction.fromFuncRef(WasmFuncRef ref);
/// Call the function referred to by this typed function reference.
@pragma("wasm:entry-point")
external F get call;
}
/// A marker type for the return type of functions and the type argument to
/// [WasmFunction] to indicate that the function type should have no outputs.
@pragma("wasm:entry-point")
class WasmVoid extends _WasmBase {}
/// A Wasm table.
@pragma("wasm:entry-point")
class WasmTable<T> extends _WasmBase {
/// Declare a table with the given size.
///
/// Must be an initializer for a static field. The [size] argument must be
/// either a constant or a reference to a `static` `final` field with a
/// constant initializer.
external WasmTable(int size);
/// Read from an entry in the table.
external T operator [](WasmI32 index);
/// Write to an entry in the table.
external void operator []=(WasmI32 index, T value);
/// The size of the table.
external WasmI32 get size;
/// Call a function stored in the table using the `call_indirect` Wasm
/// instruction. The function value returned from this method must be
/// called directly.
@pragma("wasm:entry-point")
external F callIndirect<F extends Function>(WasmI32 index);
}
extension IntToWasmInt on int {
WasmI32 toWasmI32() => WasmI32.fromInt(this);
WasmI64 toWasmI64() => WasmI64.fromInt(this);
}
extension DoubleToWasmFloat on double {
WasmF32 toWasmF32() => WasmF32.fromDouble(this);
WasmF64 toWasmF64() => WasmF64.fromDouble(this);
}
extension WasmExternRefToJSAny on WasmExternRef {
external JSAny get toJS;
}
// Note: We would make this an extension method on JSAny, but external methods
// on JS interop types are assumed to be JS interop functions, not methods that
// are patched in patch files. So instead we just use a plain function here.
external WasmExternRef? externRefForJSAny(JSAny object);