[dart2wasm] Add support for reading wasm files to package:wasm_builder

This adds a wasm binary reader that produces an `ir.Module`.

We also make a few changes to existing code

* Represent the import section with an `ir.Imports` object (similar to
  `ir.Exports`, `ir.Functions`, ...)

* We make a bunch of data structures allocatable in uninitialized state
  (the fields being usually uninitialized `late final` fields) where the
  deserializer can create those objects and then fill in details later.

  => This comes partly due to the way wasm binaries are structured
     themselves: The "data count" section comes first so a reader knows
     how many data sections there will be, then the "code section" can
     refer to those data sections. Then afterwards the actual "data
     segment" comes that fills in the data of the section.

* We make names consistently optional: Wasm objects don't have to have
  names, so the names should be optional, so we make them `String?`. We
  also make them non-final as that's consistent with other names.

* We make the `ir.Types`, `ir.Functions`, ... objects have `operator[]`
  and the index used is the same index used e.g. in wasm instructions.

* We make static constants for section ids and custom section names.

Issue https://github.com/dart-lang/sdk/issues/60928

Change-Id: I5394d6b82cf4dc68d24cea1dee66c5b33eb2f60f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/452144
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ömer Ağacan <omersa@google.com>
This commit is contained in:
Martin Kustermann
2025-10-01 03:37:31 -07:00
committed by Commit Queue
parent 3ab6859973
commit 8322e6af37
26 changed files with 2672 additions and 135 deletions
+7 -3
View File
@@ -21,12 +21,12 @@ abstract class BaseFunction with Indexable, Exportable {
@override
final FinalizableIndex finalizableIndex;
final FunctionType type;
final String? functionName;
String? functionName;
@override
final Module enclosingModule;
BaseFunction(this.enclosingModule, this.finalizableIndex, this.type,
this.functionName);
[this.functionName]);
@override
String get name => functionName ?? super.name;
@@ -40,7 +40,7 @@ abstract class BaseFunction with Indexable, Exportable {
/// A function defined in a module.
class DefinedFunction extends BaseFunction implements Serializable {
final Instructions body;
late final Instructions body;
/// All local variables defined in the function, including its inputs.
List<Local> get locals => body.locals;
@@ -51,6 +51,10 @@ class DefinedFunction extends BaseFunction implements Serializable {
super.enclosingModule, this.body, super.finalizableIndex, super.type,
[super.functionName]);
DefinedFunction.withoutBody(
super.enclosingModule, super.finalizableIndex, super.type,
[super.functionName]);
@override
void serialize(Serializer s) {
// Serialize locals internally first in order to compute the total size of