blob: e30579f21e4cd83bde4e973abce96e05d1e66c0f [file] [log] [blame] [edit]
// 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 'dart:convert';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/wolf/ir/call_descriptor.dart';
import 'package:analyzer/src/wolf/ir/ir.dart';
/// Container for a sequence of IR instructions, along with auxiliary tables
/// representing types, literal values, etc. that those instructions refer to.
///
/// See [BaseIRContainer] for additional information.
///
/// To construct a sequence of IR instructions, see [CodedIRWriter].
class CodedIRContainer extends BaseIRContainer {
final List<CallDescriptor> _callDescriptorTable;
final List<Object?> _literalTable;
final List<DartType> _typeTable;
CodedIRContainer(CodedIRWriter super.writer)
: _callDescriptorTable = writer._callDescriptorTable,
_literalTable = writer._literalTable,
_typeTable = writer._typeTable;
@override
String callDescriptorRefToString(CallDescriptorRef callDescriptor) =>
decodeCallDescriptor(callDescriptor).toString();
@override
int countParameters(TypeRef type) =>
(decodeType(type) as FunctionType).formalParameters.length;
CallDescriptor decodeCallDescriptor(CallDescriptorRef callDescriptorRef) =>
_callDescriptorTable[callDescriptorRef.index];
Object? decodeLiteral(LiteralRef literal) => _literalTable[literal.index];
DartType decodeType(TypeRef type) => _typeTable[type.index];
@override
String literalRefToString(LiteralRef value) =>
json.encode(decodeLiteral(value));
/// Applies [f] to each call descriptor in the call descriptor table, and
/// gathers the results into a list.
List<T> mapCallDescriptors<T>(T Function(CallDescriptor) f) =>
_callDescriptorTable.map(f).toList();
@override
String typeRefToString(TypeRef type) => decodeType(type).toString();
}
/// Writer of an IR instruction stream, which can encode types, literal values,
/// etc. into auxiliary tables.
///
/// See [RawIRWriter] for more information.
class CodedIRWriter extends RawIRWriter {
final _callDescriptorTable = <CallDescriptor>[];
final _callDescriptorToRef = <CallDescriptor, CallDescriptorRef>{};
final _literalTable = <Object?>[];
final _literalToRef = <Object?, LiteralRef>{};
final _typeTable = <DartType>[];
final _typeToRef = <DartType, TypeRef>{};
CallDescriptorRef encodeCallDescriptor(CallDescriptor callDescriptor) =>
// TODO(paulberry): is `putIfAbsent` the best-performing way to do this?
_callDescriptorToRef.putIfAbsent(callDescriptor, () {
var encoding = CallDescriptorRef(_callDescriptorTable.length);
_callDescriptorTable.add(callDescriptor);
return encoding;
});
LiteralRef encodeLiteral(Object? value) =>
// TODO(paulberry): is `putIfAbsent` the best-performing way to do this?
_literalToRef.putIfAbsent(value, () {
var encoding = LiteralRef(_literalTable.length);
_literalTable.add(value);
return encoding;
});
TypeRef encodeType(DartType type) =>
// TODO(paulberry): is `putIfAbsent` the best-performing way to do this?
_typeToRef.putIfAbsent(type, () {
var encoding = TypeRef(_typeTable.length);
_typeTable.add(type);
return encoding;
});
}