| // 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; | |
| } | |
| } |