• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 };
275 
276 class StubFileGenerator : public FileGenerator {
277 public:
StubFileGenerator(const CompilerLog * log,const MethodLogList * logList,const std::string & triple,bool concurrentCompile)278     StubFileGenerator(const CompilerLog* log, const MethodLogList* logList, const std::string& triple,
279                       bool concurrentCompile)
280         : FileGenerator(log, logList),
281           cfg_(triple),
282           concurrentCompile_(concurrentCompile)
283     {
284     }
285     ~StubFileGenerator() override = default;
286 
287     Module* AddModule(NativeAreaAllocator *allocator, const std::string &name, const std::string &triple,
288                       LOptions option, bool logDebug, StubFileKind k);
289 
DisassembleEachFunc(std::map<uintptr_t,std::string> & addr2name)290     void DisassembleEachFunc(std::map<uintptr_t, std::string> &addr2name)
291     {
292         for (auto m : modulePackage_) {
293             m.DisassemblerFunc(addr2name, 0, *(log_), *(logList_), codeStream_);
294         }
295         PrintMergedCodeComment();
296     }
297 
298     void DisassembleAsmStubs(std::map<uintptr_t, std::string> &addr2name);
299     // save function funcs for aot files containing stubs
300     void SaveStubFile(const std::string &filename);
301 protected:
302     void RunLLVMAssembler() override;
303 private:
304     void RunAsmAssembler();
305     void CollectAsmStubCodeInfo(std::map<uintptr_t, std::string> &addr2name, uint32_t bridgeModuleIdx);
306     void CollectCodeInfo();
307 
308     StubFileInfo stubInfo_;
309     AssemblerModule asmModule_;
310     CompilationConfig cfg_;
311     CodeInfo::CodeSpaceOnDemand jitCodeSpace_ {};
312     bool concurrentCompile_ {false};
313 };
314 }  // namespace panda::ecmascript::kungfu
315 #endif // ECMASCRIPT_COMPILER_FILE_GENERATORS_H
316