* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_COMPILER_FILE_GENERATORS_H
#define ECMASCRIPT_COMPILER_FILE_GENERATORS_H
#include "ecmascript/base/number_helper.h"
#include "ecmascript/common.h"
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
#include "ecmascript/compiler/assembler_module.h"
#include "ecmascript/compiler/codegen/llvm/llvm_codegen.h"
#include "ecmascript/compiler/codegen/llvm/llvm_ir_builder.h"
#include "ecmascript/compiler/compiler_log.h"
#include "ecmascript/compiler/ir_module.h"
#include "ecmascript/compiler/jit_compilation_env.h"
#include "ecmascript/stackmap/cg_stackmap.h"
#include "ecmascript/mem/machine_code.h"
namespace panda::ecmascript::kungfu {
class Module {
public:
Module() = default;
Module(IRModule *module, Assembler *assembler)
: irModule_(module), assembler_(assembler)
{
}
std::vector<uintptr_t> GetFuncEntryPoints();
void CollectFuncEntryInfo(const std::vector<uintptr_t>& entrys, std::map<uintptr_t, std::string> &addr2name,
StubFileInfo &stubInfo, uint32_t moduleIndex, const CompilerLog &log);
void CollectFuncEntryInfo(std::map<uintptr_t, std::string> &addr2name, AnFileInfo &aotInfo, uint32_t fileIndex,
uint32_t moduleIndex, const CompilerLog &log);
#ifdef COMPILE_MAPLE
void CollectFuncEntryInfoByLiteCG(std::map<uintptr_t, std::string> &addr2name, AnFileInfo &aotInfo,
uint32_t fileIndex, uint32_t moduleIndex);
#endif
bool IsRelaSection(ElfSecName sec) const
{
return sec == ElfSecName::RELATEXT;
}
void CollectModuleSectionDes(ModuleSectionDes &moduleDes) const;
void CollectAnModuleSectionDes(ModuleSectionDes &moduleDes, uint64_t textOffset,
CGStackMapInfo &stackMapInfo) const;
void CollectStackMapDes(ModuleSectionDes &moduleDes) const;
void CollectAnStackMapDes(ModuleSectionDes& des, uint64_t textOffset,
CGStackMapInfo &stackMapInfo) const;
uint32_t GetSectionSize(ElfSecName sec) const;
uintptr_t GetSectionAddr(ElfSecName sec) const;
std::tuple<uint64_t, uint32_t, uint64_t, uint32_t> GetMergedRODataAddrAndSize(uint64_t textAddr) const
{
uint64_t addrBeforeText = base::MAX_UINT64_VALUE;
uint32_t sizeBeforeText = 0;
uint64_t addrAfterText = base::MAX_UINT64_VALUE;
uint32_t sizeAfterText = 0;
for (uint8_t i = static_cast<uint8_t>(ElfSecName::RODATA); i <= static_cast<uint8_t>(ElfSecName::RODATA_CST32);
i++) {
UpdateRODataInfo(textAddr, addrBeforeText, sizeBeforeText, addrAfterText, sizeAfterText,
static_cast<ElfSecName>(i));
}
return std::make_tuple(addrBeforeText, sizeBeforeText, addrAfterText, sizeAfterText);
}
void PUBLIC_API RunAssembler(const CompilerLog &log, bool fastCompileMode, bool isJit = false,
const std::string &filename = "");
void DisassemblerFunc(std::map<uintptr_t, std::string> &addr2name, uint64_t textOffset, const CompilerLog &log,
const MethodLogList &logList, std::ostringstream &codeStream);
void DestroyModule();
IRModule* GetModule() const
{
return irModule_;
}
bool IsLLVM() const
{
return irModule_->GetModuleKind() == MODULE_LLVM;
}
private:
uintptr_t GetTextAddr() const
{
return assembler_->GetSectionAddr(ElfSecName::TEXT);
}
uint32_t GetTextSize() const
{
return assembler_->GetSectionSize(ElfSecName::TEXT);
}
void UpdateRODataInfo(uint64_t textAddr, uint64_t &addrBeforeText, uint32_t &sizeBeforeText,
uint64_t &addrAfterText, uint32_t &sizeAfterText, ElfSecName sec) const
{
uint64_t curSectionAddr = GetSectionAddr(sec);
if (curSectionAddr == 0) {
ASSERT(GetSectionSize(sec) == 0);
return;
}
ASSERT(curSectionAddr != textAddr);
if (curSectionAddr < textAddr) {
addrBeforeText = (curSectionAddr < addrBeforeText) ? curSectionAddr : addrBeforeText;
sizeBeforeText += GetSectionSize(sec);
} else {
addrAfterText = (curSectionAddr < addrAfterText) ? curSectionAddr : addrAfterText;
sizeAfterText += GetSectionSize(sec);
}
}
IRModule *irModule_ {nullptr};
Assembler *assembler_ {nullptr};
uint32_t startIndex_ {static_cast<uint32_t>(-1)};
uint32_t funcCount_ {0};
};
class FileGenerator {
public:
FileGenerator(const CompilerLog *log, const MethodLogList *logList) : log_(log), logList_(logList) {};
virtual ~FileGenerator()
{
codeStream_.clear();
codeStream_.str("");
}
const CompilerLog GetLog() const
{
return *log_;
}
void PrintMergedCodeComment()
{
if (codeStream_.str().empty()) {
return;
}
LOG_COMPILER(INFO) << "\n" << codeStream_.str();
}
protected:
std::vector<Module> modulePackage_ {};
const CompilerLog *log_ {nullptr};
const MethodLogList *logList_ {nullptr};
std::ostringstream codeStream_;
virtual void RunLLVMAssembler()
{
for (auto m : modulePackage_) {
m.RunAssembler(*(log_), false);
}
}
void DestroyModule()
{
for (auto m : modulePackage_) {
m.DestroyModule();
}
}
void CollectStackMapDes(ModuleSectionDes& des);
};
class AOTFileGenerator : public FileGenerator {
public:
AOTFileGenerator(const CompilerLog *log, const MethodLogList *logList, CompilationEnv *env,
const std::string &triple, bool useLiteCG = false, size_t anFileMaxByteSize = 0)
: FileGenerator(log, logList),
cfg_(triple),
compilationEnv_(env),
useLiteCG_(useLiteCG),
anFileMaxByteSize_(anFileMaxByteSize)
{
}
~AOTFileGenerator() override = default;
Module* GetLatestModule();
uint32_t GetModuleVecSize() const;
Module* AddModule(const std::string &name, const std::string &triple, LOptions option, bool logDebug,
bool isJit = false);
void CompileLatestModuleThenDestroy(bool isJit = false);
void DestroyCollectedStackMapInfo();
bool GenerateMergedStackmapSection();
static bool CreateDirIfNotExist(const std::string& filename);
bool SetFileModeAsDefault(const std::string &filename);
bool PUBLIC_API SaveAOTFile(const std::string &filename, const std::string &appSignature,
const std::unordered_map<CString, uint32_t> &fileNameToChecksumMap);
bool PUBLIC_API SaveAOTFile(int anFd, const std::string &filename, const std::string &appSignature,
const std::unordered_map<CString, uint32_t> &fileNameToChecksumMap);
static void PUBLIC_API SaveEmptyAOTFile(const std::string& filename, const std::string& appSignature,
bool isAnFile);
bool PUBLIC_API SaveSnapshotFile();
void SetCurrentCompileFileName(CString fileName)
{
curCompileFileName_ = fileName.c_str();
}
bool GetMemoryCodeInfos(MachineCodeDesc &machineCodeDesc);
void JitCreateLitecgModule();
bool IsAArch64() const;
std::string ExtractPrefix(const std::string &filename);
std::string GenAotCodeCommentFileName(const std::string &filename);
bool PUBLIC_API CreateAOTCodeCommentFile(const std::string &filename);
const std::string &GetAotCodeCommentFile() const
{
return aotCodeCommentFile_;
}
void SetAotCodeCommentFile(const std::string &filename)
{
aotCodeCommentFile_ = filename;
}
protected:
AnFileInfo aotInfo_;
CompilationConfig cfg_;
private:
void CollectCodeInfo(Module *module, uint32_t moduleIdx);
uint64_t RollbackTextSize(Module *module);
CGStackMapInfo *stackMapInfo_ = nullptr;
CompilationEnv *compilationEnv_ {nullptr};
std::string curCompileFileName_;
std::map<uint32_t, uint32_t> methodToEntryIndexMap_ {};
const bool useLiteCG_;
CodeInfo::CodeSpaceOnDemand jitCodeSpace_ {};
std::string aotCodeCommentFile_ = "";
size_t anFileMaxByteSize_ {0_MB};
};
enum class StubFileKind {
BC,
COM,
BUILTIN,
BASELINE,
BC_STW_COPY,
BUILTIN_STW_COPY
};
class StubFileGenerator : public FileGenerator {
public:
StubFileGenerator(const CompilerLog* log, const MethodLogList* logList, const std::string& triple,
bool concurrentCompile)
: FileGenerator(log, logList),
cfg_(triple),
concurrentCompile_(concurrentCompile)
{
}
~StubFileGenerator() override = default;
Module* AddModule(NativeAreaAllocator *allocator, const std::string &name, const std::string &triple,
LOptions option, bool logDebug, StubFileKind k);
void DisassembleEachFunc(std::map<uintptr_t, std::string> &addr2name)
{
for (auto m : modulePackage_) {
m.DisassemblerFunc(addr2name, 0, *(log_), *(logList_), codeStream_);
}
PrintMergedCodeComment();
}
void DisassembleAsmStubs(std::map<uintptr_t, std::string> &addr2name);
void SaveStubFile(const std::string &filename);
protected:
void RunLLVMAssembler() override;
private:
void RunAsmAssembler();
void CollectAsmStubCodeInfo(std::map<uintptr_t, std::string> &addr2name, uint32_t bridgeModuleIdx);
void CollectCodeInfo();
StubFileInfo stubInfo_;
AssemblerModule asmModule_;
CompilationConfig cfg_;
CodeInfo::CodeSpaceOnDemand jitCodeSpace_ {};
bool concurrentCompile_ {false};
};
}
#endif