blob: dc760d806d0b2eb5805d1a4879840e6ac7b4575f [file] [log] [blame]
// Copyright (c) 2023, 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 '../serialize/serialize.dart';
import '../serialize/printer.dart';
import 'ir.dart';
/// An (imported or defined) table.
class Table with Indexable, Exportable implements Serializable {
@override
final FinalizableIndex finalizableIndex;
final RefType type;
// Mutable so that a table's size does not need to be known prior to the table
// being instantiated.
int minSize;
final int? maxSize;
@override
final Module enclosingModule;
Table(this.enclosingModule, this.finalizableIndex, this.type, this.minSize,
this.maxSize);
@override
void serialize(Serializer s) {
s.write(type);
if (maxSize == null) {
s.writeByte(0x00);
s.writeUnsigned(minSize);
} else {
s.writeByte(0x01);
s.writeUnsigned(minSize);
s.writeUnsigned(maxSize!);
}
}
/// Export a table from the module.
@override
Export buildExport(String name) => TableExport(name, this);
}
/// A table defined in a module.
class DefinedTable extends Table {
final List<BaseFunction?> elements;
DefinedTable(super.enclosingModule, this.elements, super.finalizableIndex,
super.type, super.minSize, super.maxSize);
void printTo(IrPrinter p, {bool includeElements = true}) {
// NOTE: This format differs from what V8's `wami` will print.
// It makes it easier to see the exact values of the table.
p.write('(table ');
p.writeTableReference(this, alwaysPrint: true);
String? exportName;
for (final e in enclosingModule.exports.exported) {
if (e is TableExport && e.table == this) {
exportName = e.name;
break;
}
}
if (exportName != null) {
p.write(' ');
p.writeExport(exportName);
}
p.write(' $minSize ');
p.writeValueType(type);
if (includeElements) {
if (elements.any((e) => e != null)) {
p.writeln();
p.withIndent(() {
for (int i = 0; i < elements.length; ++i) {
final function = elements[i];
if (function != null) {
p.write('(def $i ');
p.writeFunctionReference(function);
p.writeln(')');
}
}
});
}
} else {
p.write(' <...>');
}
p.write(')');
}
}
/// An imported table.
class ImportedTable extends Table implements Import {
@override
final String module;
@override
final String name;
/// Functions to be inserted via the elements section.
final Map<int, BaseFunction> setElements = {};
ImportedTable(super.enclosingModule, this.module, this.name,
super.finalizableIndex, super.type, super.minSize, super.maxSize);
@override
void serialize(Serializer s) {
s.writeName(module);
s.writeName(name);
s.writeByte(0x01);
super.serialize(s);
}
void printTo(IrPrinter p, {bool includeElements = true}) {
// NOTE: This format differs from what V8's `wami` will print.
// It makes it easier to see the exact values of the table.
p.write('(table ');
p.writeTableReference(this, alwaysPrint: true);
p.write(' ');
p.writeImport(module, name);
p.write(' $minSize ');
p.writeValueType(type);
if (includeElements) {
if (setElements.isNotEmpty) {
p.writeln();
p.withIndent(() {
setElements.forEach((int i, function) {
p.write('(set $i ');
p.writeFunctionReference(function);
p.writeln(')');
});
});
}
} else {
p.write(' <...>');
}
p.write(')');
}
}
class TableExport extends Export {
final Table table;
TableExport(super.name, this.table);
@override
void serialize(Serializer s) {
s.writeName(name);
s.writeByte(0x01);
s.writeUnsigned(table.index);
}
}