Files
sdk/pkg/dart2bytecode/lib/recognized_methods.dart
T
Alexander Markov 3abf78212c Bytecode compiler
Add dart2bytecode tool which takes Dart sources and produces
Dart bytecode. The tool uses common front-end (CFE) to parse Dart
source code and contains bytecode generator which translates
kernel AST to bytecode.

Change-Id: I90bd6e72c619cf0edc556da0640760b30e81091d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/378560
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
2024-08-08 18:08:58 +00:00

107 lines
2.9 KiB
Dart

// Copyright (c) 2024, 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 'package:kernel/ast.dart';
import 'package:kernel/type_environment.dart' show StaticTypeContext;
import 'dbc.dart';
import 'generics.dart' show getStaticType;
class RecognizedMethods {
static const binaryIntOps = <String, Opcode>{
'+': Opcode.kAddInt,
'-': Opcode.kSubInt,
'*': Opcode.kMulInt,
'~/': Opcode.kTruncDivInt,
'%': Opcode.kModInt,
'&': Opcode.kBitAndInt,
'|': Opcode.kBitOrInt,
'^': Opcode.kBitXorInt,
'<<': Opcode.kShlInt,
'>>': Opcode.kShrInt,
'==': Opcode.kCompareIntEq,
'>': Opcode.kCompareIntGt,
'<': Opcode.kCompareIntLt,
'>=': Opcode.kCompareIntGe,
'<=': Opcode.kCompareIntLe,
};
static const binaryDoubleOps = <String, Opcode>{
'+': Opcode.kAddDouble,
'-': Opcode.kSubDouble,
'*': Opcode.kMulDouble,
'/': Opcode.kDivDouble,
'==': Opcode.kCompareDoubleEq,
'>': Opcode.kCompareDoubleGt,
'<': Opcode.kCompareDoubleLt,
'>=': Opcode.kCompareDoubleGe,
'<=': Opcode.kCompareDoubleLe,
};
final StaticTypeContext staticTypeContext;
RecognizedMethods(this.staticTypeContext);
DartType staticType(Expression expr) =>
getStaticType(expr, staticTypeContext);
bool isInt(DartType type) =>
type == staticTypeContext.typeEnvironment.coreTypes.intNonNullableRawType;
bool isDouble(DartType type) =>
type ==
staticTypeContext.typeEnvironment.coreTypes.doubleNonNullableRawType;
Opcode? specializedBytecodeFor(InstanceInvocationExpression node) {
final args = node.arguments;
if (args.named.isNotEmpty) {
return null;
}
final Expression receiver = node.receiver;
final String selector = node.name.text;
switch (args.positional.length) {
case 0:
return specializedBytecodeForUnaryOp(selector, receiver);
case 1:
return specializedBytecodeForBinaryOp(
selector, receiver, args.positional.single);
default:
return null;
}
}
Opcode? specializedBytecodeForUnaryOp(String selector, Expression arg) {
if (selector == 'unary-') {
final argType = staticType(arg);
if (isInt(argType)) {
return Opcode.kNegateInt;
} else if (isDouble(argType)) {
return Opcode.kNegateDouble;
}
}
return null;
}
Opcode? specializedBytecodeForBinaryOp(
String selector, Expression a, Expression b) {
if (selector == '==' && (a is NullLiteral || b is NullLiteral)) {
return Opcode.kEqualsNull;
}
final aType = staticType(a);
final bType = staticType(b);
if (isInt(aType) && isInt(bType)) {
return binaryIntOps[selector];
}
if (isDouble(aType) && isDouble(bType)) {
return binaryDoubleOps[selector];
}
return null;
}
}