blob: 70feec414c7ec1f5ae5965a5e7a67fccfd253d37 [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 '../builder/module.dart';
import '../serialize/serialize.dart';
import 'ir.dart';
/// A local variable defined in a function.
class Local {
final int index;
final ValueType type;
Local(this.index, this.type);
@override
String toString() => "$index";
}
/// An (imported or defined) function.
abstract class BaseFunction with Indexable, Exportable {
@override
final FinalizableIndex finalizableIndex;
final FunctionType type;
final String? functionName;
@override
final ModuleBuilder enclosingModule;
BaseFunction(this.enclosingModule, this.finalizableIndex, this.type,
this.functionName);
@override
String get name => functionName ?? super.name;
/// Creates an export of this function in this module.
@override
Export buildExport(String name) {
return FunctionExport(name, this);
}
}
/// A function defined in a module.
class DefinedFunction extends BaseFunction implements Serializable {
final Instructions body;
/// All local variables defined in the function, including its inputs.
List<Local> get locals => body.locals;
Map<int, String> get localNames => body.localNames;
DefinedFunction(
super.enclosingModule, this.body, super.finalizableIndex, super.type,
[super.functionName]);
@override
void serialize(Serializer s) {
// Serialize locals internally first in order to compute the total size of
// the serialized data.
final localS = Serializer();
int paramCount = type.inputs.length;
int entries = 0;
for (int i = paramCount + 1; i <= locals.length; i++) {
if (i == locals.length || locals[i - 1].type != locals[i].type) entries++;
}
localS.writeUnsigned(entries);
int start = paramCount;
for (int i = paramCount + 1; i <= locals.length; i++) {
if (i == locals.length || locals[i - 1].type != locals[i].type) {
localS.writeUnsigned(i - start);
localS.write(locals[i - 1].type);
start = i;
}
}
// Bundle locals and body
localS.write(body);
s.writeUnsigned(localS.data.length);
s.sourceMapSerializer.copyMappings(localS.sourceMapSerializer, s.offset);
s.writeData(localS);
}
@override
String toString() => functionName ?? "#$finalizableIndex";
}
/// An imported function.
class ImportedFunction extends BaseFunction implements Import {
@override
final String module;
@override
final String name;
ImportedFunction(super.enclosingModule, this.module, this.name,
super.finalizableIndex, super.type,
[super.functionName]);
@override
void serialize(Serializer s) {
s.writeName(module);
s.writeName(name);
s.writeByte(0x00);
s.writeUnsigned(type.index);
}
@override
String toString() => "$module.$name";
}
class FunctionExport extends Export {
final BaseFunction function;
FunctionExport(super.name, this.function);
@override
void serialize(Serializer s) {
s.writeName(name);
s.writeByte(0x00);
s.writeUnsigned(function.index);
}
}