14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_IC_IC_BINARY_OP_H_ 174514f5e3Sopenharmony_ci#define ECMASCRIPT_IC_IC_BINARY_OP_H_ 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/ic/profile_type_info.h" 204514f5e3Sopenharmony_ci#include "ecmascript/interpreter/slow_runtime_stub.h" 214514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h" 224514f5e3Sopenharmony_ci#include "ecmascript/property_attributes.h" 234514f5e3Sopenharmony_ci#include "ecmascript/runtime_call_id.h" 244514f5e3Sopenharmony_ci 254514f5e3Sopenharmony_cinamespace panda::ecmascript { 264514f5e3Sopenharmony_cienum class BinaryType : uint8_t { 274514f5e3Sopenharmony_ci NUMBER, 284514f5e3Sopenharmony_ci NUMBER_GEN, 294514f5e3Sopenharmony_ci STRING, 304514f5e3Sopenharmony_ci STRING_GEN, 314514f5e3Sopenharmony_ci GENERIC, 324514f5e3Sopenharmony_ci}; 334514f5e3Sopenharmony_ci 344514f5e3Sopenharmony_ciclass ICBinaryOP { 354514f5e3Sopenharmony_cipublic: 364514f5e3Sopenharmony_ci static inline JSTaggedValue AddWithTSType(JSThread *thread, JSTaggedValue left, 374514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 384514f5e3Sopenharmony_ci { 394514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, AddWithTSType); 404514f5e3Sopenharmony_ci BinaryType addType = static_cast<BinaryType>(argType.GetInt()); 414514f5e3Sopenharmony_ci switch (addType) { 424514f5e3Sopenharmony_ci // Support cases, such as: int + double, int + int, double + double 434514f5e3Sopenharmony_ci case BinaryType::NUMBER: { 444514f5e3Sopenharmony_ci double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble(); 454514f5e3Sopenharmony_ci double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble(); 464514f5e3Sopenharmony_ci double ret = a0Double + a1Double; 474514f5e3Sopenharmony_ci return JSTaggedValue(ret); 484514f5e3Sopenharmony_ci } 494514f5e3Sopenharmony_ci // Support cases, such as: number + null, undefined + null, boolean + number, etc. 504514f5e3Sopenharmony_ci case BinaryType::NUMBER_GEN: { 514514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> leftValue(thread, left); 524514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> rightValue(thread, right); 534514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> primitiveA0(thread, JSTaggedValue::ToPrimitive(thread, leftValue)); 544514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 554514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> primitiveA1(thread, JSTaggedValue::ToPrimitive(thread, rightValue)); 564514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 574514f5e3Sopenharmony_ci 584514f5e3Sopenharmony_ci JSTaggedNumber taggedValueA0 = JSTaggedValue::ToNumber(thread, primitiveA0); 594514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 604514f5e3Sopenharmony_ci JSTaggedNumber taggedValueA1 = JSTaggedValue::ToNumber(thread, primitiveA1); 614514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 624514f5e3Sopenharmony_ci double a0Double = taggedValueA0.GetNumber(); 634514f5e3Sopenharmony_ci double a1Double = taggedValueA1.GetNumber(); 644514f5e3Sopenharmony_ci return JSTaggedValue(a0Double + a1Double); 654514f5e3Sopenharmony_ci } 664514f5e3Sopenharmony_ci // Support case: string + string. 674514f5e3Sopenharmony_ci case BinaryType::STRING: { 684514f5e3Sopenharmony_ci JSHandle<EcmaString> stringA0 = JSHandle<EcmaString>(JSHandle<JSTaggedValue>(thread, left)); 694514f5e3Sopenharmony_ci JSHandle<EcmaString> stringA1 = JSHandle<EcmaString>(JSHandle<JSTaggedValue>(thread, right)); 704514f5e3Sopenharmony_ci EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1); 714514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 724514f5e3Sopenharmony_ci return JSTaggedValue(ret); 734514f5e3Sopenharmony_ci } 744514f5e3Sopenharmony_ci // Support cases, such as: string + null, string + object, string + boolean, string + number, etc. 754514f5e3Sopenharmony_ci case BinaryType::STRING_GEN: { 764514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> leftValue(thread, left); 774514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> rightValue(thread, right); 784514f5e3Sopenharmony_ci if (left.IsString()) { 794514f5e3Sopenharmony_ci JSHandle<EcmaString> stringA0 = JSHandle<EcmaString>(leftValue); 804514f5e3Sopenharmony_ci JSHandle<EcmaString> stringA1 = JSTaggedValue::ToString(thread, rightValue); 814514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 824514f5e3Sopenharmony_ci EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1); 834514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 844514f5e3Sopenharmony_ci return JSTaggedValue(ret); 854514f5e3Sopenharmony_ci } else { 864514f5e3Sopenharmony_ci JSHandle<EcmaString> stringA0 = JSTaggedValue::ToString(thread, leftValue); 874514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 884514f5e3Sopenharmony_ci JSHandle<EcmaString> stringA1 = JSHandle<EcmaString>(rightValue); 894514f5e3Sopenharmony_ci EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1); 904514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 914514f5e3Sopenharmony_ci return JSTaggedValue(ret); 924514f5e3Sopenharmony_ci } 934514f5e3Sopenharmony_ci } 944514f5e3Sopenharmony_ci // Some special cases, such as: object + undefined, object + boolean, etc. 954514f5e3Sopenharmony_ci case BinaryType::GENERIC: { 964514f5e3Sopenharmony_ci JSTaggedValue res = SlowRuntimeStub::Add2(thread, left, right); 974514f5e3Sopenharmony_ci return res; 984514f5e3Sopenharmony_ci } 994514f5e3Sopenharmony_ci default: { 1004514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 1014514f5e3Sopenharmony_ci UNREACHABLE(); 1024514f5e3Sopenharmony_ci } 1034514f5e3Sopenharmony_ci } 1044514f5e3Sopenharmony_ci } 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_ci static inline JSTaggedValue SubWithTSType(JSThread *thread, JSTaggedValue left, 1074514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 1084514f5e3Sopenharmony_ci { 1094514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, SubWithTSType); 1104514f5e3Sopenharmony_ci BinaryType subType = static_cast<BinaryType>(argType.GetInt()); 1114514f5e3Sopenharmony_ci switch (subType) { 1124514f5e3Sopenharmony_ci // Support int or number 1134514f5e3Sopenharmony_ci case BinaryType::NUMBER: { 1144514f5e3Sopenharmony_ci double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble(); 1154514f5e3Sopenharmony_ci double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble(); 1164514f5e3Sopenharmony_ci double ret = a0Double - a1Double; 1174514f5e3Sopenharmony_ci return JSTaggedValue(ret); 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci // Support cases, such as: string like '2333', boolean, null 1204514f5e3Sopenharmony_ci case BinaryType::GENERIC: { 1214514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> leftValue(thread, left); 1224514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> rightValue(thread, right); 1234514f5e3Sopenharmony_ci JSTaggedNumber number0 = JSTaggedValue::ToNumber(thread, leftValue); 1244514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1254514f5e3Sopenharmony_ci JSTaggedNumber number1 = JSTaggedValue::ToNumber(thread, rightValue); 1264514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1274514f5e3Sopenharmony_ci auto ret = number0 - number1; 1284514f5e3Sopenharmony_ci return JSTaggedValue(ret); 1294514f5e3Sopenharmony_ci } 1304514f5e3Sopenharmony_ci case BinaryType::NUMBER_GEN: 1314514f5e3Sopenharmony_ci case BinaryType::STRING: 1324514f5e3Sopenharmony_ci case BinaryType::STRING_GEN: 1334514f5e3Sopenharmony_ci default: { 1344514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 1354514f5e3Sopenharmony_ci UNREACHABLE(); 1364514f5e3Sopenharmony_ci } 1374514f5e3Sopenharmony_ci } 1384514f5e3Sopenharmony_ci } 1394514f5e3Sopenharmony_ci static inline JSTaggedValue MulWithTSType(JSThread *thread, JSTaggedValue left, 1404514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 1414514f5e3Sopenharmony_ci { 1424514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, MulWithTSType); 1434514f5e3Sopenharmony_ci BinaryType mulType = static_cast<BinaryType>(argType.GetInt()); 1444514f5e3Sopenharmony_ci switch (mulType) { 1454514f5e3Sopenharmony_ci // Support int or number 1464514f5e3Sopenharmony_ci case BinaryType::NUMBER: { 1474514f5e3Sopenharmony_ci return JSTaggedValue(left.GetNumber() * right.GetNumber()); 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci // Support cases, such as: string like '2333', boolean, null 1504514f5e3Sopenharmony_ci case BinaryType::GENERIC: { 1514514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> leftValue(thread, left); 1524514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> rightValue(thread, right); 1534514f5e3Sopenharmony_ci // 6. Let lnum be ToNumber(leftValue). 1544514f5e3Sopenharmony_ci JSTaggedNumber primitiveA = JSTaggedValue::ToNumber(thread, leftValue); 1554514f5e3Sopenharmony_ci // 7. ReturnIfAbrupt(lnum). 1564514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1574514f5e3Sopenharmony_ci // 8. Let rnum be ToNumber(rightValue). 1584514f5e3Sopenharmony_ci JSTaggedNumber primitiveB = JSTaggedValue::ToNumber(thread, rightValue); 1594514f5e3Sopenharmony_ci // 9. ReturnIfAbrupt(rnum). 1604514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1614514f5e3Sopenharmony_ci // 12.6.3.1 Applying the * Operator 1624514f5e3Sopenharmony_ci return primitiveA * primitiveB; 1634514f5e3Sopenharmony_ci } 1644514f5e3Sopenharmony_ci case BinaryType::NUMBER_GEN: 1654514f5e3Sopenharmony_ci case BinaryType::STRING: 1664514f5e3Sopenharmony_ci case BinaryType::STRING_GEN: 1674514f5e3Sopenharmony_ci default: { 1684514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 1694514f5e3Sopenharmony_ci UNREACHABLE(); 1704514f5e3Sopenharmony_ci } 1714514f5e3Sopenharmony_ci } 1724514f5e3Sopenharmony_ci } 1734514f5e3Sopenharmony_ci 1744514f5e3Sopenharmony_ci static inline JSTaggedValue DivWithTSType(JSThread *thread, JSTaggedValue left, 1754514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 1764514f5e3Sopenharmony_ci { 1774514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, DivWithTSType); 1784514f5e3Sopenharmony_ci BinaryType divType = static_cast<BinaryType>(argType.GetInt()); 1794514f5e3Sopenharmony_ci switch (divType) { 1804514f5e3Sopenharmony_ci // Support int or number 1814514f5e3Sopenharmony_ci case BinaryType::NUMBER: { 1824514f5e3Sopenharmony_ci double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble(); 1834514f5e3Sopenharmony_ci double dRight = right.IsInt() ? right.GetInt() : right.GetDouble(); 1844514f5e3Sopenharmony_ci if (UNLIKELY(dRight == 0.0)) { 1854514f5e3Sopenharmony_ci if (dLeft == 0.0 || std::isnan(dLeft)) { 1864514f5e3Sopenharmony_ci return JSTaggedValue(base::NAN_VALUE); 1874514f5e3Sopenharmony_ci } 1884514f5e3Sopenharmony_ci uint64_t flagBit = ((base::bit_cast<uint64_t>(dLeft)) ^ (base::bit_cast<uint64_t>(dRight))) & 1894514f5e3Sopenharmony_ci base::DOUBLE_SIGN_MASK; 1904514f5e3Sopenharmony_ci return JSTaggedValue(base::bit_cast<double>( 1914514f5e3Sopenharmony_ci flagBit ^ (base::bit_cast<uint64_t>(base::POSITIVE_INFINITY)))); 1924514f5e3Sopenharmony_ci } 1934514f5e3Sopenharmony_ci return JSTaggedValue(dLeft / dRight); 1944514f5e3Sopenharmony_ci } 1954514f5e3Sopenharmony_ci // Support special cases, such as: string like '2333', boolean, null 1964514f5e3Sopenharmony_ci case BinaryType::GENERIC: { 1974514f5e3Sopenharmony_ci auto res = SlowRuntimeStub::Div2(thread, left, right); 1984514f5e3Sopenharmony_ci return res; 1994514f5e3Sopenharmony_ci } 2004514f5e3Sopenharmony_ci case BinaryType::NUMBER_GEN: 2014514f5e3Sopenharmony_ci case BinaryType::STRING: 2024514f5e3Sopenharmony_ci case BinaryType::STRING_GEN: 2034514f5e3Sopenharmony_ci default: { 2044514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 2054514f5e3Sopenharmony_ci UNREACHABLE(); 2064514f5e3Sopenharmony_ci } 2074514f5e3Sopenharmony_ci } 2084514f5e3Sopenharmony_ci } 2094514f5e3Sopenharmony_ci 2104514f5e3Sopenharmony_ci static inline JSTaggedValue ModWithTSType(JSThread *thread, JSTaggedValue left, 2114514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 2124514f5e3Sopenharmony_ci { 2134514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, ModWithTSType); 2144514f5e3Sopenharmony_ci BinaryType modType = static_cast<BinaryType>(argType.GetInt()); 2154514f5e3Sopenharmony_ci switch (modType) { 2164514f5e3Sopenharmony_ci // Support int or number 2174514f5e3Sopenharmony_ci case BinaryType::NUMBER: { 2184514f5e3Sopenharmony_ci double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble(); 2194514f5e3Sopenharmony_ci double dRight = right.IsInt() ? right.GetInt() : right.GetDouble(); 2204514f5e3Sopenharmony_ci if (dRight == 0.0 || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) { 2214514f5e3Sopenharmony_ci return JSTaggedValue(base::NAN_VALUE); 2224514f5e3Sopenharmony_ci } 2234514f5e3Sopenharmony_ci if (dLeft == 0.0 || std::isinf(dRight)) { 2244514f5e3Sopenharmony_ci return JSTaggedValue(dLeft); 2254514f5e3Sopenharmony_ci } 2264514f5e3Sopenharmony_ci return JSTaggedValue(std::fmod(dLeft, dRight)); 2274514f5e3Sopenharmony_ci } 2284514f5e3Sopenharmony_ci // Support special cases, such as: string like '2333', boolean, null 2294514f5e3Sopenharmony_ci case BinaryType::GENERIC: { 2304514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> leftValue(thread, left); 2314514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> rightValue(thread, right); 2324514f5e3Sopenharmony_ci JSTaggedNumber leftNumber = JSTaggedValue::ToNumber(thread, leftValue); 2334514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2344514f5e3Sopenharmony_ci double dLeft = leftNumber.GetNumber(); 2354514f5e3Sopenharmony_ci JSTaggedNumber rightNumber = JSTaggedValue::ToNumber(thread, rightValue); 2364514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2374514f5e3Sopenharmony_ci double dRight = rightNumber.GetNumber(); 2384514f5e3Sopenharmony_ci // 12.6.3.3 Applying the % Operator 2394514f5e3Sopenharmony_ci if ((dRight == 0.0) || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) { 2404514f5e3Sopenharmony_ci return JSTaggedValue(base::NAN_VALUE); 2414514f5e3Sopenharmony_ci } 2424514f5e3Sopenharmony_ci if ((dLeft == 0.0) || std::isinf(dRight)) { 2434514f5e3Sopenharmony_ci return JSTaggedValue(dLeft); 2444514f5e3Sopenharmony_ci } 2454514f5e3Sopenharmony_ci return JSTaggedValue(std::fmod(dLeft, dRight)); 2464514f5e3Sopenharmony_ci } 2474514f5e3Sopenharmony_ci case BinaryType::NUMBER_GEN: 2484514f5e3Sopenharmony_ci case BinaryType::STRING: 2494514f5e3Sopenharmony_ci case BinaryType::STRING_GEN: 2504514f5e3Sopenharmony_ci default: { 2514514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 2524514f5e3Sopenharmony_ci UNREACHABLE(); 2534514f5e3Sopenharmony_ci } 2544514f5e3Sopenharmony_ci } 2554514f5e3Sopenharmony_ci } 2564514f5e3Sopenharmony_ci 2574514f5e3Sopenharmony_ci static inline void GetBitOPDate(JSThread *thread, JSTaggedValue left, JSTaggedValue right, 2584514f5e3Sopenharmony_ci int32_t &opNumber0, int32_t &opNumber1, BinaryType opType) 2594514f5e3Sopenharmony_ci { 2604514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, GetBitOPDate); 2614514f5e3Sopenharmony_ci switch (opType) { 2624514f5e3Sopenharmony_ci case BinaryType::NUMBER: { 2634514f5e3Sopenharmony_ci opNumber0 = 2644514f5e3Sopenharmony_ci left.IsInt() ? left.GetInt() : 2654514f5e3Sopenharmony_ci base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS); 2664514f5e3Sopenharmony_ci opNumber1 = 2674514f5e3Sopenharmony_ci right.IsInt() ? right.GetInt() : 2684514f5e3Sopenharmony_ci base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS); 2694514f5e3Sopenharmony_ci break; 2704514f5e3Sopenharmony_ci } 2714514f5e3Sopenharmony_ci // Support special cases, such as: string like '2333', boolean, null 2724514f5e3Sopenharmony_ci case BinaryType::GENERIC: { 2734514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> leftValue(thread, left); 2744514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> rightValue(thread, right); 2754514f5e3Sopenharmony_ci JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, 2764514f5e3Sopenharmony_ci leftValue.GetTaggedValue()); 2774514f5e3Sopenharmony_ci JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithUint32(thread, 2784514f5e3Sopenharmony_ci rightValue.GetTaggedValue()); 2794514f5e3Sopenharmony_ci opNumber0 = taggedNumber0.GetInt(); 2804514f5e3Sopenharmony_ci opNumber1 = taggedNumber1.GetInt(); 2814514f5e3Sopenharmony_ci break; 2824514f5e3Sopenharmony_ci } 2834514f5e3Sopenharmony_ci case BinaryType::NUMBER_GEN: 2844514f5e3Sopenharmony_ci case BinaryType::STRING: 2854514f5e3Sopenharmony_ci case BinaryType::STRING_GEN: 2864514f5e3Sopenharmony_ci default: { 2874514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 2884514f5e3Sopenharmony_ci UNREACHABLE(); 2894514f5e3Sopenharmony_ci } 2904514f5e3Sopenharmony_ci } 2914514f5e3Sopenharmony_ci return; 2924514f5e3Sopenharmony_ci } 2934514f5e3Sopenharmony_ci 2944514f5e3Sopenharmony_ci static inline JSTaggedValue ShlWithTSType(JSThread *thread, JSTaggedValue left, 2954514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 2964514f5e3Sopenharmony_ci { 2974514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, ShlWithTSType); 2984514f5e3Sopenharmony_ci BinaryType shlType = static_cast<BinaryType>(argType.GetInt()); 2994514f5e3Sopenharmony_ci int32_t opNumber0 = 0; 3004514f5e3Sopenharmony_ci int32_t opNumber1 = 0; 3014514f5e3Sopenharmony_ci GetBitOPDate(thread, left, right, opNumber0, opNumber1, shlType); 3024514f5e3Sopenharmony_ci uint32_t shift = 3034514f5e3Sopenharmony_ci static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers) 3044514f5e3Sopenharmony_ci using unsigned_type = std::make_unsigned_t<int32_t>; 3054514f5e3Sopenharmony_ci auto ret = 3064514f5e3Sopenharmony_ci static_cast<int32_t>(static_cast<unsigned_type>(opNumber0) << shift); // NOLINT(hicpp-signed-bitwise) 3074514f5e3Sopenharmony_ci return JSTaggedValue(ret); 3084514f5e3Sopenharmony_ci } 3094514f5e3Sopenharmony_ci 3104514f5e3Sopenharmony_ci static inline JSTaggedValue ShrWithTSType(JSThread *thread, JSTaggedValue left, 3114514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 3124514f5e3Sopenharmony_ci { 3134514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, ShrWithTSType); 3144514f5e3Sopenharmony_ci BinaryType shrType = static_cast<BinaryType>(argType.GetInt()); 3154514f5e3Sopenharmony_ci int32_t opNumber0 = 0; 3164514f5e3Sopenharmony_ci int32_t opNumber1 = 0; 3174514f5e3Sopenharmony_ci GetBitOPDate(thread, left, right, opNumber0, opNumber1, shrType); 3184514f5e3Sopenharmony_ci uint32_t shift = 3194514f5e3Sopenharmony_ci static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers) 3204514f5e3Sopenharmony_ci auto ret = static_cast<int32_t>(opNumber0 >> shift); // NOLINT(hicpp-signed-bitwise) 3214514f5e3Sopenharmony_ci return JSTaggedValue(ret); 3224514f5e3Sopenharmony_ci } 3234514f5e3Sopenharmony_ci 3244514f5e3Sopenharmony_ci static inline JSTaggedValue AshrWithTSType(JSThread *thread, JSTaggedValue left, 3254514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 3264514f5e3Sopenharmony_ci { 3274514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, AshrWithTSType); 3284514f5e3Sopenharmony_ci BinaryType ashrType = static_cast<BinaryType>(argType.GetInt()); 3294514f5e3Sopenharmony_ci int32_t opNumber0 = 0; 3304514f5e3Sopenharmony_ci int32_t opNumber1 = 0; 3314514f5e3Sopenharmony_ci GetBitOPDate(thread, left, right, opNumber0, opNumber1, ashrType); 3324514f5e3Sopenharmony_ci uint32_t shift = 3334514f5e3Sopenharmony_ci static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers) 3344514f5e3Sopenharmony_ci using unsigned_type = std::make_unsigned_t<uint32_t>; 3354514f5e3Sopenharmony_ci auto ret = 3364514f5e3Sopenharmony_ci static_cast<uint32_t>(static_cast<unsigned_type>(opNumber0) >> shift); // NOLINT(hicpp-signed-bitwise) 3374514f5e3Sopenharmony_ci return JSTaggedValue(ret); 3384514f5e3Sopenharmony_ci } 3394514f5e3Sopenharmony_ci 3404514f5e3Sopenharmony_ci static inline JSTaggedValue AndWithTSType(JSThread *thread, JSTaggedValue left, 3414514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 3424514f5e3Sopenharmony_ci { 3434514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, AndWithTSType); 3444514f5e3Sopenharmony_ci BinaryType andType = static_cast<BinaryType>(argType.GetInt()); 3454514f5e3Sopenharmony_ci int32_t opNumber0 = 0; 3464514f5e3Sopenharmony_ci int32_t opNumber1 = 0; 3474514f5e3Sopenharmony_ci GetBitOPDate(thread, left, right, opNumber0, opNumber1, andType); 3484514f5e3Sopenharmony_ci // NOLINT(hicpp-signed-bitwise) 3494514f5e3Sopenharmony_ci auto ret = static_cast<uint32_t>(opNumber0) & static_cast<uint32_t>(opNumber1); 3504514f5e3Sopenharmony_ci return JSTaggedValue(ret); 3514514f5e3Sopenharmony_ci } 3524514f5e3Sopenharmony_ci 3534514f5e3Sopenharmony_ci static inline JSTaggedValue OrWithTSType(JSThread *thread, JSTaggedValue left, 3544514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 3554514f5e3Sopenharmony_ci { 3564514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, OrWithTSType); 3574514f5e3Sopenharmony_ci BinaryType orType = static_cast<BinaryType>(argType.GetInt()); 3584514f5e3Sopenharmony_ci int32_t opNumber0 = 0; 3594514f5e3Sopenharmony_ci int32_t opNumber1 = 0; 3604514f5e3Sopenharmony_ci GetBitOPDate(thread, left, right, opNumber0, opNumber1, orType); 3614514f5e3Sopenharmony_ci // NOLINT(hicpp-signed-bitwise) 3624514f5e3Sopenharmony_ci auto ret = static_cast<uint32_t>(opNumber0) | static_cast<uint32_t>(opNumber1); 3634514f5e3Sopenharmony_ci return JSTaggedValue(ret); 3644514f5e3Sopenharmony_ci } 3654514f5e3Sopenharmony_ci 3664514f5e3Sopenharmony_ci static inline JSTaggedValue XorWithTSType(JSThread *thread, JSTaggedValue left, 3674514f5e3Sopenharmony_ci JSTaggedValue right, JSTaggedValue argType) 3684514f5e3Sopenharmony_ci { 3694514f5e3Sopenharmony_ci INTERPRETER_TRACE(thread, XorWithTSType); 3704514f5e3Sopenharmony_ci BinaryType xorType = static_cast<BinaryType>(argType.GetInt()); 3714514f5e3Sopenharmony_ci int32_t opNumber0 = 0; 3724514f5e3Sopenharmony_ci int32_t opNumber1 = 0; 3734514f5e3Sopenharmony_ci GetBitOPDate(thread, left, right, opNumber0, opNumber1, xorType); 3744514f5e3Sopenharmony_ci // NOLINT(hicpp-signed-bitwise) 3754514f5e3Sopenharmony_ci auto ret = static_cast<uint32_t>(opNumber0) ^ static_cast<uint32_t>(opNumber1); 3764514f5e3Sopenharmony_ci return JSTaggedValue(ret); 3774514f5e3Sopenharmony_ci } 3784514f5e3Sopenharmony_ci}; 3794514f5e3Sopenharmony_ci} // namespace panda::ecmascript 3804514f5e3Sopenharmony_ci 3814514f5e3Sopenharmony_ci#endif // ECMASCRIPT_IC_IC_BINARY_OP_H_ 382