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 "ecmascript/compiler/file_generators.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/common.h"
194514f5e3Sopenharmony_ci#include "ecmascript/compiler/aot_file/aot_file_manager.h"
204514f5e3Sopenharmony_ci#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
214514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
224514f5e3Sopenharmony_ci#include "ecmascript/platform/code_sign.h"
234514f5e3Sopenharmony_ci#include "ecmascript/platform/directory.h"
244514f5e3Sopenharmony_ci#include "ecmascript/platform/os.h"
254514f5e3Sopenharmony_ci#include "ecmascript/snapshot/mem/snapshot.h"
264514f5e3Sopenharmony_ci#include "ecmascript/stackmap/ark_stackmap_builder.h"
274514f5e3Sopenharmony_ci#include "ecmascript/stackmap/llvm/llvm_stackmap_parser.h"
284514f5e3Sopenharmony_ci#ifdef COMPILE_MAPLE
294514f5e3Sopenharmony_ci#include "ecmascript/compiler/codegen/maple/litecg_codegen.h"
304514f5e3Sopenharmony_ci#include "ecmascript/compiler/codegen/maple/litecg_ir_builder.h"
314514f5e3Sopenharmony_ci#include "ecmascript/compiler/codegen/maple/maple_be/include/litecg/litecg.h"
324514f5e3Sopenharmony_ci#include "ecmascript/stackmap/litecg/litecg_stackmap_type.h"
334514f5e3Sopenharmony_ci#ifdef JIT_ENABLE_CODE_SIGN
344514f5e3Sopenharmony_ci#include "ecmascript/compiler/jit_signcode.h"
354514f5e3Sopenharmony_ci#endif
364514f5e3Sopenharmony_ci#endif
374514f5e3Sopenharmony_ci#include "ecmascript/jit/jit.h"
384514f5e3Sopenharmony_ci#include "ecmascript/jit/jit_task.h"
394514f5e3Sopenharmony_ci#include "ecmascript/compiler/jit_compiler.h"
404514f5e3Sopenharmony_ci
414514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
424514f5e3Sopenharmony_civoid Module::CollectStackMapDes(ModuleSectionDes& des) const
434514f5e3Sopenharmony_ci{
444514f5e3Sopenharmony_ci    uint32_t stackmapSize = des.GetSecSize(ElfSecName::LLVM_STACKMAP);
454514f5e3Sopenharmony_ci    std::unique_ptr<uint8_t[]> stackmapPtr(std::make_unique<uint8_t[]>(stackmapSize));
464514f5e3Sopenharmony_ci    uint64_t addr = des.GetSecAddr(ElfSecName::LLVM_STACKMAP);
474514f5e3Sopenharmony_ci    if (addr == 0) { // assembler stub don't existed llvm stackmap
484514f5e3Sopenharmony_ci        return;
494514f5e3Sopenharmony_ci    }
504514f5e3Sopenharmony_ci    uint64_t textAddr = des.GetSecAddr(ElfSecName::TEXT);
514514f5e3Sopenharmony_ci    if (memcpy_s(stackmapPtr.get(), stackmapSize, reinterpret_cast<void *>(addr), stackmapSize) != EOK) {
524514f5e3Sopenharmony_ci        LOG_COMPILER(FATAL) << "memcpy_s failed";
534514f5e3Sopenharmony_ci        UNREACHABLE();
544514f5e3Sopenharmony_ci    }
554514f5e3Sopenharmony_ci    std::shared_ptr<uint8_t> ptr = nullptr;
564514f5e3Sopenharmony_ci    uint32_t size = 0;
574514f5e3Sopenharmony_ci    ArkStackMapBuilder builder;
584514f5e3Sopenharmony_ci    std::tie(ptr, size) = builder.Run(std::move(stackmapPtr), textAddr, irModule_->GetTriple());
594514f5e3Sopenharmony_ci    des.EraseSec(ElfSecName::LLVM_STACKMAP);
604514f5e3Sopenharmony_ci    des.SetArkStackMapPtr(ptr);
614514f5e3Sopenharmony_ci    des.SetArkStackMapSize(size);
624514f5e3Sopenharmony_ci}
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_civoid Module::CollectAnStackMapDes(ModuleSectionDes& des, uint64_t textOffset,
654514f5e3Sopenharmony_ci                                  CGStackMapInfo &stackMapInfo) const
664514f5e3Sopenharmony_ci{
674514f5e3Sopenharmony_ci#ifdef COMPILE_MAPLE
684514f5e3Sopenharmony_ci    if (!IsLLVM()) {
694514f5e3Sopenharmony_ci        static_cast<LiteCGAssembler*>(assembler_)->CollectAnStackMap(stackMapInfo);
704514f5e3Sopenharmony_ci        return;
714514f5e3Sopenharmony_ci    }
724514f5e3Sopenharmony_ci#endif
734514f5e3Sopenharmony_ci    uint32_t stackmapSize = des.GetSecSize(ElfSecName::LLVM_STACKMAP);
744514f5e3Sopenharmony_ci    std::unique_ptr<uint8_t[]> stackmapPtr(std::make_unique<uint8_t[]>(stackmapSize));
754514f5e3Sopenharmony_ci    uint64_t addr = des.GetSecAddr(ElfSecName::LLVM_STACKMAP);
764514f5e3Sopenharmony_ci    if (addr == 0) { // assembler stub don't existed llvm stackmap
774514f5e3Sopenharmony_ci        return;
784514f5e3Sopenharmony_ci    }
794514f5e3Sopenharmony_ci    uint64_t textAddr = des.GetSecAddr(ElfSecName::TEXT);
804514f5e3Sopenharmony_ci    if (memcpy_s(stackmapPtr.get(), stackmapSize, reinterpret_cast<void *>(addr), stackmapSize) != EOK) {
814514f5e3Sopenharmony_ci        LOG_COMPILER(FATAL) << "memcpy_s failed";
824514f5e3Sopenharmony_ci        UNREACHABLE();
834514f5e3Sopenharmony_ci    }
844514f5e3Sopenharmony_ci    ArkStackMapBuilder builder;
854514f5e3Sopenharmony_ci    builder.Collect(std::move(stackmapPtr), textAddr, textOffset, stackMapInfo);
864514f5e3Sopenharmony_ci    des.EraseSec(ElfSecName::LLVM_STACKMAP);
874514f5e3Sopenharmony_ci}
884514f5e3Sopenharmony_ci
894514f5e3Sopenharmony_cistd::vector<uintptr_t> Module::GetFuncEntryPoints()
904514f5e3Sopenharmony_ci{
914514f5e3Sopenharmony_ci    std::vector<uintptr_t> entrys;
924514f5e3Sopenharmony_ci    if (irModule_->GetModuleKind() != MODULE_LLVM) {
934514f5e3Sopenharmony_ci        std::cout << "GetFuncEntryPoints is not supported for litecg currently" << std::endl;
944514f5e3Sopenharmony_ci        return entrys;
954514f5e3Sopenharmony_ci    }
964514f5e3Sopenharmony_ci    LLVMModule *llvmModule = static_cast<LLVMModule *>(irModule_);
974514f5e3Sopenharmony_ci    LLVMAssembler *assembler = static_cast<LLVMAssembler *>(assembler_);
984514f5e3Sopenharmony_ci    auto engine = assembler->GetEngine();
994514f5e3Sopenharmony_ci
1004514f5e3Sopenharmony_ci    for (size_t j = 0; j < llvmModule->GetFuncCount(); j++) {
1014514f5e3Sopenharmony_ci        LLVMValueRef func = llvmModule->GetFunction(j);
1024514f5e3Sopenharmony_ci        ASSERT(func != nullptr);
1034514f5e3Sopenharmony_ci        uintptr_t entry = reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(engine, func));
1044514f5e3Sopenharmony_ci        entrys.push_back(entry);
1054514f5e3Sopenharmony_ci    }
1064514f5e3Sopenharmony_ci    return entrys;
1074514f5e3Sopenharmony_ci}
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_civoid Module::CollectFuncEntryInfo(const std::vector<uintptr_t>& entrys, std::map<uintptr_t, std::string> &addr2name,
1104514f5e3Sopenharmony_ci                                  StubFileInfo &stubInfo, uint32_t moduleIndex, const CompilerLog &log)
1114514f5e3Sopenharmony_ci{
1124514f5e3Sopenharmony_ci    LLVMModule *llvmModule = static_cast<LLVMModule*>(irModule_);
1134514f5e3Sopenharmony_ci    LLVMAssembler *assembler = static_cast<LLVMAssembler*>(assembler_);
1144514f5e3Sopenharmony_ci    auto codeBuff = assembler->GetSectionAddr(ElfSecName::TEXT);
1154514f5e3Sopenharmony_ci    auto callSigns = llvmModule->GetCSigns();
1164514f5e3Sopenharmony_ci    const size_t funcCount = entrys.size();
1174514f5e3Sopenharmony_ci    funcCount_ = funcCount;
1184514f5e3Sopenharmony_ci    startIndex_ = stubInfo.GetEntrySize();
1194514f5e3Sopenharmony_ci
1204514f5e3Sopenharmony_ci    for (size_t j = 0; j < funcCount; j++) {
1214514f5e3Sopenharmony_ci        auto cs = callSigns[j];
1224514f5e3Sopenharmony_ci        LLVMValueRef func = llvmModule->GetFunction(j);
1234514f5e3Sopenharmony_ci        ASSERT(func != nullptr);
1244514f5e3Sopenharmony_ci        int delta = assembler->GetFpDeltaPrevFramSp(func, log);
1254514f5e3Sopenharmony_ci        ASSERT(delta >= 0 && (delta % sizeof(uintptr_t) == 0));
1264514f5e3Sopenharmony_ci        uint32_t funcSize = 0;
1274514f5e3Sopenharmony_ci        if (j < funcCount - 1) {
1284514f5e3Sopenharmony_ci            funcSize = entrys[j + 1] - entrys[j];
1294514f5e3Sopenharmony_ci        } else {
1304514f5e3Sopenharmony_ci            funcSize = codeBuff + assembler->GetSectionSize(ElfSecName::TEXT) - entrys[j];
1314514f5e3Sopenharmony_ci        }
1324514f5e3Sopenharmony_ci        kungfu::CalleeRegAndOffsetVec info = assembler->GetCalleeReg2Offset(func, log);
1334514f5e3Sopenharmony_ci        stubInfo.AddEntry(cs->GetTargetKind(), false, false, cs->GetID(), entrys[j] - codeBuff,
1344514f5e3Sopenharmony_ci                          AOTFileManager::STUB_FILE_INDEX, moduleIndex, delta, funcSize, info);
1354514f5e3Sopenharmony_ci        ASSERT(!cs->GetName().empty());
1364514f5e3Sopenharmony_ci        addr2name[entrys[j]] = cs->GetName();
1374514f5e3Sopenharmony_ci    }
1384514f5e3Sopenharmony_ci}
1394514f5e3Sopenharmony_ci
1404514f5e3Sopenharmony_civoid Module::CollectFuncEntryInfo(std::map<uintptr_t, std::string> &addr2name, AnFileInfo &aotInfo, uint32_t fileIndex,
1414514f5e3Sopenharmony_ci                                  uint32_t moduleIndex, const CompilerLog &log)
1424514f5e3Sopenharmony_ci{
1434514f5e3Sopenharmony_ci#ifdef COMPILE_MAPLE
1444514f5e3Sopenharmony_ci    if (irModule_->GetModuleKind() != MODULE_LLVM) {
1454514f5e3Sopenharmony_ci        CollectFuncEntryInfoByLiteCG(addr2name, aotInfo, fileIndex, moduleIndex);
1464514f5e3Sopenharmony_ci        return;
1474514f5e3Sopenharmony_ci    }
1484514f5e3Sopenharmony_ci#endif
1494514f5e3Sopenharmony_ci    LLVMAssembler *assembler = static_cast<LLVMAssembler*>(assembler_);
1504514f5e3Sopenharmony_ci    auto engine = assembler->GetEngine();
1514514f5e3Sopenharmony_ci    std::vector<std::tuple<uint64_t, size_t, int, bool>> funcInfo; // entry idx delta
1524514f5e3Sopenharmony_ci    std::vector<kungfu::CalleeRegAndOffsetVec> calleeSaveRegisters; // entry idx delta
1534514f5e3Sopenharmony_ci    // 1.Compile all functions and collect function infos
1544514f5e3Sopenharmony_ci    LLVMModule *llvmModule = static_cast<LLVMModule*>(irModule_);
1554514f5e3Sopenharmony_ci    llvmModule->IteratefuncIndexMap([&](size_t idx, LLVMValueRef func, bool isFastCall) {
1564514f5e3Sopenharmony_ci        uint64_t funcEntry = reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(engine, func));
1574514f5e3Sopenharmony_ci        uint64_t length = 0;
1584514f5e3Sopenharmony_ci        std::string funcName(LLVMGetValueName2(func, reinterpret_cast<size_t *>(&length)));
1594514f5e3Sopenharmony_ci        ASSERT(length != 0);
1604514f5e3Sopenharmony_ci        addr2name[funcEntry] = funcName;
1614514f5e3Sopenharmony_ci        int delta = assembler->GetFpDeltaPrevFramSp(func, log);
1624514f5e3Sopenharmony_ci        ASSERT(delta >= 0 && (delta % sizeof(uintptr_t) == 0));
1634514f5e3Sopenharmony_ci        funcInfo.emplace_back(std::tuple(funcEntry, idx, delta, isFastCall));
1644514f5e3Sopenharmony_ci        kungfu::CalleeRegAndOffsetVec info = assembler->GetCalleeReg2Offset(func, log);
1654514f5e3Sopenharmony_ci        calleeSaveRegisters.emplace_back(info);
1664514f5e3Sopenharmony_ci    });
1674514f5e3Sopenharmony_ci    // 2.After all functions compiled, the module sections would be fixed
1684514f5e3Sopenharmony_ci    uintptr_t textAddr = GetTextAddr();
1694514f5e3Sopenharmony_ci    uint32_t textSize = GetTextSize();
1704514f5e3Sopenharmony_ci    uintptr_t rodataAddrBeforeText = 0;
1714514f5e3Sopenharmony_ci    uint32_t rodataSizeBeforeText = 0;
1724514f5e3Sopenharmony_ci    uintptr_t rodataAddrAfterText = 0;
1734514f5e3Sopenharmony_ci    uint32_t rodataSizeAfterText = 0;
1744514f5e3Sopenharmony_ci    std::tie(rodataAddrBeforeText, rodataSizeBeforeText, rodataAddrAfterText, rodataSizeAfterText) =
1754514f5e3Sopenharmony_ci        GetMergedRODataAddrAndSize(textAddr);
1764514f5e3Sopenharmony_ci    aotInfo.AlignTextSec(AOTFileInfo::PAGE_ALIGN);
1774514f5e3Sopenharmony_ci    if (rodataSizeBeforeText != 0) {
1784514f5e3Sopenharmony_ci        aotInfo.UpdateCurTextSecOffset(rodataSizeBeforeText);
1794514f5e3Sopenharmony_ci        aotInfo.AlignTextSec(AOTFileInfo::TEXT_SEC_ALIGN);
1804514f5e3Sopenharmony_ci    }
1814514f5e3Sopenharmony_ci
1824514f5e3Sopenharmony_ci    const size_t funcCount = funcInfo.size();
1834514f5e3Sopenharmony_ci    funcCount_ = funcCount;
1844514f5e3Sopenharmony_ci    startIndex_ = aotInfo.GetEntrySize();
1854514f5e3Sopenharmony_ci    // 3.Add function entries based on the module sections
1864514f5e3Sopenharmony_ci    for (size_t i = 0; i < funcInfo.size(); i++) {
1874514f5e3Sopenharmony_ci        uint64_t funcEntry;
1884514f5e3Sopenharmony_ci        size_t idx;
1894514f5e3Sopenharmony_ci        int delta;
1904514f5e3Sopenharmony_ci        bool isFastCall;
1914514f5e3Sopenharmony_ci        uint32_t funcSize;
1924514f5e3Sopenharmony_ci        std::tie(funcEntry, idx, delta, isFastCall) = funcInfo[i];
1934514f5e3Sopenharmony_ci        if (i < funcCount - 1) {
1944514f5e3Sopenharmony_ci            funcSize = std::get<0>(funcInfo[i + 1]) - funcEntry;
1954514f5e3Sopenharmony_ci        } else {
1964514f5e3Sopenharmony_ci            funcSize = textAddr + textSize - funcEntry;
1974514f5e3Sopenharmony_ci        }
1984514f5e3Sopenharmony_ci        auto found = addr2name[funcEntry].find(panda::ecmascript::JSPandaFile::ENTRY_FUNCTION_NAME);
1994514f5e3Sopenharmony_ci        bool isMainFunc = found != std::string::npos;
2004514f5e3Sopenharmony_ci        uint64_t offset = funcEntry - textAddr + aotInfo.GetCurTextSecOffset();
2014514f5e3Sopenharmony_ci        aotInfo.AddEntry(CallSignature::TargetKind::JSFUNCTION, isMainFunc, isFastCall, idx,
2024514f5e3Sopenharmony_ci                         offset, fileIndex, moduleIndex, delta, funcSize, calleeSaveRegisters[i]);
2034514f5e3Sopenharmony_ci    }
2044514f5e3Sopenharmony_ci    aotInfo.UpdateCurTextSecOffset(textSize);
2054514f5e3Sopenharmony_ci    if (rodataSizeAfterText != 0) {
2064514f5e3Sopenharmony_ci        aotInfo.AlignTextSec(AOTFileInfo::DATA_SEC_ALIGN);
2074514f5e3Sopenharmony_ci        aotInfo.UpdateCurTextSecOffset(rodataSizeAfterText);
2084514f5e3Sopenharmony_ci    }
2094514f5e3Sopenharmony_ci}
2104514f5e3Sopenharmony_ci
2114514f5e3Sopenharmony_ci#ifdef COMPILE_MAPLE
2124514f5e3Sopenharmony_civoid Module::CollectFuncEntryInfoByLiteCG(std::map<uintptr_t, std::string> &addr2name, AnFileInfo &aotInfo,
2134514f5e3Sopenharmony_ci                                          uint32_t fileIndex, uint32_t moduleIndex)
2144514f5e3Sopenharmony_ci{
2154514f5e3Sopenharmony_ci    std::vector<std::tuple<uint64_t, size_t, int, bool>> funcInfo; // entry idx delta
2164514f5e3Sopenharmony_ci    std::vector<kungfu::CalleeRegAndOffsetVec> calleeSaveRegisters; // entry idx delta
2174514f5e3Sopenharmony_ci    // 1.Compile all functions and collect function infos
2184514f5e3Sopenharmony_ci    LMIRModule *lmirModule = static_cast<LMIRModule*>(irModule_);
2194514f5e3Sopenharmony_ci    LiteCGAssembler *assembler = static_cast<LiteCGAssembler*>(assembler_);
2204514f5e3Sopenharmony_ci    const auto &func2Addr = assembler->GetCodeInfo().GetFuncInfos();
2214514f5e3Sopenharmony_ci    lmirModule->IteratefuncIndexMap([&](size_t idx, std::string funcName, bool isFastCall) {
2224514f5e3Sopenharmony_ci        auto itr = func2Addr.find(funcName);
2234514f5e3Sopenharmony_ci        if (itr == func2Addr.end()) {
2244514f5e3Sopenharmony_ci            LOG_COMPILER(FATAL) << "get function address from emitter failed";
2254514f5e3Sopenharmony_ci            UNREACHABLE();
2264514f5e3Sopenharmony_ci        }
2274514f5e3Sopenharmony_ci        uint64_t funcEntry = itr->second.addr;
2284514f5e3Sopenharmony_ci        addr2name[funcEntry] = funcName;
2294514f5e3Sopenharmony_ci        int delta = itr->second.fp2PrevFrameSpDelta;
2304514f5e3Sopenharmony_ci        ASSERT(delta >= 0 && (delta % sizeof(uintptr_t) == 0));
2314514f5e3Sopenharmony_ci        funcInfo.emplace_back(std::tuple(funcEntry, idx, delta, isFastCall));
2324514f5e3Sopenharmony_ci        kungfu::CalleeRegAndOffsetVec info = itr->second.calleeRegInfo;
2334514f5e3Sopenharmony_ci        calleeSaveRegisters.emplace_back(info);
2344514f5e3Sopenharmony_ci    });
2354514f5e3Sopenharmony_ci    // 2.After all functions compiled, the module sections would be fixed
2364514f5e3Sopenharmony_ci    uint32_t textSize = GetTextSize();
2374514f5e3Sopenharmony_ci    uint32_t rodataSizeBeforeText = 0;
2384514f5e3Sopenharmony_ci    uint32_t rodataSizeAfterText = 0;
2394514f5e3Sopenharmony_ci
2404514f5e3Sopenharmony_ci    aotInfo.AlignTextSec(AOTFileInfo::PAGE_ALIGN);
2414514f5e3Sopenharmony_ci    if (rodataSizeBeforeText != 0) {
2424514f5e3Sopenharmony_ci        aotInfo.UpdateCurTextSecOffset(rodataSizeBeforeText);
2434514f5e3Sopenharmony_ci        aotInfo.AlignTextSec(AOTFileInfo::TEXT_SEC_ALIGN);
2444514f5e3Sopenharmony_ci    }
2454514f5e3Sopenharmony_ci
2464514f5e3Sopenharmony_ci    const size_t funcCount = funcInfo.size();
2474514f5e3Sopenharmony_ci    funcCount_ = funcCount;
2484514f5e3Sopenharmony_ci    startIndex_ = aotInfo.GetEntrySize();
2494514f5e3Sopenharmony_ci    // 3.Add function entries based on the module sections
2504514f5e3Sopenharmony_ci    for (size_t i = 0; i < funcInfo.size(); i++) {
2514514f5e3Sopenharmony_ci        uint64_t funcEntry = 0;
2524514f5e3Sopenharmony_ci        size_t idx;
2534514f5e3Sopenharmony_ci        int delta;
2544514f5e3Sopenharmony_ci        bool isFastCall;
2554514f5e3Sopenharmony_ci        uint32_t funcSize;
2564514f5e3Sopenharmony_ci        std::tie(funcEntry, idx, delta, isFastCall) = funcInfo[i];
2574514f5e3Sopenharmony_ci        if (i < funcCount - 1) {
2584514f5e3Sopenharmony_ci            funcSize = std::get<0>(funcInfo[i + 1]) - funcEntry;
2594514f5e3Sopenharmony_ci        } else {
2604514f5e3Sopenharmony_ci            funcSize = textSize - funcEntry;
2614514f5e3Sopenharmony_ci        }
2624514f5e3Sopenharmony_ci        auto found = addr2name[funcEntry].find(panda::ecmascript::JSPandaFile::ENTRY_FUNCTION_NAME);
2634514f5e3Sopenharmony_ci        bool isMainFunc = found != std::string::npos;
2644514f5e3Sopenharmony_ci        uint64_t offset = funcEntry;
2654514f5e3Sopenharmony_ci        aotInfo.AddEntry(CallSignature::TargetKind::JSFUNCTION, isMainFunc, isFastCall, idx,
2664514f5e3Sopenharmony_ci                         offset, fileIndex, moduleIndex, delta, funcSize, calleeSaveRegisters[i]);
2674514f5e3Sopenharmony_ci    }
2684514f5e3Sopenharmony_ci    aotInfo.UpdateCurTextSecOffset(textSize);
2694514f5e3Sopenharmony_ci    if (rodataSizeAfterText != 0) {
2704514f5e3Sopenharmony_ci        aotInfo.AlignTextSec(AOTFileInfo::DATA_SEC_ALIGN);
2714514f5e3Sopenharmony_ci        aotInfo.UpdateCurTextSecOffset(rodataSizeAfterText);
2724514f5e3Sopenharmony_ci    }
2734514f5e3Sopenharmony_ci}
2744514f5e3Sopenharmony_ci#endif
2754514f5e3Sopenharmony_ci
2764514f5e3Sopenharmony_civoid Module::CollectModuleSectionDes(ModuleSectionDes &moduleDes) const
2774514f5e3Sopenharmony_ci{
2784514f5e3Sopenharmony_ci    if (irModule_->GetModuleKind() != MODULE_LLVM) {
2794514f5e3Sopenharmony_ci        std::cout << "CollectModuleSectionDes is not supported for litecg currently" << std::endl;
2804514f5e3Sopenharmony_ci        return;
2814514f5e3Sopenharmony_ci    }
2824514f5e3Sopenharmony_ci    ASSERT(assembler_ != nullptr);
2834514f5e3Sopenharmony_ci    LLVMAssembler *assembler = static_cast<LLVMAssembler*>(assembler_);
2844514f5e3Sopenharmony_ci    assembler->IterateSecInfos([&](size_t i, std::pair<uint8_t *, size_t> secInfo) {
2854514f5e3Sopenharmony_ci        auto curSec = ElfSection(i);
2864514f5e3Sopenharmony_ci        ElfSecName sec = curSec.GetElfEnumValue();
2874514f5e3Sopenharmony_ci        if (IsRelaSection(sec)) {
2884514f5e3Sopenharmony_ci            moduleDes.EraseSec(sec);
2894514f5e3Sopenharmony_ci        } else { // aot need relocated; stub don't need collect relocated section
2904514f5e3Sopenharmony_ci            moduleDes.SetSecAddrAndSize(sec, reinterpret_cast<uint64_t>(secInfo.first), secInfo.second);
2914514f5e3Sopenharmony_ci            moduleDes.SetStartIndex(startIndex_);
2924514f5e3Sopenharmony_ci            moduleDes.SetFuncCount(funcCount_);
2934514f5e3Sopenharmony_ci        }
2944514f5e3Sopenharmony_ci    });
2954514f5e3Sopenharmony_ci    CollectStackMapDes(moduleDes);
2964514f5e3Sopenharmony_ci}
2974514f5e3Sopenharmony_ci
2984514f5e3Sopenharmony_civoid Module::CollectAnModuleSectionDes(ModuleSectionDes &moduleDes, uint64_t textOffset,
2994514f5e3Sopenharmony_ci                                       CGStackMapInfo &stackMapInfo) const
3004514f5e3Sopenharmony_ci{
3014514f5e3Sopenharmony_ci    ASSERT(assembler_ != nullptr);
3024514f5e3Sopenharmony_ci    assembler_->IterateSecInfos([&](size_t i, std::pair<uint8_t *, size_t> secInfo) {
3034514f5e3Sopenharmony_ci        auto curSec = ElfSection(i);
3044514f5e3Sopenharmony_ci        ElfSecName sec = curSec.GetElfEnumValue();
3054514f5e3Sopenharmony_ci        // aot need relocated; stub don't need collect relocated section
3064514f5e3Sopenharmony_ci        moduleDes.SetSecAddrAndSize(sec, reinterpret_cast<uint64_t>(secInfo.first), secInfo.second);
3074514f5e3Sopenharmony_ci        moduleDes.SetStartIndex(startIndex_);
3084514f5e3Sopenharmony_ci        moduleDes.SetFuncCount(funcCount_);
3094514f5e3Sopenharmony_ci    });
3104514f5e3Sopenharmony_ci    CollectAnStackMapDes(moduleDes, textOffset, stackMapInfo);
3114514f5e3Sopenharmony_ci}
3124514f5e3Sopenharmony_ci
3134514f5e3Sopenharmony_ciuint32_t Module::GetSectionSize(ElfSecName sec) const
3144514f5e3Sopenharmony_ci{
3154514f5e3Sopenharmony_ci    return assembler_->GetSectionSize(sec);
3164514f5e3Sopenharmony_ci}
3174514f5e3Sopenharmony_ci
3184514f5e3Sopenharmony_ciuintptr_t Module::GetSectionAddr(ElfSecName sec) const
3194514f5e3Sopenharmony_ci{
3204514f5e3Sopenharmony_ci    return assembler_->GetSectionAddr(sec);
3214514f5e3Sopenharmony_ci}
3224514f5e3Sopenharmony_ci
3234514f5e3Sopenharmony_civoid Module::RunAssembler(const CompilerLog &log, bool fastCompileMode, bool isJit)
3244514f5e3Sopenharmony_ci{
3254514f5e3Sopenharmony_ci    assembler_->Run(log, fastCompileMode, isJit);
3264514f5e3Sopenharmony_ci}
3274514f5e3Sopenharmony_ci
3284514f5e3Sopenharmony_civoid Module::DisassemblerFunc(std::map<uintptr_t, std::string> &addr2name, uint64_t textOffset,
3294514f5e3Sopenharmony_ci                              const CompilerLog &log, const MethodLogList &logList, std::ostringstream &codeStream)
3304514f5e3Sopenharmony_ci{
3314514f5e3Sopenharmony_ci    if (irModule_->GetModuleKind() != MODULE_LLVM) {
3324514f5e3Sopenharmony_ci        std::cout << "DisassemblerFunc is not supported for litecg currently" << std::endl;
3334514f5e3Sopenharmony_ci        return;
3344514f5e3Sopenharmony_ci    }
3354514f5e3Sopenharmony_ci    auto *assembler = static_cast<LLVMAssembler*>(assembler_);
3364514f5e3Sopenharmony_ci    assembler->Disassemble(addr2name, textOffset, log, logList, codeStream);
3374514f5e3Sopenharmony_ci}
3384514f5e3Sopenharmony_ci
3394514f5e3Sopenharmony_civoid Module::DestroyModule()
3404514f5e3Sopenharmony_ci{
3414514f5e3Sopenharmony_ci    if (irModule_ != nullptr) {
3424514f5e3Sopenharmony_ci        delete irModule_;
3434514f5e3Sopenharmony_ci        irModule_ = nullptr;
3444514f5e3Sopenharmony_ci    }
3454514f5e3Sopenharmony_ci    if (assembler_ != nullptr) {
3464514f5e3Sopenharmony_ci        delete assembler_;
3474514f5e3Sopenharmony_ci        assembler_ = nullptr;
3484514f5e3Sopenharmony_ci    }
3494514f5e3Sopenharmony_ci}
3504514f5e3Sopenharmony_ci
3514514f5e3Sopenharmony_civoid StubFileGenerator::CollectAsmStubCodeInfo(std::map<uintptr_t, std::string> &addr2name, uint32_t bridgeModuleIdx)
3524514f5e3Sopenharmony_ci{
3534514f5e3Sopenharmony_ci    uint32_t funSize = 0;
3544514f5e3Sopenharmony_ci    for (size_t i = 0; i < asmModule_.GetFunctionCount(); i++) {
3554514f5e3Sopenharmony_ci        auto cs = asmModule_.GetCSign(i);
3564514f5e3Sopenharmony_ci        auto entryOffset = asmModule_.GetFunction(cs->GetID());
3574514f5e3Sopenharmony_ci        if (i < asmModule_.GetFunctionCount() - 1) {
3584514f5e3Sopenharmony_ci            auto nextcs = asmModule_.GetCSign(i + 1);
3594514f5e3Sopenharmony_ci            funSize = asmModule_.GetFunction(nextcs->GetID()) - entryOffset;
3604514f5e3Sopenharmony_ci        } else {
3614514f5e3Sopenharmony_ci            funSize = asmModule_.GetBufferSize() - entryOffset;
3624514f5e3Sopenharmony_ci        }
3634514f5e3Sopenharmony_ci        stubInfo_.AddEntry(cs->GetTargetKind(), false, false, cs->GetID(), entryOffset,
3644514f5e3Sopenharmony_ci                           AOTFileManager::STUB_FILE_INDEX, bridgeModuleIdx, 0, funSize);
3654514f5e3Sopenharmony_ci        ASSERT(!cs->GetName().empty());
3664514f5e3Sopenharmony_ci        addr2name[entryOffset] = cs->GetName();
3674514f5e3Sopenharmony_ci    }
3684514f5e3Sopenharmony_ci}
3694514f5e3Sopenharmony_ci
3704514f5e3Sopenharmony_civoid StubFileGenerator::CollectCodeInfo()
3714514f5e3Sopenharmony_ci{
3724514f5e3Sopenharmony_ci    std::map<uintptr_t, std::string> stubAddr2Name;
3734514f5e3Sopenharmony_ci    std::vector<std::vector<uintptr_t>> entryPoints(modulePackage_.size());
3744514f5e3Sopenharmony_ci
3754514f5e3Sopenharmony_ci    if (!concurrentCompile_) {
3764514f5e3Sopenharmony_ci        for (size_t i = 0; i < modulePackage_.size(); ++i) {
3774514f5e3Sopenharmony_ci            entryPoints[i] = modulePackage_[i].GetFuncEntryPoints();
3784514f5e3Sopenharmony_ci        }
3794514f5e3Sopenharmony_ci    } else if (!modulePackage_.empty()) {
3804514f5e3Sopenharmony_ci        // For first module, run it in current thread.
3814514f5e3Sopenharmony_ci        // For others, run them in child threads and wait for finish.
3824514f5e3Sopenharmony_ci        std::vector<std::thread> threads;
3834514f5e3Sopenharmony_ci        for (size_t i = 1; i < modulePackage_.size(); ++i) {
3844514f5e3Sopenharmony_ci            threads.emplace_back([&, i]() {
3854514f5e3Sopenharmony_ci                entryPoints[i] = modulePackage_[i].GetFuncEntryPoints();
3864514f5e3Sopenharmony_ci            });
3874514f5e3Sopenharmony_ci        }
3884514f5e3Sopenharmony_ci        entryPoints[0] = modulePackage_[0].GetFuncEntryPoints();
3894514f5e3Sopenharmony_ci        for (auto& t : threads) {
3904514f5e3Sopenharmony_ci            if (t.joinable()) {
3914514f5e3Sopenharmony_ci                t.join();
3924514f5e3Sopenharmony_ci            }
3934514f5e3Sopenharmony_ci        }
3944514f5e3Sopenharmony_ci    }
3954514f5e3Sopenharmony_ci
3964514f5e3Sopenharmony_ci    for (size_t i = 0; i < modulePackage_.size(); ++i) {
3974514f5e3Sopenharmony_ci        modulePackage_[i].CollectFuncEntryInfo(entryPoints[i], stubAddr2Name, stubInfo_, i, GetLog());
3984514f5e3Sopenharmony_ci        ModuleSectionDes des;
3994514f5e3Sopenharmony_ci        modulePackage_[i].CollectModuleSectionDes(des);
4004514f5e3Sopenharmony_ci        stubInfo_.AddModuleDes(des);
4014514f5e3Sopenharmony_ci    }
4024514f5e3Sopenharmony_ci    std::map<uintptr_t, std::string> asmAddr2Name;
4034514f5e3Sopenharmony_ci    // idx for bridge module is the one after last module in modulePackage
4044514f5e3Sopenharmony_ci    CollectAsmStubCodeInfo(asmAddr2Name, modulePackage_.size());
4054514f5e3Sopenharmony_ci    if (log_->OutputASM()) {
4064514f5e3Sopenharmony_ci        DisassembleAsmStubs(asmAddr2Name);
4074514f5e3Sopenharmony_ci        DisassembleEachFunc(stubAddr2Name);
4084514f5e3Sopenharmony_ci    }
4094514f5e3Sopenharmony_ci}
4104514f5e3Sopenharmony_ci
4114514f5e3Sopenharmony_civoid StubFileGenerator::DisassembleAsmStubs(std::map<uintptr_t, std::string> &addr2name)
4124514f5e3Sopenharmony_ci{
4134514f5e3Sopenharmony_ci    std::string tri = cfg_.GetTripleStr();
4144514f5e3Sopenharmony_ci    uint8_t *buf = reinterpret_cast<uint8_t*>(stubInfo_.GetAsmStubAddr());
4154514f5e3Sopenharmony_ci    size_t size = stubInfo_.GetAsmStubSize();
4164514f5e3Sopenharmony_ci    LLVMAssembler::Disassemble(&addr2name, tri, buf, size);
4174514f5e3Sopenharmony_ci}
4184514f5e3Sopenharmony_ci
4194514f5e3Sopenharmony_ciuint64_t AOTFileGenerator::RollbackTextSize(Module *module)
4204514f5e3Sopenharmony_ci{
4214514f5e3Sopenharmony_ci    uint64_t textAddr = module->GetSectionAddr(ElfSecName::TEXT);
4224514f5e3Sopenharmony_ci    uint32_t textSize = module->GetSectionSize(ElfSecName::TEXT);
4234514f5e3Sopenharmony_ci    uint64_t rodataAddrBeforeText = 0;
4244514f5e3Sopenharmony_ci    uint32_t rodataSizeBeforeText = 0;
4254514f5e3Sopenharmony_ci    uint64_t rodataAddrAfterText = 0;
4264514f5e3Sopenharmony_ci    uint32_t rodataSizeAfterText = 0;
4274514f5e3Sopenharmony_ci    if (module->IsLLVM()) {
4284514f5e3Sopenharmony_ci        // In llvm the ro section is separated from the text section, but these all in text section in LiteCG.
4294514f5e3Sopenharmony_ci        std::tie(rodataAddrBeforeText, rodataSizeBeforeText, rodataAddrAfterText, rodataSizeAfterText) =
4304514f5e3Sopenharmony_ci            module->GetMergedRODataAddrAndSize(textAddr);
4314514f5e3Sopenharmony_ci    }
4324514f5e3Sopenharmony_ci    uint64_t textStart = 0;
4334514f5e3Sopenharmony_ci    if (rodataSizeAfterText == 0) {
4344514f5e3Sopenharmony_ci        textStart = aotInfo_.GetCurTextSecOffset() - textSize;
4354514f5e3Sopenharmony_ci    } else {
4364514f5e3Sopenharmony_ci        textStart = aotInfo_.GetCurTextSecOffset() - textSize - rodataSizeAfterText;
4374514f5e3Sopenharmony_ci        textStart = AlignDown(textStart, AOTFileInfo::DATA_SEC_ALIGN);
4384514f5e3Sopenharmony_ci    }
4394514f5e3Sopenharmony_ci    return textStart;
4404514f5e3Sopenharmony_ci}
4414514f5e3Sopenharmony_ci
4424514f5e3Sopenharmony_civoid AOTFileGenerator::CollectCodeInfo(Module *module, uint32_t moduleIdx)
4434514f5e3Sopenharmony_ci{
4444514f5e3Sopenharmony_ci    std::map<uintptr_t, std::string> addr2name;
4454514f5e3Sopenharmony_ci    uint32_t lastEntryIdx = aotInfo_.GetEntrySize();
4464514f5e3Sopenharmony_ci    pgo::ApEntityId abcId = INVALID_INDEX;
4474514f5e3Sopenharmony_ci    pgo::PGOProfilerManager::GetInstance()->GetPandaFileId(curCompileFileName_.c_str(), abcId);
4484514f5e3Sopenharmony_ci    module->CollectFuncEntryInfo(addr2name, aotInfo_, abcId, moduleIdx, GetLog());
4494514f5e3Sopenharmony_ci    aotInfo_.MappingEntryFuncsToAbcFiles(curCompileFileName_, lastEntryIdx, aotInfo_.GetEntrySize());
4504514f5e3Sopenharmony_ci    ModuleSectionDes des;
4514514f5e3Sopenharmony_ci    uint64_t textOffset = RollbackTextSize(module);
4524514f5e3Sopenharmony_ci    if (stackMapInfo_ == nullptr) {
4534514f5e3Sopenharmony_ci        LOG_ECMA(FATAL) << "stackMapInfo_ isn't be initialized";
4544514f5e3Sopenharmony_ci        UNREACHABLE();
4554514f5e3Sopenharmony_ci    }
4564514f5e3Sopenharmony_ci    module->CollectAnModuleSectionDes(des, textOffset, *stackMapInfo_);
4574514f5e3Sopenharmony_ci
4584514f5e3Sopenharmony_ci    aotInfo_.AddModuleDes(des);
4594514f5e3Sopenharmony_ci    if (module->IsLLVM() && log_->OutputASM()) {
4604514f5e3Sopenharmony_ci        module->DisassemblerFunc(addr2name, textOffset, *(log_), *(logList_), codeStream_);
4614514f5e3Sopenharmony_ci    }
4624514f5e3Sopenharmony_ci}
4634514f5e3Sopenharmony_ci
4644514f5e3Sopenharmony_ciModule* AOTFileGenerator::GetLatestModule()
4654514f5e3Sopenharmony_ci{
4664514f5e3Sopenharmony_ci    return &modulePackage_.back();
4674514f5e3Sopenharmony_ci}
4684514f5e3Sopenharmony_ci
4694514f5e3Sopenharmony_ciuint32_t AOTFileGenerator::GetModuleVecSize() const
4704514f5e3Sopenharmony_ci{
4714514f5e3Sopenharmony_ci    return modulePackage_.size();
4724514f5e3Sopenharmony_ci}
4734514f5e3Sopenharmony_ci
4744514f5e3Sopenharmony_ciModule* AOTFileGenerator::AddModule(const std::string &name, const std::string &triple,
4754514f5e3Sopenharmony_ci                                    [[maybe_unused]] LOptions option, bool logDebug, [[maybe_unused]] bool isJit)
4764514f5e3Sopenharmony_ci{
4774514f5e3Sopenharmony_ci#ifdef COMPILE_MAPLE
4784514f5e3Sopenharmony_ci    if (useLiteCG_) {
4794514f5e3Sopenharmony_ci        LMIRModule *irModule = new LMIRModule(compilationEnv_->GetNativeAreaAllocator(), name, logDebug, triple, isJit);
4804514f5e3Sopenharmony_ci        LiteCGAssembler *ass = new LiteCGAssembler(*irModule, jitCodeSpace_,
4814514f5e3Sopenharmony_ci            compilationEnv_->GetJSOptions().GetCompilerCodegenOptions());
4824514f5e3Sopenharmony_ci        modulePackage_.emplace_back(Module(irModule, ass));
4834514f5e3Sopenharmony_ci        if (stackMapInfo_ == nullptr) {
4844514f5e3Sopenharmony_ci            stackMapInfo_ = new LiteCGStackMapInfo();
4854514f5e3Sopenharmony_ci        }
4864514f5e3Sopenharmony_ci        return &modulePackage_.back();
4874514f5e3Sopenharmony_ci    }
4884514f5e3Sopenharmony_ci#endif
4894514f5e3Sopenharmony_ci    LLVMModule *m = new LLVMModule(compilationEnv_->GetNativeAreaAllocator(), name, logDebug, triple);
4904514f5e3Sopenharmony_ci    LLVMAssembler *ass = new LLVMAssembler(m, jitCodeSpace_, option);
4914514f5e3Sopenharmony_ci    modulePackage_.emplace_back(Module(m, ass));
4924514f5e3Sopenharmony_ci    if (stackMapInfo_ == nullptr) {
4934514f5e3Sopenharmony_ci        stackMapInfo_ = new LLVMStackMapInfo();
4944514f5e3Sopenharmony_ci    }
4954514f5e3Sopenharmony_ci    return &modulePackage_.back();
4964514f5e3Sopenharmony_ci}
4974514f5e3Sopenharmony_ci
4984514f5e3Sopenharmony_ciModule* StubFileGenerator::AddModule(NativeAreaAllocator *allocator, const std::string &name, const std::string &triple,
4994514f5e3Sopenharmony_ci                                     LOptions option, bool logDebug, StubFileKind kind)
5004514f5e3Sopenharmony_ci{
5014514f5e3Sopenharmony_ci    LLVMModule* m = new LLVMModule(allocator, name, logDebug, triple);
5024514f5e3Sopenharmony_ci    switch (kind) {
5034514f5e3Sopenharmony_ci        case StubFileKind::BC:
5044514f5e3Sopenharmony_ci            m->SetUpForBytecodeHandlerStubs();
5054514f5e3Sopenharmony_ci            break;
5064514f5e3Sopenharmony_ci        case StubFileKind::COM:
5074514f5e3Sopenharmony_ci            m->SetUpForCommonStubs();
5084514f5e3Sopenharmony_ci            break;
5094514f5e3Sopenharmony_ci        case StubFileKind::BUILTIN:
5104514f5e3Sopenharmony_ci            m->SetUpForBuiltinsStubs();
5114514f5e3Sopenharmony_ci            break;
5124514f5e3Sopenharmony_ci        case StubFileKind::BASELINE:
5134514f5e3Sopenharmony_ci            m->SetUpForBaselineStubs();
5144514f5e3Sopenharmony_ci            break;
5154514f5e3Sopenharmony_ci        default:
5164514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "unsupported stub file kind";
5174514f5e3Sopenharmony_ci            UNREACHABLE();
5184514f5e3Sopenharmony_ci            break;
5194514f5e3Sopenharmony_ci    }
5204514f5e3Sopenharmony_ci    LLVMAssembler* ass = new LLVMAssembler(m, jitCodeSpace_, option);
5214514f5e3Sopenharmony_ci    modulePackage_.emplace_back(Module(m, ass));
5224514f5e3Sopenharmony_ci    return &modulePackage_.back();
5234514f5e3Sopenharmony_ci}
5244514f5e3Sopenharmony_ci
5254514f5e3Sopenharmony_civoid StubFileGenerator::RunLLVMAssembler()
5264514f5e3Sopenharmony_ci{
5274514f5e3Sopenharmony_ci    if (!concurrentCompile_) {
5284514f5e3Sopenharmony_ci        for (auto &m: modulePackage_) {
5294514f5e3Sopenharmony_ci            m.RunAssembler(*(this->log_), false);
5304514f5e3Sopenharmony_ci        }
5314514f5e3Sopenharmony_ci    } else if (!modulePackage_.empty()) {
5324514f5e3Sopenharmony_ci        // For first module, run it in current thread.
5334514f5e3Sopenharmony_ci        // For others, run them in child threads and wait for finish.
5344514f5e3Sopenharmony_ci        std::vector<std::thread> threads;
5354514f5e3Sopenharmony_ci        for (size_t i = 1; i < modulePackage_.size(); ++i) {
5364514f5e3Sopenharmony_ci            const CompilerLog &log = *(this->log_);
5374514f5e3Sopenharmony_ci            threads.emplace_back([&, i] {
5384514f5e3Sopenharmony_ci                modulePackage_[i].RunAssembler(log, false);
5394514f5e3Sopenharmony_ci            });
5404514f5e3Sopenharmony_ci        }
5414514f5e3Sopenharmony_ci        modulePackage_[0].RunAssembler(*(this->log_), false);
5424514f5e3Sopenharmony_ci        for (auto& t : threads) {
5434514f5e3Sopenharmony_ci            if (t.joinable()) {
5444514f5e3Sopenharmony_ci                t.join();
5454514f5e3Sopenharmony_ci            }
5464514f5e3Sopenharmony_ci        }
5474514f5e3Sopenharmony_ci    }
5484514f5e3Sopenharmony_ci}
5494514f5e3Sopenharmony_ci
5504514f5e3Sopenharmony_civoid StubFileGenerator::RunAsmAssembler()
5514514f5e3Sopenharmony_ci{
5524514f5e3Sopenharmony_ci    NativeAreaAllocator allocator;
5534514f5e3Sopenharmony_ci    Chunk chunk(&allocator);
5544514f5e3Sopenharmony_ci    asmModule_.Run(&cfg_, &chunk);
5554514f5e3Sopenharmony_ci
5564514f5e3Sopenharmony_ci    auto buffer = asmModule_.GetBuffer();
5574514f5e3Sopenharmony_ci    auto bufferSize = asmModule_.GetBufferSize();
5584514f5e3Sopenharmony_ci    if (bufferSize == 0U) {
5594514f5e3Sopenharmony_ci        return;
5604514f5e3Sopenharmony_ci    }
5614514f5e3Sopenharmony_ci    stubInfo_.AddAsmStubELFInfo(asmModule_.GetCSigns(), asmModule_.GetStubsOffset());
5624514f5e3Sopenharmony_ci    stubInfo_.FillAsmStubTempHolder(buffer, bufferSize);
5634514f5e3Sopenharmony_ci    stubInfo_.accumulateTotalSize(bufferSize);
5644514f5e3Sopenharmony_ci}
5654514f5e3Sopenharmony_ci
5664514f5e3Sopenharmony_civoid StubFileGenerator::SaveStubFile(const std::string &filename)
5674514f5e3Sopenharmony_ci{
5684514f5e3Sopenharmony_ci    RunLLVMAssembler();
5694514f5e3Sopenharmony_ci    RunAsmAssembler();
5704514f5e3Sopenharmony_ci    CollectCodeInfo();
5714514f5e3Sopenharmony_ci    stubInfo_.Save(filename, cfg_.GetTriple());
5724514f5e3Sopenharmony_ci}
5734514f5e3Sopenharmony_ci
5744514f5e3Sopenharmony_civoid AOTFileGenerator::CompileLatestModuleThenDestroy(bool isJit)
5754514f5e3Sopenharmony_ci{
5764514f5e3Sopenharmony_ci    Module *latestModule = GetLatestModule();
5774514f5e3Sopenharmony_ci#ifdef COMPILE_MAPLE
5784514f5e3Sopenharmony_ci    static uint32_t lastModulePC = 0;
5794514f5e3Sopenharmony_ci    if (useLiteCG_ && compilationEnv_->IsJitCompiler()) {
5804514f5e3Sopenharmony_ci        lastModulePC = 0;
5814514f5e3Sopenharmony_ci    }
5824514f5e3Sopenharmony_ci    if (latestModule->GetModule()->GetModuleKind() != MODULE_LLVM) {
5834514f5e3Sopenharmony_ci        LMIRModule *lmirModule = static_cast<LMIRModule*>(latestModule->GetModule());
5844514f5e3Sopenharmony_ci        lastModulePC = AlignUp(lastModulePC, AOTFileInfo::PAGE_ALIGN);
5854514f5e3Sopenharmony_ci        lmirModule->GetModule()->SetLastModulePC(lastModulePC);
5864514f5e3Sopenharmony_ci        // pass triple to litecg
5874514f5e3Sopenharmony_ci        lmirModule->GetModule()->SetIsAArch64(isAArch64());
5884514f5e3Sopenharmony_ci    }
5894514f5e3Sopenharmony_ci#endif
5904514f5e3Sopenharmony_ci    ASSERT(GetModuleVecSize() > 0);
5914514f5e3Sopenharmony_ci    uint32_t latestModuleIdx = GetModuleVecSize() - 1;
5924514f5e3Sopenharmony_ci    {
5934514f5e3Sopenharmony_ci        TimeScope timescope("LLVMIROpt", const_cast<CompilerLog *>(log_));
5944514f5e3Sopenharmony_ci        bool fastCompileMode = compilationEnv_->GetJSOptions().GetFastAOTCompileMode();
5954514f5e3Sopenharmony_ci        latestModule->RunAssembler(*(log_), fastCompileMode, isJit);
5964514f5e3Sopenharmony_ci    }
5974514f5e3Sopenharmony_ci    {
5984514f5e3Sopenharmony_ci        TimeScope timescope("LLVMCodeGen", const_cast<CompilerLog *>(log_));
5994514f5e3Sopenharmony_ci        CollectCodeInfo(latestModule, latestModuleIdx);
6004514f5e3Sopenharmony_ci    }
6014514f5e3Sopenharmony_ci    // message has been put into aotInfo, so latestModule could be destroyed
6024514f5e3Sopenharmony_ci#ifdef COMPILE_MAPLE
6034514f5e3Sopenharmony_ci    if (latestModule->GetModule()->GetModuleKind() != MODULE_LLVM) {
6044514f5e3Sopenharmony_ci        LMIRModule *lmirModule = static_cast<LMIRModule*>(latestModule->GetModule());
6054514f5e3Sopenharmony_ci        lastModulePC = lmirModule->GetModule()->GetCurModulePC();
6064514f5e3Sopenharmony_ci    }
6074514f5e3Sopenharmony_ci#endif
6084514f5e3Sopenharmony_ci    latestModule->DestroyModule();
6094514f5e3Sopenharmony_ci}
6104514f5e3Sopenharmony_ci
6114514f5e3Sopenharmony_civoid AOTFileGenerator::DestroyCollectedStackMapInfo()
6124514f5e3Sopenharmony_ci{
6134514f5e3Sopenharmony_ci    if (stackMapInfo_ != nullptr) {
6144514f5e3Sopenharmony_ci        delete stackMapInfo_;
6154514f5e3Sopenharmony_ci        stackMapInfo_ = nullptr;
6164514f5e3Sopenharmony_ci    }
6174514f5e3Sopenharmony_ci}
6184514f5e3Sopenharmony_ci
6194514f5e3Sopenharmony_civoid AOTFileGenerator::GenerateMergedStackmapSection()
6204514f5e3Sopenharmony_ci{
6214514f5e3Sopenharmony_ci    ArkStackMapBuilder builder;
6224514f5e3Sopenharmony_ci    std::shared_ptr<uint8_t> ptr = nullptr;
6234514f5e3Sopenharmony_ci    uint32_t size = 0;
6244514f5e3Sopenharmony_ci    if (stackMapInfo_ == nullptr) {
6254514f5e3Sopenharmony_ci        LOG_ECMA(FATAL) << "stackMapInfo_ isn't be initialized";
6264514f5e3Sopenharmony_ci        UNREACHABLE();
6274514f5e3Sopenharmony_ci    }
6284514f5e3Sopenharmony_ci    std::tie(ptr, size) = builder.GenerateArkStackMap(*stackMapInfo_, cfg_.GetTriple());
6294514f5e3Sopenharmony_ci    aotInfo_.UpdateStackMap(ptr, size, 0);
6304514f5e3Sopenharmony_ci    DestroyCollectedStackMapInfo();
6314514f5e3Sopenharmony_ci}
6324514f5e3Sopenharmony_ci
6334514f5e3Sopenharmony_cibool AOTFileGenerator::CreateDirIfNotExist(const std::string &filename)
6344514f5e3Sopenharmony_ci{
6354514f5e3Sopenharmony_ci    std::string realPath;
6364514f5e3Sopenharmony_ci    if (!panda::ecmascript::RealPath(filename, realPath, false)) {
6374514f5e3Sopenharmony_ci        return false;
6384514f5e3Sopenharmony_ci    }
6394514f5e3Sopenharmony_ci    auto index = realPath.find_last_of('/');
6404514f5e3Sopenharmony_ci    if (index == std::string::npos) {
6414514f5e3Sopenharmony_ci        return true;
6424514f5e3Sopenharmony_ci    }
6434514f5e3Sopenharmony_ci    std::string path = realPath.substr(0, index);
6444514f5e3Sopenharmony_ci    if (!panda::ecmascript::ForceCreateDirectory(path)) {
6454514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Fail to make dir: " << path;
6464514f5e3Sopenharmony_ci        return false;
6474514f5e3Sopenharmony_ci    }
6484514f5e3Sopenharmony_ci    return panda::ecmascript::SetDirModeAsDefault(path);
6494514f5e3Sopenharmony_ci}
6504514f5e3Sopenharmony_ci
6514514f5e3Sopenharmony_cibool AOTFileGenerator::SaveAOTFile(const std::string &filename, const std::string &appSignature)
6524514f5e3Sopenharmony_ci{
6534514f5e3Sopenharmony_ci    if (aotInfo_.GetTotalCodeSize() == 0) {
6544514f5e3Sopenharmony_ci        LOG_COMPILER(WARN) << "error: code size of generated an file is empty!";
6554514f5e3Sopenharmony_ci        return false;
6564514f5e3Sopenharmony_ci    }
6574514f5e3Sopenharmony_ci    if (!CreateDirIfNotExist(filename)) {
6584514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Fail to access dir: " << filename;
6594514f5e3Sopenharmony_ci        return false;
6604514f5e3Sopenharmony_ci    }
6614514f5e3Sopenharmony_ci    PrintMergedCodeComment();
6624514f5e3Sopenharmony_ci    GenerateMergedStackmapSection();
6634514f5e3Sopenharmony_ci    aotInfo_.GenerateMethodToEntryIndexMap();
6644514f5e3Sopenharmony_ci    if (!aotInfo_.Save(filename, cfg_.GetTriple())) {
6654514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Fail to save an file: " << filename;
6664514f5e3Sopenharmony_ci        return false;
6674514f5e3Sopenharmony_ci    }
6684514f5e3Sopenharmony_ci    if (!panda::ecmascript::SetFileModeAsDefault(filename)) {
6694514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Fail to set an file mode:" << filename;
6704514f5e3Sopenharmony_ci        return false;
6714514f5e3Sopenharmony_ci    }
6724514f5e3Sopenharmony_ci    SetSecurityLabel(filename);
6734514f5e3Sopenharmony_ci    panda::ecmascript::CodeSignatureForAOTFile(filename, appSignature);
6744514f5e3Sopenharmony_ci    return true;
6754514f5e3Sopenharmony_ci}
6764514f5e3Sopenharmony_ci
6774514f5e3Sopenharmony_civoid AOTFileGenerator::SaveEmptyAOTFile(const std::string& filename, const std::string& appSignature, bool isAnFile)
6784514f5e3Sopenharmony_ci{
6794514f5e3Sopenharmony_ci    if (!CreateDirIfNotExist(filename)) {
6804514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Fail to access dir: " << filename;
6814514f5e3Sopenharmony_ci        return;
6824514f5e3Sopenharmony_ci    }
6834514f5e3Sopenharmony_ci    std::string realPath;
6844514f5e3Sopenharmony_ci    if (!RealPath(filename, realPath, false)) {
6854514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Fail to get realPath: " << filename;
6864514f5e3Sopenharmony_ci        return;
6874514f5e3Sopenharmony_ci    }
6884514f5e3Sopenharmony_ci    if (FileExist(realPath.c_str())) {
6894514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "AOT file: " << realPath << " exist, skip create empty file";
6904514f5e3Sopenharmony_ci        return;
6914514f5e3Sopenharmony_ci    }
6924514f5e3Sopenharmony_ci    const char* rawPath = realPath.c_str();
6934514f5e3Sopenharmony_ci    std::ofstream file(rawPath, std::ofstream::binary);
6944514f5e3Sopenharmony_ci    file.close();
6954514f5e3Sopenharmony_ci    if (!panda::ecmascript::SetFileModeAsDefault(filename)) {
6964514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Fail to set file mode: " << filename;
6974514f5e3Sopenharmony_ci    }
6984514f5e3Sopenharmony_ci    if (isAnFile) {
6994514f5e3Sopenharmony_ci        panda::ecmascript::CodeSignatureForAOTFile(filename, appSignature);
7004514f5e3Sopenharmony_ci    }
7014514f5e3Sopenharmony_ci    LOG_COMPILER(ERROR) << "create empty AOT file: " << realPath << " due to illegal AP file";
7024514f5e3Sopenharmony_ci}
7034514f5e3Sopenharmony_ci
7044514f5e3Sopenharmony_cibool AOTFileGenerator::GetMemoryCodeInfos(MachineCodeDesc &machineCodeDesc)
7054514f5e3Sopenharmony_ci{
7064514f5e3Sopenharmony_ci    if (aotInfo_.GetTotalCodeSize() == 0) {
7074514f5e3Sopenharmony_ci        LOG_COMPILER(WARN) << "error: code size of generated an file is empty!";
7084514f5e3Sopenharmony_ci        return false;
7094514f5e3Sopenharmony_ci    }
7104514f5e3Sopenharmony_ci
7114514f5e3Sopenharmony_ci    if (log_->OutputASM()) {
7124514f5e3Sopenharmony_ci        PrintMergedCodeComment();
7134514f5e3Sopenharmony_ci    }
7144514f5e3Sopenharmony_ci    GenerateMergedStackmapSection();
7154514f5e3Sopenharmony_ci
7164514f5e3Sopenharmony_ci    // get func entry Map
7174514f5e3Sopenharmony_ci    aotInfo_.GenerateMethodToEntryIndexMap();
7184514f5e3Sopenharmony_ci
7194514f5e3Sopenharmony_ci    uint64_t funcEntryAddr = reinterpret_cast<uint64_t>(aotInfo_.GetStubs().data());
7204514f5e3Sopenharmony_ci    ASSERT(aotInfo_.GetStubs().size() <= 2); // jsfunc + __llvm_deoptimize, 2 : size
7214514f5e3Sopenharmony_ci    uint32_t funcEntrySize = sizeof(AOTFileInfo::FuncEntryDes) * aotInfo_.GetStubs().size();
7224514f5e3Sopenharmony_ci
7234514f5e3Sopenharmony_ci    ASSERT(aotInfo_.GetModuleSectionDes().size() == 1);
7244514f5e3Sopenharmony_ci    auto &moduleSectionDes = aotInfo_.GetModuleSectionDes()[0];
7254514f5e3Sopenharmony_ci    // get code data
7264514f5e3Sopenharmony_ci    uint64_t textAddr = moduleSectionDes.GetSecAddr(ElfSecName::TEXT);
7274514f5e3Sopenharmony_ci    size_t textSize = moduleSectionDes.GetSecSize(ElfSecName::TEXT);
7284514f5e3Sopenharmony_ci
7294514f5e3Sopenharmony_ci    uint64_t rodataAddrBeforeText = 0;
7304514f5e3Sopenharmony_ci    uint32_t rodataSizeBeforeText = 0;
7314514f5e3Sopenharmony_ci    uint64_t rodataAddrAfterText = 0;
7324514f5e3Sopenharmony_ci    uint32_t rodataSizeAfterText = 0;
7334514f5e3Sopenharmony_ci    std::tie(rodataAddrBeforeText, rodataSizeBeforeText, rodataAddrAfterText, rodataSizeAfterText) =
7344514f5e3Sopenharmony_ci        moduleSectionDes.GetMergedRODataAddrAndSize(textAddr);
7354514f5e3Sopenharmony_ci
7364514f5e3Sopenharmony_ci    machineCodeDesc.rodataAddrBeforeText = rodataAddrBeforeText;
7374514f5e3Sopenharmony_ci    machineCodeDesc.rodataSizeBeforeText = rodataSizeBeforeText;
7384514f5e3Sopenharmony_ci    machineCodeDesc.rodataAddrAfterText = rodataAddrAfterText;
7394514f5e3Sopenharmony_ci    machineCodeDesc.rodataSizeAfterText = rodataSizeAfterText;
7404514f5e3Sopenharmony_ci
7414514f5e3Sopenharmony_ci#ifdef JIT_ENABLE_CODE_SIGN
7424514f5e3Sopenharmony_ci    machineCodeDesc.codeSigner = 0;
7434514f5e3Sopenharmony_ci    JitSignCode *singleton = JitSignCode::GetInstance();
7444514f5e3Sopenharmony_ci    if (singleton->GetCodeSigner() != 0) {
7454514f5e3Sopenharmony_ci        LOG_JIT(DEBUG) << "In GetMemoryCodeInfos, signer = " << singleton->GetCodeSigner();
7464514f5e3Sopenharmony_ci        LOG_JIT(DEBUG) << "     signTableSize = " << singleton->signTableSize_;
7474514f5e3Sopenharmony_ci        machineCodeDesc.codeSigner = reinterpret_cast<uintptr_t>(singleton->GetCodeSigner());
7484514f5e3Sopenharmony_ci    }
7494514f5e3Sopenharmony_ci#endif
7504514f5e3Sopenharmony_ci
7514514f5e3Sopenharmony_ci    uint64_t stackMapPtr = reinterpret_cast<uint64_t>(moduleSectionDes.GetArkStackMapSharePtr().get());
7524514f5e3Sopenharmony_ci    size_t stackMapSize = moduleSectionDes.GetArkStackMapSize();
7534514f5e3Sopenharmony_ci
7544514f5e3Sopenharmony_ci    machineCodeDesc.codeAddr = textAddr;
7554514f5e3Sopenharmony_ci    machineCodeDesc.codeSize = textSize;
7564514f5e3Sopenharmony_ci    machineCodeDesc.funcEntryDesAddr = funcEntryAddr;
7574514f5e3Sopenharmony_ci    machineCodeDesc.funcEntryDesSize = funcEntrySize;
7584514f5e3Sopenharmony_ci    machineCodeDesc.stackMapOrOffsetTableAddr = stackMapPtr;
7594514f5e3Sopenharmony_ci    machineCodeDesc.stackMapOrOffsetTableSize = stackMapSize;
7604514f5e3Sopenharmony_ci    machineCodeDesc.codeType = MachineCodeType::FAST_JIT_CODE;
7614514f5e3Sopenharmony_ci
7624514f5e3Sopenharmony_ci    if (Jit::GetInstance()->IsEnableJitFort() && Jit::GetInstance()->IsEnableAsyncCopyToFort() &&
7634514f5e3Sopenharmony_ci        JitCompiler::AllocFromFortAndCopy(*compilationEnv_, machineCodeDesc) == false) {
7644514f5e3Sopenharmony_ci        return false;
7654514f5e3Sopenharmony_ci    }
7664514f5e3Sopenharmony_ci    return true;
7674514f5e3Sopenharmony_ci}
7684514f5e3Sopenharmony_ci
7694514f5e3Sopenharmony_civoid AOTFileGenerator::JitCreateLitecgModule()
7704514f5e3Sopenharmony_ci{
7714514f5e3Sopenharmony_ci#ifdef COMPILE_MAPLE
7724514f5e3Sopenharmony_ci    Module *latestModule = GetLatestModule();
7734514f5e3Sopenharmony_ci    if (latestModule->GetModule()->GetModuleKind() != MODULE_LLVM) {
7744514f5e3Sopenharmony_ci        LMIRModule *lmirModule = static_cast<LMIRModule*>(latestModule->GetModule());
7754514f5e3Sopenharmony_ci        lmirModule->JitCreateLitecgModule();
7764514f5e3Sopenharmony_ci    }
7774514f5e3Sopenharmony_ci#endif
7784514f5e3Sopenharmony_ci}
7794514f5e3Sopenharmony_ci
7804514f5e3Sopenharmony_cibool AOTFileGenerator::isAArch64() const
7814514f5e3Sopenharmony_ci{
7824514f5e3Sopenharmony_ci    return cfg_.IsAArch64();
7834514f5e3Sopenharmony_ci}
7844514f5e3Sopenharmony_ci
7854514f5e3Sopenharmony_cibool AOTFileGenerator::SaveSnapshotFile()
7864514f5e3Sopenharmony_ci{
7874514f5e3Sopenharmony_ci    TimeScope timescope("LLVMCodeGenPass-AI", const_cast<CompilerLog *>(log_));
7884514f5e3Sopenharmony_ci    Snapshot snapshot(compilationEnv_->GetEcmaVM());
7894514f5e3Sopenharmony_ci    const CString snapshotPath(compilationEnv_->GetJSOptions().GetAOTOutputFile().c_str());
7904514f5e3Sopenharmony_ci    const auto &methodToEntryIndexMap = aotInfo_.GetMethodToEntryIndexMap();
7914514f5e3Sopenharmony_ci    PGOTypeManager *ptManager = compilationEnv_->GetPTManager();
7924514f5e3Sopenharmony_ci    ptManager->GetAOTSnapshot().ResolveSnapshotData(methodToEntryIndexMap);
7934514f5e3Sopenharmony_ci
7944514f5e3Sopenharmony_ci    CString aiPath = snapshotPath + AOTFileManager::FILE_EXTENSION_AI;
7954514f5e3Sopenharmony_ci    if (!CreateDirIfNotExist(aiPath.c_str())) {
7964514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Fail to access dir: " << aiPath;
7974514f5e3Sopenharmony_ci        return false;
7984514f5e3Sopenharmony_ci    }
7994514f5e3Sopenharmony_ci    snapshot.Serialize(aiPath);
8004514f5e3Sopenharmony_ci    if (!panda::ecmascript::SetFileModeAsDefault(aiPath.c_str())) {
8014514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Fail to set ai file mode:" << aiPath;
8024514f5e3Sopenharmony_ci        return false;
8034514f5e3Sopenharmony_ci    }
8044514f5e3Sopenharmony_ci    SetSecurityLabel(aiPath.c_str());
8054514f5e3Sopenharmony_ci    return true;
8064514f5e3Sopenharmony_ci}
8074514f5e3Sopenharmony_ci}  // namespace panda::ecmascript::kungfu
808