14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include <chrono>
174514f5e3Sopenharmony_ci#include <iostream>
184514f5e3Sopenharmony_ci#include <memory>
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_ci#include "ecmascript/base/string_helper.h"
214514f5e3Sopenharmony_ci#include "ecmascript/checkpoint/thread_state_transition.h"
224514f5e3Sopenharmony_ci#include "ecmascript/compiler/aot_compilation_env.h"
234514f5e3Sopenharmony_ci#include "ecmascript/compiler/aot_compiler_preprocessor.h"
244514f5e3Sopenharmony_ci#include "ecmascript/compiler/aot_file/aot_file_manager.h"
254514f5e3Sopenharmony_ci#include "ecmascript/compiler/pass_manager.h"
264514f5e3Sopenharmony_ci#include "ecmascript/ecma_string.h"
274514f5e3Sopenharmony_ci#include "ecmascript/js_runtime_options.h"
284514f5e3Sopenharmony_ci#include "ecmascript/log.h"
294514f5e3Sopenharmony_ci#include "ecmascript/log_wrapper.h"
304514f5e3Sopenharmony_ci#include "ecmascript/napi/include/jsnapi.h"
314514f5e3Sopenharmony_ci#include "ecmascript/ohos/enable_aot_list_helper.h"
324514f5e3Sopenharmony_ci#include "ecmascript/ohos/ohos_pkg_args.h"
334514f5e3Sopenharmony_ci#include "ecmascript/platform/aot_crash_info.h"
344514f5e3Sopenharmony_ci#include "ecmascript/platform/file.h"
354514f5e3Sopenharmony_ci#include "ecmascript/platform/filesystem.h"
364514f5e3Sopenharmony_ci
374514f5e3Sopenharmony_ci#include "ecmascript/compiler/aot_compiler_stats.h"
384514f5e3Sopenharmony_ci
394514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
404514f5e3Sopenharmony_cinamespace {
414514f5e3Sopenharmony_ci/**
424514f5e3Sopenharmony_ci * @param ErrCode return code of ark_aot_compiler
434514f5e3Sopenharmony_ci * @attention it must sync with RetStatusOfCompiler of
444514f5e3Sopenharmony_ci *            "ets_runtime/compiler_service/include/aot_compiler_constants.h"
454514f5e3Sopenharmony_ci */
464514f5e3Sopenharmony_cienum ErrCode {
474514f5e3Sopenharmony_ci    ERR_OK = (0),   // IMPORTANT: Only if aot compiler SUCCESS and save an/ai SUCCESS, return ERR_OK.
484514f5e3Sopenharmony_ci    ERR_FAIL = (-1),
494514f5e3Sopenharmony_ci    ERR_HELP = (1),
504514f5e3Sopenharmony_ci    ERR_NO_AP = (2),
514514f5e3Sopenharmony_ci    ERR_MERGE_AP = (3),
524514f5e3Sopenharmony_ci    ERR_CHECK_VERSION = (4),
534514f5e3Sopenharmony_ci    ERR_AN_EMPTY = (5),
544514f5e3Sopenharmony_ci    ERR_AN_FAIL = (6),
554514f5e3Sopenharmony_ci    ERR_AI_FAIL = (7),
564514f5e3Sopenharmony_ci};
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_cibool CheckVersion(JSRuntimeOptions& runtimeOptions, AotCompilerStats& compilerStats, bool isPgoMerged)
594514f5e3Sopenharmony_ci{
604514f5e3Sopenharmony_ci    if (runtimeOptions.IsCheckPgoVersion()) {
614514f5e3Sopenharmony_ci        if (!isPgoMerged) {
624514f5e3Sopenharmony_ci            LOG_COMPILER(ERROR) << "CheckVersion ap and abc may not match";
634514f5e3Sopenharmony_ci            compilerStats.SetPgoFileLegal(false);
644514f5e3Sopenharmony_ci        }
654514f5e3Sopenharmony_ci        if (runtimeOptions.IsTargetCompilerMode()) {
664514f5e3Sopenharmony_ci            compilerStats.PrintCompilerStatsLog();
674514f5e3Sopenharmony_ci        }
684514f5e3Sopenharmony_ci        return true;
694514f5e3Sopenharmony_ci    }
704514f5e3Sopenharmony_ci    return false;
714514f5e3Sopenharmony_ci}
724514f5e3Sopenharmony_ci
734514f5e3Sopenharmony_cibool IsExistsPkgInfo(AotCompilerPreprocessor &cPreprocessor)
744514f5e3Sopenharmony_ci{
754514f5e3Sopenharmony_ci    if (cPreprocessor.GetMainPkgArgs()) {
764514f5e3Sopenharmony_ci        return true;
774514f5e3Sopenharmony_ci    }
784514f5e3Sopenharmony_ci    return false;
794514f5e3Sopenharmony_ci}
804514f5e3Sopenharmony_ci} // namespace
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ciint Main(const int argc, const char **argv)
834514f5e3Sopenharmony_ci{
844514f5e3Sopenharmony_ci    if (argc < 2) { // 2: at least have two arguments
854514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << AotCompilerPreprocessor::GetHelper();
864514f5e3Sopenharmony_ci        return ERR_FAIL;
874514f5e3Sopenharmony_ci    }
884514f5e3Sopenharmony_ci
894514f5e3Sopenharmony_ci    JSRuntimeOptions runtimeOptions;
904514f5e3Sopenharmony_ci    bool retOpt = runtimeOptions.ParseCommand(argc, argv);
914514f5e3Sopenharmony_ci    if (!retOpt) {
924514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << AotCompilerPreprocessor::GetHelper();
934514f5e3Sopenharmony_ci        return ERR_HELP;
944514f5e3Sopenharmony_ci    }
954514f5e3Sopenharmony_ci
964514f5e3Sopenharmony_ci    bool ret = true;
974514f5e3Sopenharmony_ci    // ark_aot_compiler running need disable asm interpreter to disable the loading of AOT files.
984514f5e3Sopenharmony_ci    runtimeOptions.SetEnableAsmInterpreter(false);
994514f5e3Sopenharmony_ci    runtimeOptions.SetOptionsForTargetCompilation();
1004514f5e3Sopenharmony_ci    EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions);
1014514f5e3Sopenharmony_ci    if (vm == nullptr) {
1024514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Cannot Create vm";
1034514f5e3Sopenharmony_ci        return ERR_FAIL;
1044514f5e3Sopenharmony_ci    }
1054514f5e3Sopenharmony_ci
1064514f5e3Sopenharmony_ci    {
1074514f5e3Sopenharmony_ci        AOTCompilationEnv aotCompilationEnv(vm);
1084514f5e3Sopenharmony_ci        ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
1094514f5e3Sopenharmony_ci        LocalScope scope(vm);
1104514f5e3Sopenharmony_ci        arg_list_t pandaFileNames {};
1114514f5e3Sopenharmony_ci        std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
1124514f5e3Sopenharmony_ci        CompilationOptions cOptions(runtimeOptions);
1134514f5e3Sopenharmony_ci
1144514f5e3Sopenharmony_ci        CompilerLog log(cOptions.logOption_);
1154514f5e3Sopenharmony_ci        log.SetEnableCompilerLogTime(cOptions.compilerLogTime_);
1164514f5e3Sopenharmony_ci        AotMethodLogList logList(cOptions.logMethodsList_);
1174514f5e3Sopenharmony_ci        PGOProfilerDecoder profilerDecoder;
1184514f5e3Sopenharmony_ci
1194514f5e3Sopenharmony_ci        AotCompilerPreprocessor cPreprocessor(vm, runtimeOptions, pkgArgsMap, profilerDecoder, pandaFileNames);
1204514f5e3Sopenharmony_ci        if (!cPreprocessor.HandleTargetCompilerMode(cOptions) || !cPreprocessor.HandlePandaFileNames(argc, argv)) {
1214514f5e3Sopenharmony_ci            return ERR_HELP;
1224514f5e3Sopenharmony_ci        }
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ci        if (IsExistsPkgInfo(cPreprocessor)) {
1254514f5e3Sopenharmony_ci            if (AotCrashInfo::IsAotEscaped(cPreprocessor.GetMainPkgArgs()->GetPgoDir())) {
1264514f5e3Sopenharmony_ci                LOG_COMPILER(ERROR) << "Stop compile AOT because there are multiple crashes";
1274514f5e3Sopenharmony_ci                return ERR_FAIL;
1284514f5e3Sopenharmony_ci            }
1294514f5e3Sopenharmony_ci        }
1304514f5e3Sopenharmony_ci        if (runtimeOptions.IsPartialCompilerMode() && cOptions.profilerIn_.empty()) {
1314514f5e3Sopenharmony_ci            // no need to compile in partial mode without any ap files.
1324514f5e3Sopenharmony_ci            return ERR_NO_AP;
1334514f5e3Sopenharmony_ci        }
1344514f5e3Sopenharmony_ci
1354514f5e3Sopenharmony_ci        AotCompilerStats compilerStats;
1364514f5e3Sopenharmony_ci        std::string bundleName = "";
1374514f5e3Sopenharmony_ci        if (cPreprocessor.GetMainPkgArgs()) {
1384514f5e3Sopenharmony_ci            bundleName = cPreprocessor.GetMainPkgArgs()->GetBundleName();
1394514f5e3Sopenharmony_ci        }
1404514f5e3Sopenharmony_ci        compilerStats.SetBundleName(bundleName);
1414514f5e3Sopenharmony_ci        compilerStats.SetAotFilePath(cOptions.outputFileName_);
1424514f5e3Sopenharmony_ci        compilerStats.SetPgoPath(cOptions.profilerIn_);
1434514f5e3Sopenharmony_ci        compilerStats.StartCompiler();
1444514f5e3Sopenharmony_ci        profilerDecoder.SetHotnessThreshold(cOptions.hotnessThreshold_);
1454514f5e3Sopenharmony_ci        profilerDecoder.SetInPath(cOptions.profilerIn_);
1464514f5e3Sopenharmony_ci        cPreprocessor.AOTInitialize();
1474514f5e3Sopenharmony_ci        uint32_t checksum = cPreprocessor.GenerateAbcFileInfos();
1484514f5e3Sopenharmony_ci
1494514f5e3Sopenharmony_ci        if (runtimeOptions.IsTargetCompilerMode() && (cPreprocessor.HasExistsAOTFiles(cOptions) ||
1504514f5e3Sopenharmony_ci            cPreprocessor.HasPreloadAotFile())) {
1514514f5e3Sopenharmony_ci            LOG_COMPILER(ERROR) << "The AOT file already exists and will not be compiled anymore";
1524514f5e3Sopenharmony_ci            return ERR_OK;
1534514f5e3Sopenharmony_ci        }
1544514f5e3Sopenharmony_ci
1554514f5e3Sopenharmony_ci        ret = cPreprocessor.GetCompilerResult();
1564514f5e3Sopenharmony_ci        // Notice: lx move load pandaFileHead and verify before GeneralAbcFileInfos.
1574514f5e3Sopenharmony_ci        // need support multiple abc
1584514f5e3Sopenharmony_ci        auto isPgoMerged = cPreprocessor.HandleMergedPgoFile(checksum);
1594514f5e3Sopenharmony_ci        if (CheckVersion(runtimeOptions, compilerStats, isPgoMerged)) {
1604514f5e3Sopenharmony_ci            return ERR_CHECK_VERSION;
1614514f5e3Sopenharmony_ci        }
1624514f5e3Sopenharmony_ci        std::string appSignature = cPreprocessor.GetMainPkgArgsAppSignature();
1634514f5e3Sopenharmony_ci        if (!isPgoMerged) {
1644514f5e3Sopenharmony_ci            AOTFileGenerator::SaveEmptyAOTFile(
1654514f5e3Sopenharmony_ci                cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AN, appSignature, true);
1664514f5e3Sopenharmony_ci            AOTFileGenerator::SaveEmptyAOTFile(
1674514f5e3Sopenharmony_ci                cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AI, appSignature, false);
1684514f5e3Sopenharmony_ci            return ERR_MERGE_AP;
1694514f5e3Sopenharmony_ci        }
1704514f5e3Sopenharmony_ci        cPreprocessor.Process(cOptions);
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ci        PassOptions::Builder optionsBuilder;
1734514f5e3Sopenharmony_ci        PassOptions passOptions =
1744514f5e3Sopenharmony_ci            optionsBuilder.EnableArrayBoundsCheckElimination(cOptions.isEnableArrayBoundsCheckElimination_)
1754514f5e3Sopenharmony_ci                .EnableTypeLowering(cOptions.isEnableTypeLowering_)
1764514f5e3Sopenharmony_ci                .EnableEarlyElimination(cOptions.isEnableEarlyElimination_)
1774514f5e3Sopenharmony_ci                .EnableLaterElimination(cOptions.isEnableLaterElimination_)
1784514f5e3Sopenharmony_ci                .EnableValueNumbering(cOptions.isEnableValueNumbering_)
1794514f5e3Sopenharmony_ci                .EnableOptInlining(cOptions.isEnableOptInlining_)
1804514f5e3Sopenharmony_ci                .EnableOptString(cOptions.isEnableOptString_)
1814514f5e3Sopenharmony_ci                .EnableOptPGOType(cOptions.isEnableOptPGOType_)
1824514f5e3Sopenharmony_ci                .EnableOptTrackField(cOptions.isEnableOptTrackField_)
1834514f5e3Sopenharmony_ci                .EnableOptLoopPeeling(cOptions.isEnableOptLoopPeeling_)
1844514f5e3Sopenharmony_ci                .EnableOptLoopInvariantCodeMotion(cOptions.isEnableOptLoopInvariantCodeMotion_)
1854514f5e3Sopenharmony_ci                .EnableOptConstantFolding(cOptions.isEnableOptConstantFolding_)
1864514f5e3Sopenharmony_ci                .EnableLexenvSpecialization(cOptions.isEnableLexenvSpecialization_)
1874514f5e3Sopenharmony_ci                .EnableInlineNative(cOptions.isEnableNativeInline_)
1884514f5e3Sopenharmony_ci                .EnableLoweringBuiltin(cOptions.isEnableLoweringBuiltin_)
1894514f5e3Sopenharmony_ci                .EnableOptBranchProfiling(cOptions.isEnableOptBranchProfiling_)
1904514f5e3Sopenharmony_ci                .EnableEscapeAnalysis(cOptions.isEnableEscapeAnalysis_)
1914514f5e3Sopenharmony_ci                .EnableInductionVariableAnalysis(cOptions.isEnableInductionVariableAnalysis_)
1924514f5e3Sopenharmony_ci                .EnableVerifierPass(cOptions.isEnableVerifierPass_)
1934514f5e3Sopenharmony_ci                .Build();
1944514f5e3Sopenharmony_ci
1954514f5e3Sopenharmony_ci        PassManager passManager(&aotCompilationEnv,
1964514f5e3Sopenharmony_ci                                cOptions.triple_,
1974514f5e3Sopenharmony_ci                                cOptions.optLevel_,
1984514f5e3Sopenharmony_ci                                cOptions.relocMode_,
1994514f5e3Sopenharmony_ci                                &log,
2004514f5e3Sopenharmony_ci                                &logList,
2014514f5e3Sopenharmony_ci                                cOptions.maxAotMethodSize_,
2024514f5e3Sopenharmony_ci                                cOptions.maxMethodsInModule_,
2034514f5e3Sopenharmony_ci                                profilerDecoder,
2044514f5e3Sopenharmony_ci                                &passOptions,
2054514f5e3Sopenharmony_ci                                cPreprocessor.GetCallMethodFlagMap(),
2064514f5e3Sopenharmony_ci                                cPreprocessor.GetAbcFileInfo(),
2074514f5e3Sopenharmony_ci                                cPreprocessor.GetBcInfoCollectors(),
2084514f5e3Sopenharmony_ci                                cOptions.optBCRange_);
2094514f5e3Sopenharmony_ci
2104514f5e3Sopenharmony_ci        bool isEnableLiteCG = runtimeOptions.IsCompilerEnableLiteCG();
2114514f5e3Sopenharmony_ci        if (ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
2124514f5e3Sopenharmony_ci            isEnableLiteCG = true;
2134514f5e3Sopenharmony_ci        }
2144514f5e3Sopenharmony_ci        vm->GetJSOptions().SetCompilerEnableLiteCG(isEnableLiteCG);
2154514f5e3Sopenharmony_ci        compilerStats.SetIsLiteCg(isEnableLiteCG);
2164514f5e3Sopenharmony_ci
2174514f5e3Sopenharmony_ci        AOTFileGenerator generator(&log, &logList, &aotCompilationEnv, cOptions.triple_, isEnableLiteCG);
2184514f5e3Sopenharmony_ci
2194514f5e3Sopenharmony_ci        passManager.CompileValidFiles(generator, ret, compilerStats);
2204514f5e3Sopenharmony_ci        if (compilerStats.GetCompilerMethodCount() == 0) {
2214514f5e3Sopenharmony_ci            return runtimeOptions.IsPartialCompilerMode() ? ERR_AN_EMPTY : ERR_OK;
2224514f5e3Sopenharmony_ci        }
2234514f5e3Sopenharmony_ci        if (!generator.SaveAOTFile(cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AN, appSignature)) {
2244514f5e3Sopenharmony_ci            return ERR_AN_FAIL;
2254514f5e3Sopenharmony_ci        }
2264514f5e3Sopenharmony_ci        if (!generator.SaveSnapshotFile()) {
2274514f5e3Sopenharmony_ci            return ERR_AI_FAIL;
2284514f5e3Sopenharmony_ci        }
2294514f5e3Sopenharmony_ci        log.Print();
2304514f5e3Sopenharmony_ci        if (runtimeOptions.IsTargetCompilerMode()) {
2314514f5e3Sopenharmony_ci            compilerStats.PrintCompilerStatsLog();
2324514f5e3Sopenharmony_ci        }
2334514f5e3Sopenharmony_ci        if (IsExistsPkgInfo(cPreprocessor)) {
2344514f5e3Sopenharmony_ci            ohos::EnableAotJitListHelper::GetInstance()->AddEnableListCount(
2354514f5e3Sopenharmony_ci                ret, cPreprocessor.GetMainPkgArgs()->GetPgoDir());
2364514f5e3Sopenharmony_ci        }
2374514f5e3Sopenharmony_ci    }
2384514f5e3Sopenharmony_ci
2394514f5e3Sopenharmony_ci    if (vm->GetJSOptions().IsEnableCompilerLogSnapshot()) {
2404514f5e3Sopenharmony_ci        vm->PrintAOTSnapShotStats();
2414514f5e3Sopenharmony_ci    }
2424514f5e3Sopenharmony_ci    LOG_COMPILER(INFO) << (ret ? "ts aot compile success" : "ts aot compile failed");
2434514f5e3Sopenharmony_ci    JSNApi::DestroyJSVM(vm);
2444514f5e3Sopenharmony_ci    return ret ? ERR_OK : ERR_FAIL;
2454514f5e3Sopenharmony_ci}
2464514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu
2474514f5e3Sopenharmony_ci
2484514f5e3Sopenharmony_ciint main(const int argc, const char **argv)
2494514f5e3Sopenharmony_ci{
2504514f5e3Sopenharmony_ci    auto result = panda::ecmascript::kungfu::Main(argc, argv);
2514514f5e3Sopenharmony_ci    return result;
2524514f5e3Sopenharmony_ci}
253