dart-sdk/pkg/dart2wasm/dart2wasm.md
Aske Simon Christensen 9814b569ba [dart2wasm] Remove support for not using non-nullable locals.
With the decision to support non-nullable locals in WasmGC as per
https://github.com/WebAssembly/function-references/issues/44 the
support in dart2wasm for forcing all locals to be nullable is no
longer needed.

This CL removes that support and cleans up some related nullability
issues. Specifically:

- Remove the `--local-nullability` and `--parameter-nullability`
  commandline options. These are now always enabled.
- Clean out special cases around forced nullable locals throughout the
  compiler.
- Make `thisLocal` and `preciseThisLocal` always non-nullable.
- Make `returnValueLocal` (for storing the return value of `return`
  statements inside `try` blocks with `finally`) always defaultable,
  since its initialization flow crosses control constructs.
- Make type argument parameters non-nullable.
- Make non-nullable `FutureOr` translate to a non-nullable Wasm type.
- Implement the "initialized until end of block" validation scheme
  in the Wasm instruction validator.
- Run tests with the `--experimental-wasm-nn-locals` option. This
  is likely going away soon, but for now we need it.

Change-Id: I05873dd70510af5944d86d37cb5765c7bdef73a9
Cq-Include-Trybots: luci.dart.try:dart2wasm-linux-x64-d8-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/252600
Commit-Queue: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
Reviewed-by: William Hesse <whesse@google.com>
2022-07-27 22:47:30 +00:00

3.7 KiB

Running dart2wasm

You don't need to build the Dart SDK to run dart2wasm, as long as you have a Dart SDK installed.

To compile a Dart file to Wasm, run:

dart --enable-asserts pkg/dart2wasm/bin/dart2wasm.dart options infile.dart outfile.wasm

where options include:

Option Default Description
--dart-sdk=path relative to script The location of the sdk directory inside the Dart SDK, containing the core library sources.
--platform=path none The location of the platform dill file containing the compiled core libraries.
--[no-]export-all no Export all functions; otherwise, just export main.
--[no-]import-shared-memory no Import a shared memory buffer. If this is on, --shared-memory-max-pages must also be specified.
--[no-]inlining no Inline small functions.
--[no-]lazy-constants no Instantiate constants lazily.
--[no-]name-section yes Emit Name Section with function names.
--[no-]nominal-types yes Emit nominal types.
--[no-]polymorphic-specialization no Do virtual calls by switching on the class ID instead of using call_indirect.
--[no-]print-kernel no Print IR for each function before compiling it.
--[no-]print-wasm no Print Wasm instructions of each compiled function.
--[no-]runtime-types no Use RTTs for allocations and casts.
--shared-memory-max-pages pagecount Max size of the imported memory buffer. If --shared-import-memory is specified, this must also be specified.
--[no-]string-data-segments no Use experimental array init from data segment for string constants.
--watch offset Print stack trace leading to the byte at offset offset in the .wasm output file. Can be specified multiple times.

The resulting .wasm file can be run with:

d8 --experimental-wasm-gc --experimental-wasm-nn-locals --wasm-gc-js-interop pkg/dart2wasm/bin/run_wasm.js -- outfile.wasm

Imports and exports

To import a function, declare it as a global, external function and mark it with a wasm:import pragma indicating the imported name (which must be two identifiers separated by a dot):

@pragma("wasm:import", "foo.bar")
external void fooBar(Object object);

which will call foo.bar on the host side:

var foo = {
    bar: function(object) { /* implementation here */ }
};

To export a function, mark it with a wasm:export pragma:

@pragma("wasm:export")
void foo(double x) { /* implementation here */  }

@pragma("wasm:export", "baz")
void bar(double x) { /* implementation here */  }

With the Wasm module instance in inst, these can be called as:

inst.exports.foo(1);
inst.exports.baz(2);

Types to use for interop

In the signatures of imported and exported functions, use the following types:

  • For numbers, use double.
  • For Dart objects, use the corresponding Dart type. The fields of the underlying representation can be accessed on the JS side as .$field0, .$field1 etc., but there is currently no defined way of finding the field index of a particular Dart field, so this mechanism is mainly useful for special objects with known layout.
  • For JS objects, use the WasmAnyRef type (or WasmAnyRef? as applicable) from the dart:wasm package. These can be passed around and stored as opaque values on the Dart side.