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