// 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 = { '+': 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 = { '+': 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; } }