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/codegen/llvm/llvm_codegen.h" 24 #include "ecmascript/compiler/codegen/llvm/llvm_ir_builder.h" 25 #include "ecmascript/compiler/compiler_log.h" 26 #include "ecmascript/compiler/ir_module.h" 27 #include "ecmascript/compiler/jit_compilation_env.h" 28 #include "ecmascript/stackmap/cg_stackmap.h" 29 #include "ecmascript/mem/machine_code.h" 30 31 namespace panda::ecmascript::kungfu { 32 class Module { 33 public: 34 Module() = default; Module(IRModule * module,Assembler * assembler)35 Module(IRModule *module, Assembler *assembler) 36 : irModule_(module), assembler_(assembler) 37 { 38 } 39 40 std::vector<uintptr_t> GetFuncEntryPoints(); 41 42 void CollectFuncEntryInfo(const std::vector<uintptr_t>& entrys, std::map<uintptr_t, std::string> &addr2name, 43 StubFileInfo &stubInfo, uint32_t moduleIndex, const CompilerLog &log); 44 45 void CollectFuncEntryInfo(std::map<uintptr_t, std::string> &addr2name, AnFileInfo &aotInfo, uint32_t fileIndex, 46 uint32_t moduleIndex, const CompilerLog &log); 47 48 #ifdef COMPILE_MAPLE 49 void CollectFuncEntryInfoByLiteCG(std::map<uintptr_t, std::string> &addr2name, AnFileInfo &aotInfo, 50 uint32_t fileIndex, uint32_t moduleIndex); 51 #endif 52 IsRelaSection(ElfSecName sec)53 bool IsRelaSection(ElfSecName sec) const 54 { 55 return sec == ElfSecName::RELATEXT; 56 } 57 58 void CollectModuleSectionDes(ModuleSectionDes &moduleDes) const; 59 60 void CollectAnModuleSectionDes(ModuleSectionDes &moduleDes, uint64_t textOffset, 61 CGStackMapInfo &stackMapInfo) const; 62 63 void CollectStackMapDes(ModuleSectionDes &moduleDes) const; 64 65 void CollectAnStackMapDes(ModuleSectionDes& des, uint64_t textOffset, 66 CGStackMapInfo &stackMapInfo) const; 67 68 uint32_t GetSectionSize(ElfSecName sec) const; 69 70 uintptr_t GetSectionAddr(ElfSecName sec) const; 71 GetMergedRODataAddrAndSize(uint64_t textAddr)72 std::tuple<uint64_t, uint32_t, uint64_t, uint32_t> GetMergedRODataAddrAndSize(uint64_t textAddr) const 73 { 74 uint64_t addrBeforeText = base::MAX_UINT64_VALUE; 75 uint32_t sizeBeforeText = 0; 76 uint64_t addrAfterText = base::MAX_UINT64_VALUE; 77 uint32_t sizeAfterText = 0; 78 for (uint8_t i = static_cast<uint8_t>(ElfSecName::RODATA); i <= static_cast<uint8_t>(ElfSecName::RODATA_CST32); 79 i++) { 80 UpdateRODataInfo(textAddr, addrBeforeText, sizeBeforeText, addrAfterText, sizeAfterText, 81 static_cast<ElfSecName>(i)); 82 } 83 return std::make_tuple(addrBeforeText, sizeBeforeText, addrAfterText, sizeAfterText); 84 } 85 86 void PUBLIC_API RunAssembler(const CompilerLog &log, bool fastCompileMode, bool isJit = false, 87 const std::string &filename = ""); 88 89 void DisassemblerFunc(std::map<uintptr_t, std::string> &addr2name, uint64_t textOffset, const CompilerLog &log, 90 const MethodLogList &logList, std::ostringstream &codeStream); 91 92 void DestroyModule(); 93 GetModule()94 IRModule* GetModule() const 95 { 96 return irModule_; 97 } 98 IsLLVM()99 bool IsLLVM() const 100 { 101 return irModule_->GetModuleKind() == MODULE_LLVM; 102 } 103 104 private: GetTextAddr()105 uintptr_t GetTextAddr() const 106 { 107 return assembler_->GetSectionAddr(ElfSecName::TEXT); 108 } 109 GetTextSize()110 uint32_t GetTextSize() const 111 { 112 return assembler_->GetSectionSize(ElfSecName::TEXT); 113 } 114 UpdateRODataInfo(uint64_t textAddr,uint64_t & addrBeforeText,uint32_t & sizeBeforeText,uint64_t & addrAfterText,uint32_t & sizeAfterText,ElfSecName sec)115 void UpdateRODataInfo(uint64_t textAddr, uint64_t &addrBeforeText, uint32_t &sizeBeforeText, 116 uint64_t &addrAfterText, uint32_t &sizeAfterText, ElfSecName sec) const 117 { 118 uint64_t curSectionAddr = GetSectionAddr(sec); 119 if (curSectionAddr == 0) { 120 ASSERT(GetSectionSize(sec) == 0); 121 return; 122 } 123 ASSERT(curSectionAddr != textAddr); 124 if (curSectionAddr < textAddr) { 125 addrBeforeText = (curSectionAddr < addrBeforeText) ? curSectionAddr : addrBeforeText; 126 sizeBeforeText += GetSectionSize(sec); 127 } else { 128 addrAfterText = (curSectionAddr < addrAfterText) ? curSectionAddr : addrAfterText; 129 sizeAfterText += GetSectionSize(sec); 130 } 131 } 132 133 IRModule *irModule_ {nullptr}; 134 Assembler *assembler_ {nullptr}; 135 // record current module first function index in StubFileInfo/AnFileInfo 136 uint32_t startIndex_ {static_cast<uint32_t>(-1)}; 137 uint32_t funcCount_ {0}; 138 }; 139 140 class FileGenerator { 141 public: FileGenerator(const CompilerLog * log,const MethodLogList * logList)142 FileGenerator(const CompilerLog *log, const MethodLogList *logList) : log_(log), logList_(logList) {}; ~FileGenerator()143 virtual ~FileGenerator() 144 { 145 codeStream_.clear(); 146 codeStream_.str(""); 147 } 148 GetLog()149 const CompilerLog GetLog() const 150 { 151 return *log_; 152 } 153 PrintMergedCodeComment()154 void PrintMergedCodeComment() 155 { 156 if (codeStream_.str().empty()) { 157 return; 158 } 159 LOG_COMPILER(INFO) << "\n" << codeStream_.str(); 160 } 161 162 protected: 163 std::vector<Module> modulePackage_ {}; 164 const CompilerLog *log_ {nullptr}; 165 const MethodLogList *logList_ {nullptr}; 166 std::ostringstream codeStream_; 167 RunLLVMAssembler()168 virtual void RunLLVMAssembler() 169 { 170 for (auto m : modulePackage_) { 171 m.RunAssembler(*(log_), false); 172 } 173 } 174 DestroyModule()175 void DestroyModule() 176 { 177 for (auto m : modulePackage_) { 178 m.DestroyModule(); 179 } 180 } 181 182 void CollectStackMapDes(ModuleSectionDes& des); 183 }; 184 185 class AOTFileGenerator : public FileGenerator { 186 public: 187 AOTFileGenerator(const CompilerLog *log, const MethodLogList *logList, CompilationEnv *env, 188 const std::string &triple, bool useLiteCG = false, size_t anFileMaxByteSize = 0) FileGenerator(log,logList)189 : FileGenerator(log, logList), 190 cfg_(triple), 191 compilationEnv_(env), 192 useLiteCG_(useLiteCG), 193 anFileMaxByteSize_(anFileMaxByteSize) 194 { 195 } 196 197 ~AOTFileGenerator() override = default; 198 199 Module* GetLatestModule(); 200 201 uint32_t GetModuleVecSize() const; 202 203 Module* AddModule(const std::string &name, const std::string &triple, LOptions option, bool logDebug, 204 bool isJit = false); 205 206 void CompileLatestModuleThenDestroy(bool isJit = false); 207 208 void DestroyCollectedStackMapInfo(); 209 210 void GenerateMergedStackmapSection(); 211 212 static bool CreateDirIfNotExist(const std::string& filename); 213 214 bool SetFileModeAsDefault(const std::string &filename); 215 216 // save function for aot files containing normal func translated from JS/TS 217 bool PUBLIC_API SaveAOTFile(const std::string &filename, const std::string &appSignature, 218 const std::unordered_map<CString, uint32_t> &fileNameToChecksumMap); 219 220 static void PUBLIC_API SaveEmptyAOTFile(const std::string& filename, const std::string& appSignature, 221 bool isAnFile); 222 223 bool PUBLIC_API SaveSnapshotFile(); 224 SetCurrentCompileFileName(CString fileName)225 void SetCurrentCompileFileName(CString fileName) 226 { 227 curCompileFileName_ = fileName.c_str(); 228 } 229 230 bool GetMemoryCodeInfos(MachineCodeDesc &machineCodeDesc); 231 void JitCreateLitecgModule(); 232 bool isAArch64() const; 233 234 std::string ExtractPrefix(const std::string &filename); 235 std::string GenAotCodeCommentFileName(const std::string &filename); 236 bool PUBLIC_API CreateAOTCodeCommentFile(const std::string &filename); 237 GetAotCodeCommentFile()238 const std::string &GetAotCodeCommentFile() const 239 { 240 return aotCodeCommentFile_; 241 } 242 SetAotCodeCommentFile(const std::string & filename)243 void SetAotCodeCommentFile(const std::string &filename) 244 { 245 aotCodeCommentFile_ = filename; 246 } 247 248 protected: 249 AnFileInfo aotInfo_; 250 CompilationConfig cfg_; 251 252 private: 253 // collect aot component info 254 void CollectCodeInfo(Module *module, uint32_t moduleIdx); 255 256 uint64_t RollbackTextSize(Module *module); 257 258 CGStackMapInfo *stackMapInfo_ = nullptr; 259 CompilationEnv *compilationEnv_ {nullptr}; 260 std::string curCompileFileName_; 261 // MethodID->EntryIndex 262 std::map<uint32_t, uint32_t> methodToEntryIndexMap_ {}; 263 const bool useLiteCG_; 264 CodeInfo::CodeSpaceOnDemand jitCodeSpace_ {}; 265 std::string aotCodeCommentFile_ = ""; 266 size_t anFileMaxByteSize_ {0_MB}; 267 }; 268 269 enum class StubFileKind { 270 BC, 271 COM, 272 BUILTIN, 273 BASELINE, 274 BC_STW_COPY 275 }; 276 277 class StubFileGenerator : public FileGenerator { 278 public: StubFileGenerator(const CompilerLog * log,const MethodLogList * logList,const std::string & triple,bool concurrentCompile)279 StubFileGenerator(const CompilerLog* log, const MethodLogList* logList, const std::string& triple, 280 bool concurrentCompile) 281 : FileGenerator(log, logList), 282 cfg_(triple), 283 concurrentCompile_(concurrentCompile) 284 { 285 } 286 ~StubFileGenerator() override = default; 287 288 Module* AddModule(NativeAreaAllocator *allocator, const std::string &name, const std::string &triple, 289 LOptions option, bool logDebug, StubFileKind k); 290 DisassembleEachFunc(std::map<uintptr_t,std::string> & addr2name)291 void DisassembleEachFunc(std::map<uintptr_t, std::string> &addr2name) 292 { 293 for (auto m : modulePackage_) { 294 m.DisassemblerFunc(addr2name, 0, *(log_), *(logList_), codeStream_); 295 } 296 PrintMergedCodeComment(); 297 } 298 299 void DisassembleAsmStubs(std::map<uintptr_t, std::string> &addr2name); 300 // save function funcs for aot files containing stubs 301 void SaveStubFile(const std::string &filename); 302 protected: 303 void RunLLVMAssembler() override; 304 private: 305 void RunAsmAssembler(); 306 void CollectAsmStubCodeInfo(std::map<uintptr_t, std::string> &addr2name, uint32_t bridgeModuleIdx); 307 void CollectCodeInfo(); 308 309 StubFileInfo stubInfo_; 310 AssemblerModule asmModule_; 311 CompilationConfig cfg_; 312 CodeInfo::CodeSpaceOnDemand jitCodeSpace_ {}; 313 bool concurrentCompile_ {false}; 314 }; 315 } // namespace panda::ecmascript::kungfu 316 #endif // ECMASCRIPT_COMPILER_FILE_GENERATORS_H 317