1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_COMPILER_FILE_GENERATORS_H 17 #define ECMASCRIPT_COMPILER_FILE_GENERATORS_H 18 19 #include "ecmascript/base/number_helper.h" 20 #include "ecmascript/common.h" 21 #include "ecmascript/compiler/aot_file/aot_file_manager.h" 22 #include "ecmascript/compiler/assembler_module.h" 23 #include "ecmascript/compiler/compiler_log.h" 24 #include "ecmascript/compiler/llvm_codegen.h" 25 #include "ecmascript/compiler/llvm_ir_builder.h" 26 #include "ecmascript/compiler/ir_module.h" 27 #include "ecmascript/stackmap/cg_stackmap.h" 28 #include "ecmascript/mem/machine_code.h" 29 30 namespace panda::ecmascript::kungfu { 31 class Module { 32 public: 33 Module() = default; Module(IRModule * module,Assembler * assembler)34 Module(IRModule *module, Assembler *assembler) 35 : irModule_(module), assembler_(assembler) 36 { 37 } 38 39 void CollectFuncEntryInfo(std::map<uintptr_t, std::string> &addr2name, StubFileInfo &stubInfo, 40 uint32_t moduleIndex, const CompilerLog &log); 41 42 void CollectFuncEntryInfo(std::map<uintptr_t, std::string> &addr2name, AnFileInfo &aotInfo, uint32_t fileIndex, 43 uint32_t moduleIndex, const CompilerLog &log); 44 45 #ifdef COMPILE_MAPLE 46 void CollectFuncEntryInfoByLiteCG(std::map<uintptr_t, std::string> &addr2name, AnFileInfo &aotInfo, 47 uint32_t fileIndex, uint32_t moduleIndex); 48 #endif 49 IsRelaSection(ElfSecName sec)50 bool IsRelaSection(ElfSecName sec) const 51 { 52 return sec == ElfSecName::RELATEXT; 53 } 54 55 void CollectModuleSectionDes(ModuleSectionDes &moduleDes) const; 56 57 void CollectAnModuleSectionDes(ModuleSectionDes &moduleDes, uint64_t textOffset, 58 CGStackMapInfo &stackMapInfo) const; 59 60 void CollectStackMapDes(ModuleSectionDes &moduleDes) const; 61 62 void CollectAnStackMapDes(ModuleSectionDes& des, uint64_t textOffset, 63 CGStackMapInfo &stackMapInfo) const; 64 65 uint32_t GetSectionSize(ElfSecName sec) const; 66 67 uintptr_t GetSectionAddr(ElfSecName sec) const; 68 GetMergedRODataAddrAndSize(uint64_t textAddr)69 std::tuple<uint64_t, uint32_t, uint64_t, uint32_t> GetMergedRODataAddrAndSize(uint64_t textAddr) const 70 { 71 uint64_t addrBeforeText = base::MAX_UINT64_VALUE; 72 uint32_t sizeBeforeText = 0; 73 uint64_t addrAfterText = base::MAX_UINT64_VALUE; 74 uint32_t sizeAfterText = 0; 75 for (uint8_t i = static_cast<uint8_t>(ElfSecName::RODATA); i <= static_cast<uint8_t>(ElfSecName::RODATA_CST32); 76 i++) { 77 UpdateRODataInfo(textAddr, addrBeforeText, sizeBeforeText, addrAfterText, sizeAfterText, 78 static_cast<ElfSecName>(i)); 79 } 80 return std::make_tuple(addrBeforeText, sizeBeforeText, addrAfterText, sizeAfterText); 81 } 82 83 void RunAssembler(const CompilerLog &log, bool fastCompileMode); 84 85 void DisassemblerFunc(std::map<uintptr_t, std::string> &addr2name, uint64_t textOffset, const CompilerLog &log, 86 const MethodLogList &logList, std::ostringstream &codeStream); 87 88 void DestroyModule(); 89 GetModule()90 IRModule* GetModule() const 91 { 92 return irModule_; 93 } 94 IsLLVM()95 bool IsLLVM() const 96 { 97 return irModule_->GetModuleKind() == MODULE_LLVM; 98 } 99 100 private: GetTextAddr()101 uintptr_t GetTextAddr() const 102 { 103 return assembler_->GetSectionAddr(ElfSecName::TEXT); 104 } 105 GetTextSize()106 uint32_t GetTextSize() const 107 { 108 return assembler_->GetSectionSize(ElfSecName::TEXT); 109 } 110 UpdateRODataInfo(uint64_t textAddr,uint64_t & addrBeforeText,uint32_t & sizeBeforeText,uint64_t & addrAfterText,uint32_t & sizeAfterText,ElfSecName sec)111 void UpdateRODataInfo(uint64_t textAddr, uint64_t &addrBeforeText, uint32_t &sizeBeforeText, 112 uint64_t &addrAfterText, uint32_t &sizeAfterText, ElfSecName sec) const 113 { 114 uint64_t curSectionAddr = GetSectionAddr(sec); 115 if (curSectionAddr == 0) { 116 ASSERT(GetSectionSize(sec) == 0); 117 return; 118 } 119 ASSERT(curSectionAddr != textAddr); 120 if (curSectionAddr < textAddr) { 121 addrBeforeText = (curSectionAddr < addrBeforeText) ? curSectionAddr : addrBeforeText; 122 sizeBeforeText += GetSectionSize(sec); 123 } else { 124 addrAfterText = (curSectionAddr < addrAfterText) ? curSectionAddr : addrAfterText; 125 sizeAfterText += GetSectionSize(sec); 126 } 127 } 128 129 IRModule *irModule_ {nullptr}; 130 Assembler *assembler_ {nullptr}; 131 // record current module first function index in StubFileInfo/AnFileInfo 132 uint32_t startIndex_ {static_cast<uint32_t>(-1)}; 133 uint32_t funcCount_ {0}; 134 }; 135 136 class FileGenerator { 137 public: FileGenerator(const CompilerLog * log,const MethodLogList * logList)138 FileGenerator(const CompilerLog *log, const MethodLogList *logList) : log_(log), logList_(logList) {}; ~FileGenerator()139 virtual ~FileGenerator() 140 { 141 codeStream_.clear(); 142 codeStream_.str(""); 143 } 144 GetLog()145 const CompilerLog GetLog() const 146 { 147 return *log_; 148 } 149 PrintMergedCodeComment()150 void PrintMergedCodeComment() 151 { 152 LOG_COMPILER(INFO) << "\n" << codeStream_.str(); 153 } 154 155 protected: 156 std::vector<Module> modulePackage_ {}; 157 const CompilerLog *log_ {nullptr}; 158 const MethodLogList *logList_ {nullptr}; 159 std::ostringstream codeStream_; 160 RunLLVMAssembler()161 void RunLLVMAssembler() 162 { 163 for (auto m : modulePackage_) { 164 m.RunAssembler(*(log_), false); 165 } 166 } 167 DestroyModule()168 void DestroyModule() 169 { 170 for (auto m : modulePackage_) { 171 m.DestroyModule(); 172 } 173 } 174 175 void CollectStackMapDes(ModuleSectionDes& des); 176 }; 177 178 class AOTFileGenerator : public FileGenerator { 179 public: 180 AOTFileGenerator(const CompilerLog *log, const MethodLogList *logList, EcmaVM* vm, const std::string &triple, 181 bool useLiteCG = false) FileGenerator(log,logList)182 : FileGenerator(log, logList), vm_(vm), cfg_(triple), useLiteCG_(useLiteCG) {} 183 184 ~AOTFileGenerator() override = default; 185 186 Module* GetLatestModule(); 187 188 uint32_t GetModuleVecSize() const; 189 190 Module* AddModule(const std::string &name, const std::string &triple, LOptions option, bool logDebug, 191 bool isJit = false); 192 193 void CompileLatestModuleThenDestroy(); 194 195 void DestroyCollectedStackMapInfo(); 196 197 void GenerateMergedStackmapSection(); 198 199 bool CreateDirIfNotExist(const std::string &filename); 200 201 bool SetFileModeAsDefault(const std::string &filename); 202 203 // save function for aot files containing normal func translated from JS/TS 204 void SaveAOTFile(const std::string &filename, const std::string &appSignature); 205 206 void SaveSnapshotFile(); 207 SetCurrentCompileFileName(CString fileName)208 void SetCurrentCompileFileName(CString fileName) 209 { 210 curCompileFileName_ = fileName.c_str(); 211 } 212 213 void GetMemoryCodeInfos(MachineCodeDesc *machineCodeDesc); 214 void JitCreateLitecgModule(); 215 216 private: 217 // collect aot component info 218 void CollectCodeInfo(Module *module, uint32_t moduleIdx); 219 220 uint64_t RollbackTextSize(Module *module); 221 222 AnFileInfo aotInfo_; 223 CGStackMapInfo *stackMapInfo_ = nullptr; 224 EcmaVM* vm_; 225 CompilationConfig cfg_; 226 std::string curCompileFileName_; 227 // MethodID->EntryIndex 228 std::map<uint32_t, uint32_t> methodToEntryIndexMap_ {}; 229 const bool useLiteCG_; 230 }; 231 232 enum class StubFileKind { 233 BC, 234 COM, 235 BUILTIN 236 }; 237 238 class StubFileGenerator : public FileGenerator { 239 public: StubFileGenerator(const CompilerLog * log,const MethodLogList * logList,const std::string & triple)240 StubFileGenerator(const CompilerLog *log, const MethodLogList *logList, const std::string &triple) 241 : FileGenerator(log, logList), 242 cfg_(triple) 243 { 244 } 245 ~StubFileGenerator() override = default; 246 247 Module* AddModule(NativeAreaAllocator *allocator, const std::string &name, const std::string &triple, 248 LOptions option, bool logDebug, StubFileKind k); 249 DisassembleEachFunc(std::map<uintptr_t,std::string> & addr2name)250 void DisassembleEachFunc(std::map<uintptr_t, std::string> &addr2name) 251 { 252 for (auto m : modulePackage_) { 253 m.DisassemblerFunc(addr2name, 0, *(log_), *(logList_), codeStream_); 254 } 255 PrintMergedCodeComment(); 256 } 257 258 void DisassembleAsmStubs(std::map<uintptr_t, std::string> &addr2name); 259 // save function funcs for aot files containing stubs 260 void SaveStubFile(const std::string &filename); 261 262 private: 263 void RunAsmAssembler(); 264 void CollectAsmStubCodeInfo(std::map<uintptr_t, std::string> &addr2name, uint32_t bridgeModuleIdx); 265 void CollectCodeInfo(); 266 267 StubFileInfo stubInfo_; 268 AssemblerModule asmModule_; 269 CompilationConfig cfg_; 270 }; 271 } // namespace panda::ecmascript::kungfu 272 #endif // ECMASCRIPT_COMPILER_FILE_GENERATORS_H 273