• 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/compiler/aot_file/aot_file_manager.h"
21 #include "ecmascript/compiler/assembler_module.h"
22 #include "ecmascript/compiler/compiler_log.h"
23 #include "ecmascript/compiler/llvm_codegen.h"
24 #include "ecmascript/compiler/llvm_ir_builder.h"
25 
26 namespace panda::ecmascript::kungfu {
27 class Module {
28 public:
29     Module() = default;
Module(LLVMModule * module,LLVMAssembler * assembler)30     Module(LLVMModule *module, LLVMAssembler *assembler)
31         : llvmModule_(module), assembler_(assembler)
32     {
33     }
34 
35     void CollectFuncEntryInfo(std::map<uintptr_t, std::string> &addr2name, StubFileInfo &stubInfo,
36                               uint32_t moduleIndex, const CompilerLog &log);
37 
38     void CollectFuncEntryInfo(std::map<uintptr_t, std::string> &addr2name, AnFileInfo &aotInfo,
39                               uint32_t moduleIndex, const CompilerLog &log);
40 
IsRelaSection(ElfSecName sec)41     bool IsRelaSection(ElfSecName sec) const
42     {
43         return sec == ElfSecName::RELATEXT || sec == ElfSecName::STRTAB || sec == ElfSecName::SYMTAB;
44     }
45 
46     void CollectModuleSectionDes(ModuleSectionDes &moduleDes) const;
47 
48     void CollectAnModuleSectionDes(ModuleSectionDes &moduleDes, uint64_t textOffset,
49         std::vector<LLVMStackMapType::Pc2CallSiteInfo> &pc2CallsiteInfoVec,
50         std::vector<LLVMStackMapType::Pc2Deopt> &pc2DeoptVec) const;
51 
52     void CollectStackMapDes(ModuleSectionDes &moduleDes) const;
53 
54     void CollectAnStackMapDes(ModuleSectionDes& des, uint64_t textOffset,
55         std::vector<LLVMStackMapType::Pc2CallSiteInfo> &pc2CallsiteInfoVec,
56         std::vector<LLVMStackMapType::Pc2Deopt> &pc2DeoptVec) const;
57 
58     uint32_t GetSectionSize(ElfSecName sec) const;
59 
60     uintptr_t GetSectionAddr(ElfSecName sec) const;
61 
GetMergedRODataAddrAndSize()62     std::tuple<uint64_t, uint32_t> GetMergedRODataAddrAndSize() const
63     {
64         uint64_t addr = base::MAX_UINT64_VALUE;
65         uint32_t size = 0;
66         UpdateRODataInfo(addr, size, ElfSecName::RODATA);
67         UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST4);
68         UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST8);
69         UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST16);
70         UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST32);
71         return std::make_tuple(addr, size);
72     }
73 
74     void RunAssembler(const CompilerLog &log, bool fastCompileMode);
75 
76     void DisassemblerFunc(std::map<uintptr_t, std::string> &addr2name, uint64_t textOffset, const CompilerLog &log,
77                           const MethodLogList &logList, std::ostringstream &codeStream);
78 
79     void DestroyModule();
80 
GetModule()81     LLVMModule* GetModule() const
82     {
83         return llvmModule_;
84     }
85 
86 private:
GetTextAddr()87     uintptr_t GetTextAddr() const
88     {
89         return assembler_->GetSectionAddr(ElfSecName::TEXT);
90     }
91 
GetTextSize()92     uint32_t GetTextSize() const
93     {
94         return assembler_->GetSectionSize(ElfSecName::TEXT);
95     }
96 
UpdateRODataInfo(uint64_t & addr,uint32_t & size,ElfSecName sec)97     void UpdateRODataInfo(uint64_t &addr, uint32_t &size, ElfSecName sec) const
98     {
99         uint64_t curSectionAddr = GetSectionAddr(sec);
100         addr = ((curSectionAddr != 0) && (curSectionAddr < addr)) ? curSectionAddr : addr;
101         size += GetSectionSize(sec);
102     }
103 
104     LLVMModule *llvmModule_ {nullptr};
105     LLVMAssembler *assembler_ {nullptr};
106     // record current module first function index in StubFileInfo/AnFileInfo
107     uint32_t startIndex_ {static_cast<uint32_t>(-1)};
108     uint32_t funcCount_ {0};
109 };
110 
111 class FileGenerator {
112 public:
FileGenerator(const CompilerLog * log,const MethodLogList * logList)113     FileGenerator(const CompilerLog *log, const MethodLogList *logList) : log_(log), logList_(logList) {};
~FileGenerator()114     virtual ~FileGenerator()
115     {
116         codeStream_.clear();
117         codeStream_.str("");
118     }
119 
GetLog()120     const CompilerLog GetLog() const
121     {
122         return *log_;
123     }
124 
PrintMergedCodeComment()125     void PrintMergedCodeComment()
126     {
127         LOG_COMPILER(INFO) << "\n" << codeStream_.str();
128     }
129 
130 protected:
131     std::vector<Module> modulePackage_ {};
132     const CompilerLog *log_ {nullptr};
133     const MethodLogList *logList_ {nullptr};
134     std::ostringstream codeStream_;
135 
RunLLVMAssembler()136     void RunLLVMAssembler()
137     {
138         for (auto m : modulePackage_) {
139             m.RunAssembler(*(log_), false);
140         }
141     }
142 
DestroyModule()143     void DestroyModule()
144     {
145         for (auto m : modulePackage_) {
146             m.DestroyModule();
147         }
148     }
149 
150     void CollectStackMapDes(ModuleSectionDes& des);
151 };
152 
153 class AOTFileGenerator : public FileGenerator {
154 public:
AOTFileGenerator(const CompilerLog * log,const MethodLogList * logList,EcmaVM * vm,const std::string & triple)155     AOTFileGenerator(const CompilerLog *log, const MethodLogList *logList, EcmaVM* vm, const std::string &triple)
156         : FileGenerator(log, logList), vm_(vm), cfg_(triple) {}
157 
158     ~AOTFileGenerator() override = default;
159 
160     Module* GetLatestModule();
161 
162     uint32_t GetModuleVecSize() const;
163 
164     Module* AddModule(const std::string &name, const std::string &triple, LOptions option, bool logDebug);
165 
166     void GenerateMethodToEntryIndexMap();
167 
168     void CompileLatestModuleThenDestroy();
169 
170     void DestroyCollectedStackMapInfo();
171 
172     void GenerateMergedStackmapSection();
173 
174     bool CreateDirIfNotExist(const std::string &filename);
175 
176     bool SetFileModeAsDefault(const std::string &filename);
177 
178     // save function for aot files containing normal func translated from JS/TS
179     void SaveAOTFile(const std::string &filename);
180     void SaveSnapshotFile();
181 
GetPc2StackMapVec()182     std::vector<LLVMStackMapType::Pc2CallSiteInfo> &GetPc2StackMapVec()
183     {
184         return pc2CallSiteInfoVec_;
185     }
GetPc2Deopt()186     std::vector<LLVMStackMapType::Pc2Deopt> &GetPc2Deopt()
187     {
188         return pc2DeoptVec_;
189     }
190 
191 private:
192     AnFileInfo aotInfo_;
193     std::vector<LLVMStackMapType::Pc2CallSiteInfo> pc2CallSiteInfoVec_;
194     std::vector<LLVMStackMapType::Pc2Deopt> pc2DeoptVec_;
195     EcmaVM* vm_;
196     CompilationConfig cfg_;
197     // MethodID->EntryIndex
198     std::map<uint32_t, uint32_t> methodToEntryIndexMap_ {};
199 
200     // collect aot component info
201     void CollectCodeInfo(Module *module, uint32_t moduleIdx);
202 
203     uint64_t RollbackTextSize(Module *module);
204 };
205 
206 enum class StubFileKind {
207     BC,
208     COM,
209     BUILTIN
210 };
211 
212 class StubFileGenerator : public FileGenerator {
213 public:
StubFileGenerator(const CompilerLog * log,const MethodLogList * logList,const std::string & triple)214     StubFileGenerator(const CompilerLog *log, const MethodLogList *logList, const std::string &triple)
215         : FileGenerator(log, logList),
216           cfg_(triple)
217     {
218     }
219     ~StubFileGenerator() override = default;
220 
221     Module* AddModule(NativeAreaAllocator *allocator, const std::string &name, const std::string &triple,
222                       LOptions option, bool logDebug, StubFileKind k);
223 
DisassembleEachFunc(std::map<uintptr_t,std::string> & addr2name)224     void DisassembleEachFunc(std::map<uintptr_t, std::string> &addr2name)
225     {
226         for (auto m : modulePackage_) {
227             m.DisassemblerFunc(addr2name, 0, *(log_), *(logList_), codeStream_);
228         }
229         PrintMergedCodeComment();
230     }
231 
232     void DisassembleAsmStubs(std::map<uintptr_t, std::string> &addr2name);
233     // save function funcs for aot files containing stubs
234     void SaveStubFile(const std::string &filename);
235 
236 private:
237     void RunAsmAssembler();
238     void CollectAsmStubCodeInfo(std::map<uintptr_t, std::string> &addr2name, uint32_t bridgeModuleIdx);
239     void CollectCodeInfo();
240 
241     StubFileInfo stubInfo_;
242     AssemblerModule asmModule_;
243     CompilationConfig cfg_;
244 };
245 }  // namespace panda::ecmascript::kungfu
246 #endif // ECMASCRIPT_COMPILER_FILE_GENERATORS_H
247