13af6ab5fSopenharmony_ci/* 23af6ab5fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.Apache.Org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "helpers.h" 173af6ab5fSopenharmony_ci 183af6ab5fSopenharmony_ci#include <binder/scope.h> 193af6ab5fSopenharmony_ci#include <es2panda.h> 203af6ab5fSopenharmony_ci#include <ir/base/classDefinition.h> 213af6ab5fSopenharmony_ci#include <ir/base/classProperty.h> 223af6ab5fSopenharmony_ci#include <ir/base/methodDefinition.h> 233af6ab5fSopenharmony_ci#include <ir/base/property.h> 243af6ab5fSopenharmony_ci#include <ir/base/scriptFunction.h> 253af6ab5fSopenharmony_ci#include <ir/base/spreadElement.h> 263af6ab5fSopenharmony_ci#include <ir/expressions/arrayExpression.h> 273af6ab5fSopenharmony_ci#include <ir/expressions/assignmentExpression.h> 283af6ab5fSopenharmony_ci#include <ir/expressions/functionExpression.h> 293af6ab5fSopenharmony_ci#include <ir/expressions/identifier.h> 303af6ab5fSopenharmony_ci#include <ir/expressions/literals/booleanLiteral.h> 313af6ab5fSopenharmony_ci#include <ir/expressions/literals/numberLiteral.h> 323af6ab5fSopenharmony_ci#include <ir/expressions/literals/stringLiteral.h> 333af6ab5fSopenharmony_ci#include <ir/expressions/objectExpression.h> 343af6ab5fSopenharmony_ci#include <ir/expressions/unaryExpression.h> 353af6ab5fSopenharmony_ci#include <ir/statement.h> 363af6ab5fSopenharmony_ci#include <ir/statements/blockStatement.h> 373af6ab5fSopenharmony_ci#include <ir/statements/expressionStatement.h> 383af6ab5fSopenharmony_ci#include <ir/statements/variableDeclaration.h> 393af6ab5fSopenharmony_ci#include <ir/statements/variableDeclarator.h> 403af6ab5fSopenharmony_ci#include <ir/ts/tsParameterProperty.h> 413af6ab5fSopenharmony_ci#include <lexer/token/sourceLocation.h> 423af6ab5fSopenharmony_ci#include <parser/module/sourceTextModuleRecord.h> 433af6ab5fSopenharmony_ci#include <util/concurrent.h> 443af6ab5fSopenharmony_ci 453af6ab5fSopenharmony_ci#ifdef ENABLE_BYTECODE_OPT 463af6ab5fSopenharmony_ci#include <bytecode_optimizer/bytecodeopt_options.h> 473af6ab5fSopenharmony_ci#include <bytecode_optimizer/bytecode_analysis_results.h> 483af6ab5fSopenharmony_ci#include <bytecode_optimizer/optimize_bytecode.h> 493af6ab5fSopenharmony_ci#else 503af6ab5fSopenharmony_ci#include <assembly-type.h> 513af6ab5fSopenharmony_ci#include <assembly-program.h> 523af6ab5fSopenharmony_ci#include <assembly-emitter.h> 533af6ab5fSopenharmony_ci#endif 543af6ab5fSopenharmony_ci 553af6ab5fSopenharmony_ci#ifdef PANDA_TARGET_WINDOWS 563af6ab5fSopenharmony_ci#include <windows.h> 573af6ab5fSopenharmony_ci#undef ERROR 583af6ab5fSopenharmony_ci#else 593af6ab5fSopenharmony_ci#include <unistd.h> 603af6ab5fSopenharmony_ci#endif 613af6ab5fSopenharmony_ci#include <algorithm> 623af6ab5fSopenharmony_ci#include <fstream> 633af6ab5fSopenharmony_ci#include <iostream> 643af6ab5fSopenharmony_ci 653af6ab5fSopenharmony_cinamespace panda::es2panda::util { 663af6ab5fSopenharmony_ci 673af6ab5fSopenharmony_ci// Helpers 683af6ab5fSopenharmony_ci 693af6ab5fSopenharmony_cibool Helpers::IsGlobalIdentifier(const util::StringView &str) 703af6ab5fSopenharmony_ci{ 713af6ab5fSopenharmony_ci return (str.Is("NaN") || str.Is("undefined") || str.Is("Infinity")); 723af6ab5fSopenharmony_ci} 733af6ab5fSopenharmony_ci 743af6ab5fSopenharmony_cibool Helpers::ContainSpreadElement(const ArenaVector<ir::Expression *> &args) 753af6ab5fSopenharmony_ci{ 763af6ab5fSopenharmony_ci return std::any_of(args.begin(), args.end(), [](const auto *it) { return it->IsSpreadElement(); }); 773af6ab5fSopenharmony_ci} 783af6ab5fSopenharmony_ci 793af6ab5fSopenharmony_ciutil::StringView Helpers::LiteralToPropName(ArenaAllocator *allocator, const ir::Expression *lit) 803af6ab5fSopenharmony_ci{ 813af6ab5fSopenharmony_ci switch (lit->Type()) { 823af6ab5fSopenharmony_ci case ir::AstNodeType::IDENTIFIER: { 833af6ab5fSopenharmony_ci return lit->AsIdentifier()->Name(); 843af6ab5fSopenharmony_ci } 853af6ab5fSopenharmony_ci case ir::AstNodeType::STRING_LITERAL: { 863af6ab5fSopenharmony_ci return lit->AsStringLiteral()->Str(); 873af6ab5fSopenharmony_ci } 883af6ab5fSopenharmony_ci case ir::AstNodeType::NUMBER_LITERAL: { 893af6ab5fSopenharmony_ci return Helpers::ToStringView(allocator, lit->AsNumberLiteral()->Number()); 903af6ab5fSopenharmony_ci } 913af6ab5fSopenharmony_ci case ir::AstNodeType::NULL_LITERAL: { 923af6ab5fSopenharmony_ci return "null"; 933af6ab5fSopenharmony_ci } 943af6ab5fSopenharmony_ci case ir::AstNodeType::BOOLEAN_LITERAL: { 953af6ab5fSopenharmony_ci if (lit->AsBooleanLiteral()->Value()) { 963af6ab5fSopenharmony_ci return "true"; 973af6ab5fSopenharmony_ci } 983af6ab5fSopenharmony_ci return "false"; 993af6ab5fSopenharmony_ci } 1003af6ab5fSopenharmony_ci default: { 1013af6ab5fSopenharmony_ci UNREACHABLE(); 1023af6ab5fSopenharmony_ci } 1033af6ab5fSopenharmony_ci } 1043af6ab5fSopenharmony_ci} 1053af6ab5fSopenharmony_ci 1063af6ab5fSopenharmony_cibool Helpers::IsIndex(double number) 1073af6ab5fSopenharmony_ci{ 1083af6ab5fSopenharmony_ci if (number >= 0 && number < static_cast<double>(INVALID_INDEX)) { 1093af6ab5fSopenharmony_ci auto intNum = static_cast<uint32_t>(number); 1103af6ab5fSopenharmony_ci 1113af6ab5fSopenharmony_ci if (static_cast<double>(intNum) == number) { 1123af6ab5fSopenharmony_ci return true; 1133af6ab5fSopenharmony_ci } 1143af6ab5fSopenharmony_ci } 1153af6ab5fSopenharmony_ci 1163af6ab5fSopenharmony_ci return false; 1173af6ab5fSopenharmony_ci} 1183af6ab5fSopenharmony_ci 1193af6ab5fSopenharmony_cistatic bool IsDigit(char c) 1203af6ab5fSopenharmony_ci{ 1213af6ab5fSopenharmony_ci return (c >= '0' && c <= '9'); 1223af6ab5fSopenharmony_ci} 1233af6ab5fSopenharmony_ci 1243af6ab5fSopenharmony_ciint64_t Helpers::GetIndex(const util::StringView &str) 1253af6ab5fSopenharmony_ci{ 1263af6ab5fSopenharmony_ci const auto &s = str.Utf8(); 1273af6ab5fSopenharmony_ci 1283af6ab5fSopenharmony_ci if (s.empty() || (*s.begin() == '0' && s.length() > 1)) { 1293af6ab5fSopenharmony_ci return INVALID_INDEX; 1303af6ab5fSopenharmony_ci } 1313af6ab5fSopenharmony_ci 1323af6ab5fSopenharmony_ci int64_t value = 0; 1333af6ab5fSopenharmony_ci for (const auto c : s) { 1343af6ab5fSopenharmony_ci if (!IsDigit(c)) { 1353af6ab5fSopenharmony_ci return INVALID_INDEX; 1363af6ab5fSopenharmony_ci } 1373af6ab5fSopenharmony_ci 1383af6ab5fSopenharmony_ci constexpr auto MULTIPLIER = 10; 1393af6ab5fSopenharmony_ci value *= MULTIPLIER; 1403af6ab5fSopenharmony_ci value += (c - '0'); 1413af6ab5fSopenharmony_ci 1423af6ab5fSopenharmony_ci if (value >= INVALID_INDEX) { 1433af6ab5fSopenharmony_ci return INVALID_INDEX; 1443af6ab5fSopenharmony_ci } 1453af6ab5fSopenharmony_ci } 1463af6ab5fSopenharmony_ci 1473af6ab5fSopenharmony_ci return value; 1483af6ab5fSopenharmony_ci} 1493af6ab5fSopenharmony_ci 1503af6ab5fSopenharmony_cibool Helpers::FileExtensionIs(std::string_view filePath, std::string_view extension) 1513af6ab5fSopenharmony_ci{ 1523af6ab5fSopenharmony_ci return filePath.length() > extension.length() && Helpers::EndsWith(filePath, extension); 1533af6ab5fSopenharmony_ci} 1543af6ab5fSopenharmony_ci 1553af6ab5fSopenharmony_cibool Helpers::EndsWith(std::string_view str, std::string_view suffix) 1563af6ab5fSopenharmony_ci{ 1573af6ab5fSopenharmony_ci if (str.length() < suffix.length()) { 1583af6ab5fSopenharmony_ci return false; 1593af6ab5fSopenharmony_ci } 1603af6ab5fSopenharmony_ci size_t expectPos = str.length() - suffix.length(); 1613af6ab5fSopenharmony_ci return str.find(suffix, expectPos) == expectPos; 1623af6ab5fSopenharmony_ci} 1633af6ab5fSopenharmony_ci 1643af6ab5fSopenharmony_civoid Helpers::GetScientificNotationForDouble(double number, uint32_t significandBitCount, int32_t &numberBitCount, 1653af6ab5fSopenharmony_ci char *significandArray, char *sciNotationArray, uint32_t size) 1663af6ab5fSopenharmony_ci{ 1673af6ab5fSopenharmony_ci if (size < MAX_DOUBLE_DIGIT) { 1683af6ab5fSopenharmony_ci std::cerr << "Failed to set the size of buffer, the buffer size provided (" << size 1693af6ab5fSopenharmony_ci << ") is less than the required minimum size (" << MAX_DOUBLE_DIGIT 1703af6ab5fSopenharmony_ci << ") for formatting the number in scientific notation." << std::endl; 1713af6ab5fSopenharmony_ci return; 1723af6ab5fSopenharmony_ci } 1733af6ab5fSopenharmony_ci if (snprintf_s(sciNotationArray, size, size - 1, "%.*e", significandBitCount - 1, number) == FAIL_SNPRINTF_S) { 1743af6ab5fSopenharmony_ci std::cerr << "Failed to format the number " << number 1753af6ab5fSopenharmony_ci << " into scientific notation using snprintf_s. Please check if the buffer size (" << size 1763af6ab5fSopenharmony_ci << ") and significand bit count (" << significandBitCount << ") are appropriate." << std::endl; 1773af6ab5fSopenharmony_ci return; 1783af6ab5fSopenharmony_ci } 1793af6ab5fSopenharmony_ci 1803af6ab5fSopenharmony_ci // sciNotationArray includes significand, '.' and 'e' 1813af6ab5fSopenharmony_ci // If significandBitCount == 1, sciNotationArray does not contain '.' 1823af6ab5fSopenharmony_ci int32_t exponent = atoi(sciNotationArray + significandBitCount + 1 + (significandBitCount > 1)); 1833af6ab5fSopenharmony_ci numberBitCount = exponent + 1; 1843af6ab5fSopenharmony_ci 1853af6ab5fSopenharmony_ci // Get the significand of the current sciNotationArray 1863af6ab5fSopenharmony_ci if (significandBitCount > 1) { 1873af6ab5fSopenharmony_ci for (uint32_t i = 0; i < significandBitCount + 1; i++) { 1883af6ab5fSopenharmony_ci significandArray[i] = sciNotationArray[i]; 1893af6ab5fSopenharmony_ci } 1903af6ab5fSopenharmony_ci } 1913af6ab5fSopenharmony_ci 1923af6ab5fSopenharmony_ci significandArray[significandBitCount + 1] = '\0'; 1933af6ab5fSopenharmony_ci} 1943af6ab5fSopenharmony_ci 1953af6ab5fSopenharmony_ciint32_t Helpers::GetIntegerSignificandBitCount(double number, int32_t &numberBitCount, char *significandArray) 1963af6ab5fSopenharmony_ci{ 1973af6ab5fSopenharmony_ci uint32_t bitPos = 0; 1983af6ab5fSopenharmony_ci uint32_t minBitPos = 1; 1993af6ab5fSopenharmony_ci uint32_t maxBitPos = MAX_DOUBLE_PRECISION_DIGIT; 2003af6ab5fSopenharmony_ci uint32_t integerAndPointBitCount = 2; 2013af6ab5fSopenharmony_ci char sciNotationArray[MAX_DOUBLE_DIGIT] = {0}; 2023af6ab5fSopenharmony_ci 2033af6ab5fSopenharmony_ci while (minBitPos < maxBitPos) { 2043af6ab5fSopenharmony_ci bitPos = (minBitPos + maxBitPos) / 2; // 2: binary search 2053af6ab5fSopenharmony_ci GetScientificNotationForDouble(number, bitPos, numberBitCount, significandArray, 2063af6ab5fSopenharmony_ci sciNotationArray, sizeof(sciNotationArray)); 2073af6ab5fSopenharmony_ci 2083af6ab5fSopenharmony_ci // Update bitPos 2093af6ab5fSopenharmony_ci if (std::strtod(sciNotationArray, nullptr) == number) { 2103af6ab5fSopenharmony_ci while (bitPos >= integerAndPointBitCount && significandArray[bitPos] == '0') { 2113af6ab5fSopenharmony_ci bitPos--; 2123af6ab5fSopenharmony_ci } 2133af6ab5fSopenharmony_ci maxBitPos = bitPos; 2143af6ab5fSopenharmony_ci } else { 2153af6ab5fSopenharmony_ci minBitPos = bitPos + 1; 2163af6ab5fSopenharmony_ci } 2173af6ab5fSopenharmony_ci } 2183af6ab5fSopenharmony_ci 2193af6ab5fSopenharmony_ci // minBitPos == maxBitPos 2203af6ab5fSopenharmony_ci bitPos = maxBitPos; 2213af6ab5fSopenharmony_ci GetScientificNotationForDouble(number, bitPos, numberBitCount, significandArray, 2223af6ab5fSopenharmony_ci sciNotationArray, sizeof(sciNotationArray)); 2233af6ab5fSopenharmony_ci 2243af6ab5fSopenharmony_ci return bitPos; 2253af6ab5fSopenharmony_ci} 2263af6ab5fSopenharmony_ci 2273af6ab5fSopenharmony_cistd::string Helpers::DoubleToString(double number) 2283af6ab5fSopenharmony_ci{ 2293af6ab5fSopenharmony_ci // In Scientific notation, number is expressed in the form of significand multiplied by exponent-th power of 10. 2303af6ab5fSopenharmony_ci // The range of significand is: 1 <= |significand| < 10 2313af6ab5fSopenharmony_ci // Scientific notation of number: sciNotationArray = significand * (10 ** exponent) 2323af6ab5fSopenharmony_ci // number 1.23e25 => sciNotationArray: 1.23e+25, significand: 1.23, exponent: 25, 2333af6ab5fSopenharmony_ci 2343af6ab5fSopenharmony_ci // In the ECMAScript, integerSignificand, integerSignificandBitCount and numberBitCount are defined as an integer: 2353af6ab5fSopenharmony_ci // 1. integerSignificand is an integer in the Decimal representation of Scientific notation. 2363af6ab5fSopenharmony_ci // 2. integerSignificandBitCount is the number of bits in the Decimal representation of significand. 2373af6ab5fSopenharmony_ci // 3. numberBitCount is the number of bits in the Decimal representation of number. 2383af6ab5fSopenharmony_ci // Scientific notation of number in the ECMAScript of Number::toString (number): 2393af6ab5fSopenharmony_ci // integerSciNotationArray = integerSignificand * (10 ** (numberBitCount - integerSignificandBitCount)) 2403af6ab5fSopenharmony_ci // number 1.23e25 => integerSciNotationArray: 123e+23, integerSignificand: 123, integerExponent: 23, 2413af6ab5fSopenharmony_ci // integerSignificandBitCount: 3, numberBitCount: 26 2423af6ab5fSopenharmony_ci std::string result; 2433af6ab5fSopenharmony_ci int32_t numberBitCount = 0; 2443af6ab5fSopenharmony_ci char significandArray[MAX_DOUBLE_DIGIT] = {0}; 2453af6ab5fSopenharmony_ci 2463af6ab5fSopenharmony_ci if (number < 0) { 2473af6ab5fSopenharmony_ci result += "-"; 2483af6ab5fSopenharmony_ci number = -number; 2493af6ab5fSopenharmony_ci } 2503af6ab5fSopenharmony_ci 2513af6ab5fSopenharmony_ci // The number of bits of significand in integer form 2523af6ab5fSopenharmony_ci int32_t integerSignificandBitCount = GetIntegerSignificandBitCount(number, numberBitCount, significandArray); 2533af6ab5fSopenharmony_ci 2543af6ab5fSopenharmony_ci std::string significand = significandArray; 2553af6ab5fSopenharmony_ci std::string integerSignificand; 2563af6ab5fSopenharmony_ci if (numberBitCount > 0 && numberBitCount <= MAX_DECIMAL_EXPONENT) { 2573af6ab5fSopenharmony_ci integerSignificand = significand.erase(1, 1); 2583af6ab5fSopenharmony_ci if (numberBitCount >= integerSignificandBitCount) { 2593af6ab5fSopenharmony_ci // If integerSignificandBitCount ≤ numberBitCount ≤ 21, return the string represented by Decimal, 2603af6ab5fSopenharmony_ci // integerSignificand followed by (numberBitCount - integerSignificandBitCount) digit zeros. 2613af6ab5fSopenharmony_ci integerSignificand += std::string(numberBitCount - integerSignificandBitCount, '0'); 2623af6ab5fSopenharmony_ci } else { 2633af6ab5fSopenharmony_ci // If 0 < numberBitCount < integerSignificandBitCount, return the string represented by Decimal, 2643af6ab5fSopenharmony_ci // integerSignificand followed by point on the (numberBitCount + 1) digit. 2653af6ab5fSopenharmony_ci integerSignificand.insert(numberBitCount, 1, '.'); 2663af6ab5fSopenharmony_ci } 2673af6ab5fSopenharmony_ci } else if (numberBitCount <= 0 && numberBitCount > MIN_DECIMAL_EXPONENT) { 2683af6ab5fSopenharmony_ci // If -6 < numberBitCount ≤ 0, return the string consisting of "0." and digit zeros represented by Decimal, 2693af6ab5fSopenharmony_ci // string followed by integerSignificand. 2703af6ab5fSopenharmony_ci integerSignificand = significand.erase(1, 1); 2713af6ab5fSopenharmony_ci integerSignificand = std::string("0.") + std::string(-numberBitCount, '0') + integerSignificand; 2723af6ab5fSopenharmony_ci } else { 2733af6ab5fSopenharmony_ci // If integerSignificandBitCount == 1, return the string consisting of the single digit of significand. 2743af6ab5fSopenharmony_ci if (integerSignificandBitCount == 1) { 2753af6ab5fSopenharmony_ci significand = significand.erase(1, 1); 2763af6ab5fSopenharmony_ci } 2773af6ab5fSopenharmony_ci // If numberBitCount ≤ -6 or numberBitCount > 21, return the string represented by Scientific notation, 2783af6ab5fSopenharmony_ci // integerSignificand followed by "e", symbol and (numberBitCount - 1) digit zeros. 2793af6ab5fSopenharmony_ci significand += 'e' + (numberBitCount >= 1 ? std::string("+") : "") + std::to_string(numberBitCount - 1); 2803af6ab5fSopenharmony_ci 2813af6ab5fSopenharmony_ci result += significand; 2823af6ab5fSopenharmony_ci return result; 2833af6ab5fSopenharmony_ci } 2843af6ab5fSopenharmony_ci 2853af6ab5fSopenharmony_ci result += integerSignificand; 2863af6ab5fSopenharmony_ci return result; 2873af6ab5fSopenharmony_ci} 2883af6ab5fSopenharmony_ci 2893af6ab5fSopenharmony_cistd::string Helpers::ToString(double number) 2903af6ab5fSopenharmony_ci{ 2913af6ab5fSopenharmony_ci if (std::isnan(number)) { 2923af6ab5fSopenharmony_ci return "NaN"; 2933af6ab5fSopenharmony_ci } 2943af6ab5fSopenharmony_ci if (number == 0.0) { 2953af6ab5fSopenharmony_ci return "0"; 2963af6ab5fSopenharmony_ci } 2973af6ab5fSopenharmony_ci if (std::isinf(number)) { 2983af6ab5fSopenharmony_ci return "Infinity"; 2993af6ab5fSopenharmony_ci } 3003af6ab5fSopenharmony_ci 3013af6ab5fSopenharmony_ci std::string str; 3023af6ab5fSopenharmony_ci if (Helpers::IsInteger<int32_t>(number)) { 3033af6ab5fSopenharmony_ci str = std::to_string(static_cast<int32_t>(number)); 3043af6ab5fSopenharmony_ci } else { 3053af6ab5fSopenharmony_ci str = DoubleToString(number); 3063af6ab5fSopenharmony_ci } 3073af6ab5fSopenharmony_ci 3083af6ab5fSopenharmony_ci return str; 3093af6ab5fSopenharmony_ci} 3103af6ab5fSopenharmony_ci 3113af6ab5fSopenharmony_ciutil::StringView Helpers::ToStringView(ArenaAllocator *allocator, double number) 3123af6ab5fSopenharmony_ci{ 3133af6ab5fSopenharmony_ci util::UString str(ToString(number), allocator); 3143af6ab5fSopenharmony_ci return str.View(); 3153af6ab5fSopenharmony_ci} 3163af6ab5fSopenharmony_ci 3173af6ab5fSopenharmony_ciutil::StringView Helpers::ToStringView(ArenaAllocator *allocator, uint32_t number) 3183af6ab5fSopenharmony_ci{ 3193af6ab5fSopenharmony_ci ASSERT(number <= static_cast<uint32_t>(std::numeric_limits<int32_t>::max())); 3203af6ab5fSopenharmony_ci return ToStringView(allocator, static_cast<int32_t>(number)); 3213af6ab5fSopenharmony_ci} 3223af6ab5fSopenharmony_ci 3233af6ab5fSopenharmony_ciutil::StringView Helpers::ToStringView(ArenaAllocator *allocator, int32_t number) 3243af6ab5fSopenharmony_ci{ 3253af6ab5fSopenharmony_ci util::UString str(ToString(number), allocator); 3263af6ab5fSopenharmony_ci return str.View(); 3273af6ab5fSopenharmony_ci} 3283af6ab5fSopenharmony_ci 3293af6ab5fSopenharmony_ciconst ir::ScriptFunction *Helpers::GetContainingConstructor(const ir::AstNode *node) 3303af6ab5fSopenharmony_ci{ 3313af6ab5fSopenharmony_ci const ir::ScriptFunction *iter = GetContainingFunction(node); 3323af6ab5fSopenharmony_ci 3333af6ab5fSopenharmony_ci while (iter != nullptr) { 3343af6ab5fSopenharmony_ci if (iter->IsConstructor()) { 3353af6ab5fSopenharmony_ci return iter; 3363af6ab5fSopenharmony_ci } 3373af6ab5fSopenharmony_ci 3383af6ab5fSopenharmony_ci if (!iter->IsArrow()) { 3393af6ab5fSopenharmony_ci return nullptr; 3403af6ab5fSopenharmony_ci } 3413af6ab5fSopenharmony_ci 3423af6ab5fSopenharmony_ci iter = GetContainingFunction(iter); 3433af6ab5fSopenharmony_ci } 3443af6ab5fSopenharmony_ci 3453af6ab5fSopenharmony_ci return iter; 3463af6ab5fSopenharmony_ci} 3473af6ab5fSopenharmony_ci 3483af6ab5fSopenharmony_ciconst ir::ScriptFunction *Helpers::GetContainingConstructor(const ir::ClassProperty *node) 3493af6ab5fSopenharmony_ci{ 3503af6ab5fSopenharmony_ci for (const auto *parent = node->Parent(); parent != nullptr; parent = parent->Parent()) { 3513af6ab5fSopenharmony_ci if (parent->IsClassDefinition()) { 3523af6ab5fSopenharmony_ci return parent->AsClassDefinition()->Ctor()->Function(); 3533af6ab5fSopenharmony_ci } 3543af6ab5fSopenharmony_ci } 3553af6ab5fSopenharmony_ci 3563af6ab5fSopenharmony_ci return nullptr; 3573af6ab5fSopenharmony_ci} 3583af6ab5fSopenharmony_ci 3593af6ab5fSopenharmony_ciconst ir::ScriptFunction *Helpers::GetContainingFunction(const ir::AstNode *node) 3603af6ab5fSopenharmony_ci{ 3613af6ab5fSopenharmony_ci for (const auto *parent = node->Parent(); parent != nullptr; parent = parent->Parent()) { 3623af6ab5fSopenharmony_ci if (parent->IsScriptFunction()) { 3633af6ab5fSopenharmony_ci return parent->AsScriptFunction(); 3643af6ab5fSopenharmony_ci } 3653af6ab5fSopenharmony_ci } 3663af6ab5fSopenharmony_ci 3673af6ab5fSopenharmony_ci return nullptr; 3683af6ab5fSopenharmony_ci} 3693af6ab5fSopenharmony_ci 3703af6ab5fSopenharmony_ciconst ir::ClassDefinition *Helpers::GetClassDefiniton(const ir::ScriptFunction *node) 3713af6ab5fSopenharmony_ci{ 3723af6ab5fSopenharmony_ci CHECK_NOT_NULL(node); 3733af6ab5fSopenharmony_ci ASSERT(node->IsConstructor() || node->IsMethod()); 3743af6ab5fSopenharmony_ci ASSERT(node->Parent()->IsFunctionExpression()); 3753af6ab5fSopenharmony_ci ASSERT(node->Parent()->Parent()->IsMethodDefinition()); 3763af6ab5fSopenharmony_ci ASSERT(node->Parent()->Parent()->Parent()->IsClassDefinition()); 3773af6ab5fSopenharmony_ci 3783af6ab5fSopenharmony_ci return node->Parent()->Parent()->Parent()->AsClassDefinition(); 3793af6ab5fSopenharmony_ci} 3803af6ab5fSopenharmony_ci 3813af6ab5fSopenharmony_cibool Helpers::IsSpecialPropertyKey(const ir::Expression *expr) 3823af6ab5fSopenharmony_ci{ 3833af6ab5fSopenharmony_ci if (!expr->IsStringLiteral()) { 3843af6ab5fSopenharmony_ci return false; 3853af6ab5fSopenharmony_ci } 3863af6ab5fSopenharmony_ci 3873af6ab5fSopenharmony_ci auto *lit = expr->AsStringLiteral(); 3883af6ab5fSopenharmony_ci return lit->Str().Is("prototype") || lit->Str().Is("constructor"); 3893af6ab5fSopenharmony_ci} 3903af6ab5fSopenharmony_ci 3913af6ab5fSopenharmony_cibool Helpers::IsConstantPropertyKey(const ir::Expression *expr, bool isComputed) 3923af6ab5fSopenharmony_ci{ 3933af6ab5fSopenharmony_ci switch (expr->Type()) { 3943af6ab5fSopenharmony_ci case ir::AstNodeType::IDENTIFIER: { 3953af6ab5fSopenharmony_ci return !isComputed; 3963af6ab5fSopenharmony_ci } 3973af6ab5fSopenharmony_ci case ir::AstNodeType::NUMBER_LITERAL: 3983af6ab5fSopenharmony_ci case ir::AstNodeType::STRING_LITERAL: 3993af6ab5fSopenharmony_ci case ir::AstNodeType::BOOLEAN_LITERAL: 4003af6ab5fSopenharmony_ci case ir::AstNodeType::NULL_LITERAL: { 4013af6ab5fSopenharmony_ci return true; 4023af6ab5fSopenharmony_ci } 4033af6ab5fSopenharmony_ci default: 4043af6ab5fSopenharmony_ci break; 4053af6ab5fSopenharmony_ci } 4063af6ab5fSopenharmony_ci 4073af6ab5fSopenharmony_ci return false; 4083af6ab5fSopenharmony_ci} 4093af6ab5fSopenharmony_ci 4103af6ab5fSopenharmony_cibool Helpers::IsConstantExpr(const ir::Expression *expr) 4113af6ab5fSopenharmony_ci{ 4123af6ab5fSopenharmony_ci switch (expr->Type()) { 4133af6ab5fSopenharmony_ci case ir::AstNodeType::NUMBER_LITERAL: 4143af6ab5fSopenharmony_ci case ir::AstNodeType::STRING_LITERAL: 4153af6ab5fSopenharmony_ci case ir::AstNodeType::BOOLEAN_LITERAL: 4163af6ab5fSopenharmony_ci case ir::AstNodeType::NULL_LITERAL: { 4173af6ab5fSopenharmony_ci return true; 4183af6ab5fSopenharmony_ci } 4193af6ab5fSopenharmony_ci default: 4203af6ab5fSopenharmony_ci break; 4213af6ab5fSopenharmony_ci } 4223af6ab5fSopenharmony_ci 4233af6ab5fSopenharmony_ci return false; 4243af6ab5fSopenharmony_ci} 4253af6ab5fSopenharmony_ci 4263af6ab5fSopenharmony_cibool Helpers::IsBindingPattern(const ir::AstNode *node) 4273af6ab5fSopenharmony_ci{ 4283af6ab5fSopenharmony_ci return node->IsArrayPattern() || node->IsObjectPattern(); 4293af6ab5fSopenharmony_ci} 4303af6ab5fSopenharmony_ci 4313af6ab5fSopenharmony_cibool Helpers::IsPattern(const ir::AstNode *node) 4323af6ab5fSopenharmony_ci{ 4333af6ab5fSopenharmony_ci return node->IsArrayPattern() || node->IsObjectPattern() || node->IsAssignmentPattern(); 4343af6ab5fSopenharmony_ci} 4353af6ab5fSopenharmony_ci 4363af6ab5fSopenharmony_cistatic void CollectBindingName(const ir::AstNode *node, std::vector<const ir::Identifier *> *bindings) 4373af6ab5fSopenharmony_ci{ 4383af6ab5fSopenharmony_ci switch (node->Type()) { 4393af6ab5fSopenharmony_ci case ir::AstNodeType::IDENTIFIER: { 4403af6ab5fSopenharmony_ci if (!Helpers::IsGlobalIdentifier(node->AsIdentifier()->Name())) { 4413af6ab5fSopenharmony_ci bindings->push_back(node->AsIdentifier()); 4423af6ab5fSopenharmony_ci } 4433af6ab5fSopenharmony_ci 4443af6ab5fSopenharmony_ci break; 4453af6ab5fSopenharmony_ci } 4463af6ab5fSopenharmony_ci case ir::AstNodeType::OBJECT_PATTERN: { 4473af6ab5fSopenharmony_ci for (const auto *prop : node->AsObjectPattern()->Properties()) { 4483af6ab5fSopenharmony_ci CollectBindingName(prop, bindings); 4493af6ab5fSopenharmony_ci } 4503af6ab5fSopenharmony_ci break; 4513af6ab5fSopenharmony_ci } 4523af6ab5fSopenharmony_ci case ir::AstNodeType::ARRAY_PATTERN: { 4533af6ab5fSopenharmony_ci for (const auto *element : node->AsArrayPattern()->Elements()) { 4543af6ab5fSopenharmony_ci CollectBindingName(element, bindings); 4553af6ab5fSopenharmony_ci } 4563af6ab5fSopenharmony_ci break; 4573af6ab5fSopenharmony_ci } 4583af6ab5fSopenharmony_ci case ir::AstNodeType::ASSIGNMENT_PATTERN: { 4593af6ab5fSopenharmony_ci CollectBindingName(node->AsAssignmentPattern()->Left(), bindings); 4603af6ab5fSopenharmony_ci break; 4613af6ab5fSopenharmony_ci } 4623af6ab5fSopenharmony_ci case ir::AstNodeType::PROPERTY: { 4633af6ab5fSopenharmony_ci CollectBindingName(node->AsProperty()->Value(), bindings); 4643af6ab5fSopenharmony_ci break; 4653af6ab5fSopenharmony_ci } 4663af6ab5fSopenharmony_ci case ir::AstNodeType::REST_ELEMENT: { 4673af6ab5fSopenharmony_ci CollectBindingName(node->AsRestElement()->Argument(), bindings); 4683af6ab5fSopenharmony_ci break; 4693af6ab5fSopenharmony_ci } 4703af6ab5fSopenharmony_ci default: 4713af6ab5fSopenharmony_ci break; 4723af6ab5fSopenharmony_ci } 4733af6ab5fSopenharmony_ci} 4743af6ab5fSopenharmony_ci 4753af6ab5fSopenharmony_cistd::vector<const ir::Identifier *> Helpers::CollectBindingNames(const ir::AstNode *node) 4763af6ab5fSopenharmony_ci{ 4773af6ab5fSopenharmony_ci std::vector<const ir::Identifier *> bindings; 4783af6ab5fSopenharmony_ci CollectBindingName(node, &bindings); 4793af6ab5fSopenharmony_ci return bindings; 4803af6ab5fSopenharmony_ci} 4813af6ab5fSopenharmony_ci 4823af6ab5fSopenharmony_ciutil::StringView Helpers::FunctionName(ArenaAllocator *allocator, const ir::ScriptFunction *func) 4833af6ab5fSopenharmony_ci{ 4843af6ab5fSopenharmony_ci if (func->Id()) { 4853af6ab5fSopenharmony_ci return func->Id()->Name(); 4863af6ab5fSopenharmony_ci } 4873af6ab5fSopenharmony_ci 4883af6ab5fSopenharmony_ci if (func->Parent()->IsFunctionDeclaration()) { 4893af6ab5fSopenharmony_ci return parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME; 4903af6ab5fSopenharmony_ci } 4913af6ab5fSopenharmony_ci 4923af6ab5fSopenharmony_ci const ir::AstNode *parent = func->Parent()->Parent(); 4933af6ab5fSopenharmony_ci 4943af6ab5fSopenharmony_ci if (func->IsConstructor()) { 4953af6ab5fSopenharmony_ci parent = parent->Parent(); 4963af6ab5fSopenharmony_ci if (parent->AsClassDefinition()->Ident()) { 4973af6ab5fSopenharmony_ci return parent->AsClassDefinition()->Ident()->Name(); 4983af6ab5fSopenharmony_ci } 4993af6ab5fSopenharmony_ci 5003af6ab5fSopenharmony_ci parent = parent->Parent()->Parent(); 5013af6ab5fSopenharmony_ci } 5023af6ab5fSopenharmony_ci return GetName(allocator, parent); 5033af6ab5fSopenharmony_ci} 5043af6ab5fSopenharmony_ci 5053af6ab5fSopenharmony_ciutil::StringView Helpers::GetName(ArenaAllocator *allocator, const ir::AstNode *node) 5063af6ab5fSopenharmony_ci{ 5073af6ab5fSopenharmony_ci switch (node->Type()) { 5083af6ab5fSopenharmony_ci case ir::AstNodeType::VARIABLE_DECLARATOR: { 5093af6ab5fSopenharmony_ci const ir::VariableDeclarator *varDecl = node->AsVariableDeclarator(); 5103af6ab5fSopenharmony_ci 5113af6ab5fSopenharmony_ci if (varDecl->Id()->IsIdentifier()) { 5123af6ab5fSopenharmony_ci return varDecl->Id()->AsIdentifier()->Name(); 5133af6ab5fSopenharmony_ci } 5143af6ab5fSopenharmony_ci 5153af6ab5fSopenharmony_ci break; 5163af6ab5fSopenharmony_ci } 5173af6ab5fSopenharmony_ci case ir::AstNodeType::METHOD_DEFINITION: { 5183af6ab5fSopenharmony_ci const ir::MethodDefinition *methodDef = node->AsMethodDefinition(); 5193af6ab5fSopenharmony_ci 5203af6ab5fSopenharmony_ci if (methodDef->Key()->IsIdentifier()) { 5213af6ab5fSopenharmony_ci return methodDef->Key()->AsIdentifier()->Name(); 5223af6ab5fSopenharmony_ci } 5233af6ab5fSopenharmony_ci 5243af6ab5fSopenharmony_ci break; 5253af6ab5fSopenharmony_ci } 5263af6ab5fSopenharmony_ci case ir::AstNodeType::ASSIGNMENT_EXPRESSION: { 5273af6ab5fSopenharmony_ci const ir::AssignmentExpression *assignment = node->AsAssignmentExpression(); 5283af6ab5fSopenharmony_ci 5293af6ab5fSopenharmony_ci if (assignment->Left()->IsIdentifier()) { 5303af6ab5fSopenharmony_ci return assignment->Left()->AsIdentifier()->Name(); 5313af6ab5fSopenharmony_ci } 5323af6ab5fSopenharmony_ci 5333af6ab5fSopenharmony_ci break; 5343af6ab5fSopenharmony_ci } 5353af6ab5fSopenharmony_ci case ir::AstNodeType::ASSIGNMENT_PATTERN: { 5363af6ab5fSopenharmony_ci const ir::AssignmentExpression *assignment = node->AsAssignmentPattern(); 5373af6ab5fSopenharmony_ci 5383af6ab5fSopenharmony_ci if (assignment->Left()->IsIdentifier()) { 5393af6ab5fSopenharmony_ci return assignment->Left()->AsIdentifier()->Name(); 5403af6ab5fSopenharmony_ci } 5413af6ab5fSopenharmony_ci 5423af6ab5fSopenharmony_ci break; 5433af6ab5fSopenharmony_ci } 5443af6ab5fSopenharmony_ci case ir::AstNodeType::PROPERTY: { 5453af6ab5fSopenharmony_ci const ir::Property *prop = node->AsProperty(); 5463af6ab5fSopenharmony_ci 5473af6ab5fSopenharmony_ci if (prop->Kind() != ir::PropertyKind::PROTO && 5483af6ab5fSopenharmony_ci Helpers::IsConstantPropertyKey(prop->Key(), prop->IsComputed())) { 5493af6ab5fSopenharmony_ci return Helpers::LiteralToPropName(allocator, prop->Key()); 5503af6ab5fSopenharmony_ci } 5513af6ab5fSopenharmony_ci 5523af6ab5fSopenharmony_ci break; 5533af6ab5fSopenharmony_ci } 5543af6ab5fSopenharmony_ci case ir::AstNodeType::CLASS_PROPERTY: { 5553af6ab5fSopenharmony_ci const ir::ClassProperty *prop = node->AsClassProperty(); 5563af6ab5fSopenharmony_ci if (Helpers::IsConstantPropertyKey(prop->Key(), prop->IsComputed())) { 5573af6ab5fSopenharmony_ci return Helpers::LiteralToPropName(allocator, prop->Key()); 5583af6ab5fSopenharmony_ci } 5593af6ab5fSopenharmony_ci 5603af6ab5fSopenharmony_ci break; 5613af6ab5fSopenharmony_ci } 5623af6ab5fSopenharmony_ci case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION: { 5633af6ab5fSopenharmony_ci return parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME; 5643af6ab5fSopenharmony_ci } 5653af6ab5fSopenharmony_ci default: 5663af6ab5fSopenharmony_ci break; 5673af6ab5fSopenharmony_ci } 5683af6ab5fSopenharmony_ci 5693af6ab5fSopenharmony_ci return util::StringView(); 5703af6ab5fSopenharmony_ci} 5713af6ab5fSopenharmony_ci 5723af6ab5fSopenharmony_cistd::tuple<util::StringView, bool> Helpers::ParamName(ArenaAllocator *allocator, const ir::AstNode *param, 5733af6ab5fSopenharmony_ci uint32_t index) 5743af6ab5fSopenharmony_ci{ 5753af6ab5fSopenharmony_ci switch (param->Type()) { 5763af6ab5fSopenharmony_ci case ir::AstNodeType::IDENTIFIER: { 5773af6ab5fSopenharmony_ci return {param->AsIdentifier()->Name(), false}; 5783af6ab5fSopenharmony_ci } 5793af6ab5fSopenharmony_ci case ir::AstNodeType::ASSIGNMENT_PATTERN: { 5803af6ab5fSopenharmony_ci const auto *lhs = param->AsAssignmentPattern()->Left(); 5813af6ab5fSopenharmony_ci if (lhs->IsIdentifier()) { 5823af6ab5fSopenharmony_ci return {param->AsAssignmentPattern()->Left()->AsIdentifier()->Name(), false}; 5833af6ab5fSopenharmony_ci } 5843af6ab5fSopenharmony_ci break; 5853af6ab5fSopenharmony_ci } 5863af6ab5fSopenharmony_ci case ir::AstNodeType::REST_ELEMENT: { 5873af6ab5fSopenharmony_ci if (param->AsRestElement()->Argument()->IsIdentifier()) { 5883af6ab5fSopenharmony_ci return {param->AsRestElement()->Argument()->AsIdentifier()->Name(), false}; 5893af6ab5fSopenharmony_ci } 5903af6ab5fSopenharmony_ci break; 5913af6ab5fSopenharmony_ci } 5923af6ab5fSopenharmony_ci case ir::AstNodeType::TS_PARAMETER_PROPERTY: { 5933af6ab5fSopenharmony_ci return ParamName(allocator, param->AsTSParameterProperty()->Parameter(), index); 5943af6ab5fSopenharmony_ci } 5953af6ab5fSopenharmony_ci default: 5963af6ab5fSopenharmony_ci break; 5973af6ab5fSopenharmony_ci } 5983af6ab5fSopenharmony_ci 5993af6ab5fSopenharmony_ci return {Helpers::ToStringView(allocator, index), true}; 6003af6ab5fSopenharmony_ci} 6013af6ab5fSopenharmony_ci 6023af6ab5fSopenharmony_cibool Helpers::IsChild(const ir::AstNode *parent, const ir::AstNode *child) 6033af6ab5fSopenharmony_ci{ 6043af6ab5fSopenharmony_ci while (child) { 6053af6ab5fSopenharmony_ci if (child == parent) { 6063af6ab5fSopenharmony_ci return true; 6073af6ab5fSopenharmony_ci } 6083af6ab5fSopenharmony_ci 6093af6ab5fSopenharmony_ci child = child->Parent(); 6103af6ab5fSopenharmony_ci } 6113af6ab5fSopenharmony_ci 6123af6ab5fSopenharmony_ci return false; 6133af6ab5fSopenharmony_ci} 6143af6ab5fSopenharmony_ci 6153af6ab5fSopenharmony_cibool Helpers::IsChildScope(const binder::Scope *parent, const binder::Scope *child) 6163af6ab5fSopenharmony_ci{ 6173af6ab5fSopenharmony_ci while (child) { 6183af6ab5fSopenharmony_ci if (child == parent) { 6193af6ab5fSopenharmony_ci return true; 6203af6ab5fSopenharmony_ci } 6213af6ab5fSopenharmony_ci 6223af6ab5fSopenharmony_ci child = child->Parent(); 6233af6ab5fSopenharmony_ci } 6243af6ab5fSopenharmony_ci 6253af6ab5fSopenharmony_ci return false; 6263af6ab5fSopenharmony_ci} 6273af6ab5fSopenharmony_ci 6283af6ab5fSopenharmony_cibool Helpers::IsObjectPropertyValue(const ArenaVector<ir::Expression *> &properties, const ir::AstNode *ident) 6293af6ab5fSopenharmony_ci{ 6303af6ab5fSopenharmony_ci for (const auto *prop : properties) { 6313af6ab5fSopenharmony_ci ASSERT(prop->IsProperty() || prop->IsSpreadElement()); 6323af6ab5fSopenharmony_ci if (prop->IsProperty() && (prop->AsProperty()->Value() == ident)) { 6333af6ab5fSopenharmony_ci return true; 6343af6ab5fSopenharmony_ci } 6353af6ab5fSopenharmony_ci 6363af6ab5fSopenharmony_ci if (prop->IsSpreadElement() && (prop->AsSpreadElement()->Argument() == ident)) { 6373af6ab5fSopenharmony_ci return true; 6383af6ab5fSopenharmony_ci } 6393af6ab5fSopenharmony_ci } 6403af6ab5fSopenharmony_ci 6413af6ab5fSopenharmony_ci return false; 6423af6ab5fSopenharmony_ci} 6433af6ab5fSopenharmony_ci 6443af6ab5fSopenharmony_ciSignedNumberLiteral Helpers::GetSignedNumberLiteral(const ir::Expression *expr) 6453af6ab5fSopenharmony_ci{ 6463af6ab5fSopenharmony_ci if (!expr->IsUnaryExpression()) { 6473af6ab5fSopenharmony_ci return SignedNumberLiteral::UNRECOGNIZED; 6483af6ab5fSopenharmony_ci } 6493af6ab5fSopenharmony_ci 6503af6ab5fSopenharmony_ci auto unaryExpression = expr->AsUnaryExpression(); 6513af6ab5fSopenharmony_ci if (!unaryExpression->Argument()->IsNumberLiteral()) { 6523af6ab5fSopenharmony_ci return SignedNumberLiteral::UNRECOGNIZED; 6533af6ab5fSopenharmony_ci } 6543af6ab5fSopenharmony_ci 6553af6ab5fSopenharmony_ci // TODO(hxw): Here we return different value for positive and nagative number literal in UnaryExpression. 6563af6ab5fSopenharmony_ci // Because when we access a computed property by MemberExpression, the compiler should emit different instruction. 6573af6ab5fSopenharmony_ci // Now es2abc always emits the instruction `loadObjByValue` whether the computed property is literal or not. 6583af6ab5fSopenharmony_ci // It can be optimized. For positive integer literal, the instruction should be `loadObjByIndex`. 6593af6ab5fSopenharmony_ci // While for negative number literal, the instruction should be `loadObjByName`. 6603af6ab5fSopenharmony_ci // So I add this util api and return different value for future use. 6613af6ab5fSopenharmony_ci if (unaryExpression->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS) { 6623af6ab5fSopenharmony_ci return SignedNumberLiteral::POSITIVE; 6633af6ab5fSopenharmony_ci } else if (unaryExpression->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS) { 6643af6ab5fSopenharmony_ci return SignedNumberLiteral::NEGATIVE; 6653af6ab5fSopenharmony_ci } 6663af6ab5fSopenharmony_ci 6673af6ab5fSopenharmony_ci return SignedNumberLiteral::UNRECOGNIZED; 6683af6ab5fSopenharmony_ci} 6693af6ab5fSopenharmony_ci 6703af6ab5fSopenharmony_civoid Helpers::SetConstantLocalExportSlots(const std::string &record, const std::unordered_set<uint32_t> &slots) 6713af6ab5fSopenharmony_ci{ 6723af6ab5fSopenharmony_ci bool ignored; 6733af6ab5fSopenharmony_ci auto &result = panda::bytecodeopt::BytecodeAnalysisResults::GetOrCreateBytecodeAnalysisResult(record, ignored); 6743af6ab5fSopenharmony_ci result.SetConstantLocalExportSlots(slots); 6753af6ab5fSopenharmony_ci} 6763af6ab5fSopenharmony_ci 6773af6ab5fSopenharmony_cistatic std::string GetTempOutputName(const std::string &inputFile) 6783af6ab5fSopenharmony_ci{ 6793af6ab5fSopenharmony_ci std::string pid; 6803af6ab5fSopenharmony_ci#ifdef PANDA_TARGET_WINDOWS 6813af6ab5fSopenharmony_ci pid = std::to_string(GetCurrentProcessId()); 6823af6ab5fSopenharmony_ci#else 6833af6ab5fSopenharmony_ci pid = std::to_string(getpid()); 6843af6ab5fSopenharmony_ci#endif 6853af6ab5fSopenharmony_ci const std::string outputSuffix = ".unopt.abc"; 6863af6ab5fSopenharmony_ci return panda::os::file::File::GetExtendedFilePath(inputFile + pid + outputSuffix); 6873af6ab5fSopenharmony_ci} 6883af6ab5fSopenharmony_ci 6893af6ab5fSopenharmony_civoid Helpers::AnalysisProgram(panda::pandasm::Program *prog, const std::string &inputFile) 6903af6ab5fSopenharmony_ci{ 6913af6ab5fSopenharmony_ci std::map<std::string, size_t> stat; 6923af6ab5fSopenharmony_ci std::map<std::string, size_t> *statp = &stat; 6933af6ab5fSopenharmony_ci 6943af6ab5fSopenharmony_ci#ifdef PANDA_WITH_BYTECODE_OPTIMIZER 6953af6ab5fSopenharmony_ci auto tempOutput = GetTempOutputName(inputFile); 6963af6ab5fSopenharmony_ci bool exists = false; 6973af6ab5fSopenharmony_ci auto mapsp = &panda::bytecodeopt::BytecodeAnalysisResults::GetOrCreateBytecodeMaps(tempOutput, exists); 6983af6ab5fSopenharmony_ci ASSERT(!exists); 6993af6ab5fSopenharmony_ci 7003af6ab5fSopenharmony_ci const uint32_t COMPONENT_MASK = panda::Logger::Component::ASSEMBLER | 7013af6ab5fSopenharmony_ci panda::Logger::Component::BYTECODE_OPTIMIZER | 7023af6ab5fSopenharmony_ci panda::Logger::Component::COMPILER; 7033af6ab5fSopenharmony_ci panda::Logger::InitializeStdLogging(panda::Logger::Level::ERROR, COMPONENT_MASK); 7043af6ab5fSopenharmony_ci 7053af6ab5fSopenharmony_ci if (panda::pandasm::AsmEmitter::Emit(tempOutput, *prog, statp, mapsp, true)) { 7063af6ab5fSopenharmony_ci panda::bytecodeopt::AnalysisBytecode(prog, mapsp, tempOutput, true, true); 7073af6ab5fSopenharmony_ci } else { 7083af6ab5fSopenharmony_ci panda::bytecodeopt::BytecodeAnalysisResults::DeleteBytecodeMaps(tempOutput); 7093af6ab5fSopenharmony_ci } 7103af6ab5fSopenharmony_ci#endif 7113af6ab5fSopenharmony_ci} 7123af6ab5fSopenharmony_ci 7133af6ab5fSopenharmony_civoid Helpers::OptimizeProgram(panda::pandasm::Program *prog, const std::string &inputFile) 7143af6ab5fSopenharmony_ci{ 7153af6ab5fSopenharmony_ci std::map<std::string, size_t> stat; 7163af6ab5fSopenharmony_ci std::map<std::string, size_t> *statp = &stat; 7173af6ab5fSopenharmony_ci auto tempOutput = GetTempOutputName(inputFile); 7183af6ab5fSopenharmony_ci 7193af6ab5fSopenharmony_ci#ifdef PANDA_WITH_BYTECODE_OPTIMIZER 7203af6ab5fSopenharmony_ci const uint32_t COMPONENT_MASK = panda::Logger::Component::ASSEMBLER | 7213af6ab5fSopenharmony_ci panda::Logger::Component::BYTECODE_OPTIMIZER | 7223af6ab5fSopenharmony_ci panda::Logger::Component::COMPILER; 7233af6ab5fSopenharmony_ci panda::Logger::InitializeStdLogging(panda::Logger::Level::ERROR, COMPONENT_MASK); 7243af6ab5fSopenharmony_ci 7253af6ab5fSopenharmony_ci bool exists = false; 7263af6ab5fSopenharmony_ci auto mapsp = &panda::bytecodeopt::BytecodeAnalysisResults::GetOrCreateBytecodeMaps(tempOutput, exists); 7273af6ab5fSopenharmony_ci if (!exists) { 7283af6ab5fSopenharmony_ci exists = panda::pandasm::AsmEmitter::Emit(tempOutput, *prog, statp, mapsp, true); 7293af6ab5fSopenharmony_ci } 7303af6ab5fSopenharmony_ci if (exists) { 7313af6ab5fSopenharmony_ci panda::bytecodeopt::OptimizeBytecode(prog, mapsp, tempOutput, true, true); 7323af6ab5fSopenharmony_ci std::remove(tempOutput.c_str()); 7333af6ab5fSopenharmony_ci } 7343af6ab5fSopenharmony_ci panda::bytecodeopt::BytecodeAnalysisResults::DeleteBytecodeMaps(tempOutput); 7353af6ab5fSopenharmony_ci 7363af6ab5fSopenharmony_ci#endif 7373af6ab5fSopenharmony_ci} 7383af6ab5fSopenharmony_ci 7393af6ab5fSopenharmony_cibool Helpers::CheckAopTransformPath(const std::string &libPath) 7403af6ab5fSopenharmony_ci{ 7413af6ab5fSopenharmony_ci std::string lowerLibPath = libPath; 7423af6ab5fSopenharmony_ci std::transform(libPath.begin(), libPath.end(), lowerLibPath.begin(), ::tolower); 7433af6ab5fSopenharmony_ci bool isValidSuffix = false; 7443af6ab5fSopenharmony_ci#ifdef PANDA_TARGET_WINDOWS 7453af6ab5fSopenharmony_ci isValidSuffix = FileExtensionIs(lowerLibPath, FileSuffix::DLL); 7463af6ab5fSopenharmony_ci std::string supportSuffix = std::string(FileSuffix::DLL); 7473af6ab5fSopenharmony_ci#else 7483af6ab5fSopenharmony_ci isValidSuffix = FileExtensionIs(lowerLibPath, FileSuffix::SO) 7493af6ab5fSopenharmony_ci || FileExtensionIs(lowerLibPath, FileSuffix::DYLIB); 7503af6ab5fSopenharmony_ci std::string supportSuffix = std::string(FileSuffix::SO) + "|" + std::string(FileSuffix::DYLIB); 7513af6ab5fSopenharmony_ci#endif 7523af6ab5fSopenharmony_ci //check file suffix(.so|.dll) 7533af6ab5fSopenharmony_ci if (!isValidSuffix) { 7543af6ab5fSopenharmony_ci std::string msg = "aop transform file suffix support " + supportSuffix + ", error file: " + libPath; 7553af6ab5fSopenharmony_ci std::cout << msg << std::endl; 7563af6ab5fSopenharmony_ci return false; 7573af6ab5fSopenharmony_ci } 7583af6ab5fSopenharmony_ci return true; 7593af6ab5fSopenharmony_ci} 7603af6ab5fSopenharmony_ci 7613af6ab5fSopenharmony_ciAopTransformFuncDef Helpers::LoadAopTransformLibFunc(const std::string &libPath, 7623af6ab5fSopenharmony_ci const std::string &funcName, os::library_loader::LibraryHandle &handler) 7633af6ab5fSopenharmony_ci{ 7643af6ab5fSopenharmony_ci auto loadRes = os::library_loader::Load(libPath); 7653af6ab5fSopenharmony_ci if (!loadRes.HasValue()) { 7663af6ab5fSopenharmony_ci std::string msg = "os::library_loader::Load error: " + loadRes.Error().ToString(); 7673af6ab5fSopenharmony_ci std::cout << msg << std::endl; 7683af6ab5fSopenharmony_ci return nullptr; 7693af6ab5fSopenharmony_ci } 7703af6ab5fSopenharmony_ci handler = std::move(loadRes.Value()); 7713af6ab5fSopenharmony_ci 7723af6ab5fSopenharmony_ci auto initRes = os::library_loader::ResolveSymbol(handler, funcName); 7733af6ab5fSopenharmony_ci if (!initRes.HasValue()) { 7743af6ab5fSopenharmony_ci std::string msg = "os::library_loader::ResolveSymbol get func Transform error: " + initRes.Error().ToString(); 7753af6ab5fSopenharmony_ci std::cout << msg << std::endl; 7763af6ab5fSopenharmony_ci return nullptr; 7773af6ab5fSopenharmony_ci } 7783af6ab5fSopenharmony_ci 7793af6ab5fSopenharmony_ci return reinterpret_cast<AopTransformFuncDef>(initRes.Value()); 7803af6ab5fSopenharmony_ci} 7813af6ab5fSopenharmony_ci 7823af6ab5fSopenharmony_cibool Helpers::AopTransform(const std::string &inputFile, const std::string &libPath) 7833af6ab5fSopenharmony_ci{ 7843af6ab5fSopenharmony_ci if (!CheckAopTransformPath(libPath)) { 7853af6ab5fSopenharmony_ci return false; 7863af6ab5fSopenharmony_ci } 7873af6ab5fSopenharmony_ci 7883af6ab5fSopenharmony_ci os::library_loader::LibraryHandle handler(nullptr); 7893af6ab5fSopenharmony_ci AopTransformFuncDef transform = LoadAopTransformLibFunc(libPath, "Transform", handler); 7903af6ab5fSopenharmony_ci if (transform == nullptr) { 7913af6ab5fSopenharmony_ci return false; 7923af6ab5fSopenharmony_ci } 7933af6ab5fSopenharmony_ci 7943af6ab5fSopenharmony_ci //invoke Transform, untransformed ABC to transformed ABC, result define: 0:success, other:fail 7953af6ab5fSopenharmony_ci int res = transform(inputFile.c_str()); 7963af6ab5fSopenharmony_ci if (res != 0) { 7973af6ab5fSopenharmony_ci std::string msg = "Transform exec fail: " + libPath; 7983af6ab5fSopenharmony_ci std::cout << msg << std::endl; 7993af6ab5fSopenharmony_ci return false; 8003af6ab5fSopenharmony_ci } 8013af6ab5fSopenharmony_ci return true; 8023af6ab5fSopenharmony_ci} 8033af6ab5fSopenharmony_ci 8043af6ab5fSopenharmony_cibool Helpers::ReadFileToBuffer(const std::string &file, std::stringstream &ss) 8053af6ab5fSopenharmony_ci{ 8063af6ab5fSopenharmony_ci std::ifstream inputStream = Helpers::FileStream<std::ifstream>( 8073af6ab5fSopenharmony_ci panda::os::file::File::GetExtendedFilePath(file), std::ios::binary); 8083af6ab5fSopenharmony_ci if (inputStream.fail()) { 8093af6ab5fSopenharmony_ci std::cerr << "Failed to read file to buffer: " << file << std::endl << 8103af6ab5fSopenharmony_ci "Solutions: > Check whether the above file exists." << 8113af6ab5fSopenharmony_ci "> Check whether you have the correct access permissions for the file."; 8123af6ab5fSopenharmony_ci return false; 8133af6ab5fSopenharmony_ci } 8143af6ab5fSopenharmony_ci ss << inputStream.rdbuf(); 8153af6ab5fSopenharmony_ci return true; 8163af6ab5fSopenharmony_ci} 8173af6ab5fSopenharmony_ci 8183af6ab5fSopenharmony_civoid Helpers::ScanDirectives(ir::ScriptFunction *func, const lexer::LineIndex &lineIndex, bool enableSendableClass, 8193af6ab5fSopenharmony_ci bool enableSendableFunc) 8203af6ab5fSopenharmony_ci{ 8213af6ab5fSopenharmony_ci auto *body = func->Body(); 8223af6ab5fSopenharmony_ci if (!body || body->IsExpression()) { 8233af6ab5fSopenharmony_ci return; 8243af6ab5fSopenharmony_ci } 8253af6ab5fSopenharmony_ci 8263af6ab5fSopenharmony_ci auto &statements = body->AsBlockStatement()->Statements(); 8273af6ab5fSopenharmony_ci if (statements.empty()) { 8283af6ab5fSopenharmony_ci return; 8293af6ab5fSopenharmony_ci } 8303af6ab5fSopenharmony_ci 8313af6ab5fSopenharmony_ci bool keepScan = true; 8323af6ab5fSopenharmony_ci auto iter = statements.begin(); 8333af6ab5fSopenharmony_ci while (keepScan && (iter != statements.end())) { 8343af6ab5fSopenharmony_ci auto *stmt = *iter++; 8353af6ab5fSopenharmony_ci if (!stmt->IsExpressionStatement()) { 8363af6ab5fSopenharmony_ci return; 8373af6ab5fSopenharmony_ci } 8383af6ab5fSopenharmony_ci 8393af6ab5fSopenharmony_ci auto *expr = stmt->AsExpressionStatement()->GetExpression(); 8403af6ab5fSopenharmony_ci if (!expr->IsStringLiteral()) { 8413af6ab5fSopenharmony_ci return; 8423af6ab5fSopenharmony_ci } 8433af6ab5fSopenharmony_ci 8443af6ab5fSopenharmony_ci keepScan = SetFuncFlagsForDirectives(expr->AsStringLiteral(), func, lineIndex, enableSendableClass, 8453af6ab5fSopenharmony_ci enableSendableFunc); 8463af6ab5fSopenharmony_ci } 8473af6ab5fSopenharmony_ci 8483af6ab5fSopenharmony_ci return; 8493af6ab5fSopenharmony_ci} 8503af6ab5fSopenharmony_ci 8513af6ab5fSopenharmony_cibool Helpers::SetFuncFlagsForDirectives(const ir::StringLiteral *strLit, ir::ScriptFunction *func, 8523af6ab5fSopenharmony_ci const lexer::LineIndex &lineIndex, bool enableSendableClass, 8533af6ab5fSopenharmony_ci bool enableSendableFunc) 8543af6ab5fSopenharmony_ci{ 8553af6ab5fSopenharmony_ci if (strLit->Str().Is(USE_CONCURRENT)) { 8563af6ab5fSopenharmony_ci util::Concurrent::SetConcurrent(func, strLit, lineIndex); 8573af6ab5fSopenharmony_ci return true; 8583af6ab5fSopenharmony_ci } 8593af6ab5fSopenharmony_ci 8603af6ab5fSopenharmony_ci if (strLit->Str().Is(USE_SENDABLE)) { 8613af6ab5fSopenharmony_ci if (func->IsConstructor()) { 8623af6ab5fSopenharmony_ci if (enableSendableClass) { 8633af6ab5fSopenharmony_ci auto *classDef = const_cast<ir::ClassDefinition*>(GetClassDefiniton(func)); 8643af6ab5fSopenharmony_ci classDef->SetSendable(); 8653af6ab5fSopenharmony_ci } 8663af6ab5fSopenharmony_ci } else if (enableSendableFunc) { 8673af6ab5fSopenharmony_ci func->AddFlag(ir::ScriptFunctionFlags::SENDABLE); 8683af6ab5fSopenharmony_ci } 8693af6ab5fSopenharmony_ci return true; 8703af6ab5fSopenharmony_ci } 8713af6ab5fSopenharmony_ci 8723af6ab5fSopenharmony_ci return false; 8733af6ab5fSopenharmony_ci} 8743af6ab5fSopenharmony_ci 8753af6ab5fSopenharmony_cistd::string Helpers::GetHashString(const std::string &str) 8763af6ab5fSopenharmony_ci{ 8773af6ab5fSopenharmony_ci uint64_t result = FNV_OFFSET; 8783af6ab5fSopenharmony_ci 8793af6ab5fSopenharmony_ci const uint8_t *input = reinterpret_cast<const uint8_t *>(str.c_str()); 8803af6ab5fSopenharmony_ci // FNV-1a 64-bit Algorithm 8813af6ab5fSopenharmony_ci for (size_t i = 0; i < str.size(); i++) { 8823af6ab5fSopenharmony_ci result ^= input[i]; 8833af6ab5fSopenharmony_ci result *= FNV_PRIME; 8843af6ab5fSopenharmony_ci } 8853af6ab5fSopenharmony_ci 8863af6ab5fSopenharmony_ci return std::to_string(result); 8873af6ab5fSopenharmony_ci} 8883af6ab5fSopenharmony_ci 8893af6ab5fSopenharmony_ci#ifdef PANDA_TARGET_WINDOWS 8903af6ab5fSopenharmony_cistd::wstring Helpers::Utf8ToUtf16(const std::string &utf8) 8913af6ab5fSopenharmony_ci{ 8923af6ab5fSopenharmony_ci std::wstring utf16; 8933af6ab5fSopenharmony_ci if (utf8.empty()) { 8943af6ab5fSopenharmony_ci return utf16; 8953af6ab5fSopenharmony_ci } 8963af6ab5fSopenharmony_ci 8973af6ab5fSopenharmony_ci if (utf8.length() > static_cast<size_t>(std::numeric_limits<int>::max())) { 8983af6ab5fSopenharmony_ci std::cerr << "Length of filename: " << utf8 << " is too long" << std::endl; 8993af6ab5fSopenharmony_ci return utf16; 9003af6ab5fSopenharmony_ci } 9013af6ab5fSopenharmony_ci 9023af6ab5fSopenharmony_ci const int utf8Length = static_cast<int>(utf8.length()); 9033af6ab5fSopenharmony_ci constexpr DWORD kFlags = MB_ERR_INVALID_CHARS; 9043af6ab5fSopenharmony_ci const int utf16Length = MultiByteToWideChar(CP_UTF8, kFlags, utf8.data(), utf8Length, nullptr, 0); 9053af6ab5fSopenharmony_ci if (utf16Length == 0) { 9063af6ab5fSopenharmony_ci std::cerr << "The filename: " << utf8 << " is not a valid utf8 encoding string" << std::endl; 9073af6ab5fSopenharmony_ci return utf16; 9083af6ab5fSopenharmony_ci } 9093af6ab5fSopenharmony_ci 9103af6ab5fSopenharmony_ci utf16.resize(utf16Length); 9113af6ab5fSopenharmony_ci MultiByteToWideChar(CP_UTF8, kFlags, utf8.data(), utf8Length, &utf16[0], utf16Length); 9123af6ab5fSopenharmony_ci return utf16; 9133af6ab5fSopenharmony_ci} 9143af6ab5fSopenharmony_ci#endif 9153af6ab5fSopenharmony_ci 9163af6ab5fSopenharmony_civoid Helpers::ThrowError(ErrorType type, const parser::Program *program, const lexer::SourcePosition &pos, 9173af6ab5fSopenharmony_ci const std::string_view &msg) 9183af6ab5fSopenharmony_ci{ 9193af6ab5fSopenharmony_ci lexer::LineIndex index(program->SourceCode()); 9203af6ab5fSopenharmony_ci lexer::SourceLocation loc = index.GetLocation(pos); 9213af6ab5fSopenharmony_ci 9223af6ab5fSopenharmony_ci throw Error {type, msg, loc.line, loc.col}; 9233af6ab5fSopenharmony_ci} 9243af6ab5fSopenharmony_ci 9253af6ab5fSopenharmony_cibool Helpers::IsUseShared(const ir::Statement *statement) 9263af6ab5fSopenharmony_ci{ 9273af6ab5fSopenharmony_ci if (!statement->IsExpressionStatement()) { 9283af6ab5fSopenharmony_ci return false; 9293af6ab5fSopenharmony_ci } 9303af6ab5fSopenharmony_ci 9313af6ab5fSopenharmony_ci if (!statement->AsExpressionStatement()->GetExpression()->IsStringLiteral()) { 9323af6ab5fSopenharmony_ci return false; 9333af6ab5fSopenharmony_ci } 9343af6ab5fSopenharmony_ci 9353af6ab5fSopenharmony_ci return statement->AsExpressionStatement()->GetExpression()->AsStringLiteral()->Str().Is(USE_SHARED); 9363af6ab5fSopenharmony_ci} 9373af6ab5fSopenharmony_ci 9383af6ab5fSopenharmony_ciconst ir::ClassDefinition *Helpers::GetContainingSendableClass(const ir::AstNode *node) 9393af6ab5fSopenharmony_ci{ 9403af6ab5fSopenharmony_ci while (node != nullptr) { 9413af6ab5fSopenharmony_ci if (node->IsClassDefinition() && node->AsClassDefinition()->IsSendable()) { 9423af6ab5fSopenharmony_ci return node->AsClassDefinition(); 9433af6ab5fSopenharmony_ci } 9443af6ab5fSopenharmony_ci 9453af6ab5fSopenharmony_ci node = node->Parent(); 9463af6ab5fSopenharmony_ci } 9473af6ab5fSopenharmony_ci 9483af6ab5fSopenharmony_ci return nullptr; 9493af6ab5fSopenharmony_ci} 9503af6ab5fSopenharmony_ci 9513af6ab5fSopenharmony_cibool Helpers::IsSpecialScopeName(const util::StringView &name) 9523af6ab5fSopenharmony_ci{ 9533af6ab5fSopenharmony_ci return name.Find(Helpers::DOT.data()) != std::string::npos || 9543af6ab5fSopenharmony_ci name.Find(Helpers::BACKSLASH.data()) != std::string::npos; 9553af6ab5fSopenharmony_ci} 9563af6ab5fSopenharmony_ci 9573af6ab5fSopenharmony_cibool Helpers::BelongingToRecords(const std::string &name, const std::unordered_set<std::string> &retainRecordSet, 9583af6ab5fSopenharmony_ci const std::string &delimiter) 9593af6ab5fSopenharmony_ci{ 9603af6ab5fSopenharmony_ci size_t pos = name.rfind(delimiter); 9613af6ab5fSopenharmony_ci if (pos == std::string::npos) { 9623af6ab5fSopenharmony_ci std::cerr << "The input name: " << name << " is illegal, it should contain the delimiter character '" << 9633af6ab5fSopenharmony_ci delimiter << "'" << std::endl; 9643af6ab5fSopenharmony_ci return false; 9653af6ab5fSopenharmony_ci } 9663af6ab5fSopenharmony_ci 9673af6ab5fSopenharmony_ci auto recordName = name.substr(0, pos); 9683af6ab5fSopenharmony_ci return retainRecordSet.find(recordName) != retainRecordSet.end(); 9693af6ab5fSopenharmony_ci} 9703af6ab5fSopenharmony_ci 9713af6ab5fSopenharmony_civoid Helpers::RemoveProgramsRedundantData(std::map<std::string, panda::es2panda::util::ProgramCache*> &progsInfo, 9723af6ab5fSopenharmony_ci const std::map<std::string, std::unordered_set<std::string>> &resolvedDepsRelation) 9733af6ab5fSopenharmony_ci{ 9743af6ab5fSopenharmony_ci auto progInfoIter = progsInfo.begin(); 9753af6ab5fSopenharmony_ci while (progInfoIter != progsInfo.end()) { 9763af6ab5fSopenharmony_ci // remove redundant sourcefiles and bytecodefile data which are not dependant in compilation 9773af6ab5fSopenharmony_ci if (resolvedDepsRelation.find(progInfoIter->first) == resolvedDepsRelation.end()) { 9783af6ab5fSopenharmony_ci progInfoIter = progsInfo.erase(progInfoIter); 9793af6ab5fSopenharmony_ci continue; 9803af6ab5fSopenharmony_ci } 9813af6ab5fSopenharmony_ci 9823af6ab5fSopenharmony_ci progInfoIter++; 9833af6ab5fSopenharmony_ci } 9843af6ab5fSopenharmony_ci} 9853af6ab5fSopenharmony_ci 9863af6ab5fSopenharmony_cibool Helpers::IsDefaultApiVersion(int apiVersion, std::string subApiVersion) 9873af6ab5fSopenharmony_ci{ 9883af6ab5fSopenharmony_ci return apiVersion < DEFAULT_TARGET_API_VERSION || ((apiVersion == DEFAULT_TARGET_API_VERSION) && 9893af6ab5fSopenharmony_ci (subApiVersion == SUB_API_VERSION_1 || subApiVersion == SUB_API_VERSION_2)); 9903af6ab5fSopenharmony_ci} 9913af6ab5fSopenharmony_ci 9923af6ab5fSopenharmony_cibool Helpers::IsSupportLazyImportVersion(int apiVersion, std::string subApiVersion) 9933af6ab5fSopenharmony_ci{ 9943af6ab5fSopenharmony_ci return !(apiVersion < LAZY_IMPORT_MIN_SUPPORTED_API_VERSION || 9953af6ab5fSopenharmony_ci ((apiVersion == LAZY_IMPORT_MIN_SUPPORTED_API_VERSION) && 9963af6ab5fSopenharmony_ci (subApiVersion == SUB_API_VERSION_1 || subApiVersion == SUB_API_VERSION_2))); 9973af6ab5fSopenharmony_ci} 9983af6ab5fSopenharmony_ci 9993af6ab5fSopenharmony_ci} // namespace panda::es2panda::util 1000