• 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_PASS_H
17 #define ECMASCRIPT_COMPILER_PASS_H
18 
19 #include "ecmascript/compiler/async_function_lowering.h"
20 #include "ecmascript/compiler/bytecode_circuit_builder.h"
21 #include "ecmascript/compiler/early_elimination.h"
22 #include "ecmascript/compiler/common_stubs.h"
23 #include "ecmascript/compiler/compiler_log.h"
24 #include "ecmascript/compiler/llvm_codegen.h"
25 #include "ecmascript/compiler/scheduler.h"
26 #include "ecmascript/compiler/slowpath_lowering.h"
27 #include "ecmascript/compiler/ts_inline_lowering.h"
28 #include "ecmascript/compiler/ts_type_lowering.h"
29 #include "ecmascript/compiler/type_inference/type_infer.h"
30 #include "ecmascript/compiler/type_lowering.h"
31 #include "ecmascript/compiler/verifier.h"
32 
33 namespace panda::ecmascript::kungfu {
34 class PassInfo;
35 
36 class PassData {
37 public:
38     PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, PassInfo *info, CompilerLog *log,
39              std::string methodName, size_t methodInfoIndex = 0, bool hasTypes = false,
40              const CString &recordName = "", MethodLiteral *methodLiteral = nullptr,
41              uint32_t methodOffset = 0, NativeAreaAllocator *allocator = nullptr)
builder_(builder)42         : builder_(builder), circuit_(circuit), info_(info), log_(log), methodName_(methodName),
43           methodInfoIndex_(methodInfoIndex), hasTypes_(hasTypes), recordName_(recordName),
44           methodLiteral_(methodLiteral), methodOffset_(methodOffset), allocator_(allocator)
45     {
46     }
47 
48     virtual ~PassData() = default;
49 
GetConstScheduleResult()50     const ControlFlowGraph &GetConstScheduleResult() const
51     {
52         return cfg_;
53     }
54 
GetCfg()55     ControlFlowGraph &GetCfg()
56     {
57         return cfg_;
58     }
59 
GetCircuit()60     virtual Circuit* GetCircuit() const
61     {
62         return circuit_;
63     }
64 
GetBuilder()65     BytecodeCircuitBuilder* GetBuilder() const
66     {
67         return builder_;
68     }
69 
GetInfo()70     PassInfo* GetInfo() const
71     {
72         return info_;
73     }
74 
GetCompilerConfig()75     CompilationConfig* GetCompilerConfig() const
76     {
77         return info_->GetCompilerConfig();
78     }
79 
GetTSManager()80     TSManager* GetTSManager() const
81     {
82         return info_->GetTSManager();
83     }
84 
GetJSPandaFile()85     const JSPandaFile* GetJSPandaFile() const
86     {
87         return info_->GetJSPandaFile();
88     }
89 
GetAotModule()90     LLVMModule* GetAotModule() const
91     {
92         return info_->GetAOTModule();
93     }
94 
GetLog()95     CompilerLog* GetLog() const
96     {
97         return log_;
98     }
99 
GetMethodName()100     const std::string& GetMethodName() const
101     {
102         return methodName_;
103     }
104 
GetMethodLiteral()105     const MethodLiteral* GetMethodLiteral() const
106     {
107         return methodLiteral_;
108     }
109 
GetMethodOffset()110     uint32_t GetMethodOffset() const
111     {
112         return methodOffset_;
113     }
114 
GetMethodInfoIndex()115     size_t GetMethodInfoIndex() const
116     {
117         return methodInfoIndex_;
118     }
119 
HasTypes()120     bool HasTypes() const
121     {
122         return hasTypes_;
123     }
124 
GetRecordName()125     const CString &GetRecordName() const
126     {
127         return recordName_;
128     }
129 
GetNativeAreaAllocator()130     NativeAreaAllocator* GetNativeAreaAllocator() const
131     {
132         return allocator_;
133     }
134 
135 private:
136     BytecodeCircuitBuilder *builder_ {nullptr};
137     Circuit *circuit_ {nullptr};
138     ControlFlowGraph cfg_;
139     PassInfo *info_ {nullptr};
140     CompilerLog *log_ {nullptr};
141     std::string methodName_;
142     size_t methodInfoIndex_;
143     bool hasTypes_;
144     const CString &recordName_;
145     MethodLiteral *methodLiteral_ {nullptr};
146     uint32_t methodOffset_;
147     NativeAreaAllocator *allocator_ {nullptr};
148 };
149 
150 template<typename T1>
151 class PassRunner {
152 public:
PassRunner(T1 * data)153     explicit PassRunner(T1* data) : data_(data) {}
154     virtual ~PassRunner() = default;
155     template<typename T2, typename... Args>
RunPass(Args...args)156     bool RunPass(Args... args)
157     {
158         T2 pass;
159         return pass.Run(data_, std::forward<Args>(args)...);
160     }
161 
162 private:
163     T1* data_;
164 };
165 
166 class TypeInferPass {
167 public:
Run(PassData * data)168     bool Run(PassData* data)
169     {
170         TimeScope timescope("TypeInferPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
171         if (data->HasTypes()) {
172             bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
173             TypeInfer typeInfer(data->GetBuilder(), data->GetCircuit(), data->GetInfo(), data->GetMethodInfoIndex(),
174                                 enableLog, data->GetMethodName(), data->GetRecordName());
175             typeInfer.TraverseCircuit();
176         }
177         return true;
178     }
179 };
180 
181 class TSTypeLoweringPass {
182 public:
Run(PassData * data)183     bool Run(PassData *data)
184     {
185         TimeScope timescope("TSTypeLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
186         bool enableLog = data->GetLog()->EnableMethodCIRLog();
187         TSTypeLowering lowering(data->GetCircuit(), data->GetInfo(), enableLog,
188                                 data->GetMethodName());
189         lowering.RunTSTypeLowering();
190         return true;
191     }
192 };
193 
194 class TypeLoweringPass {
195 public:
Run(PassData * data)196     bool Run(PassData *data)
197     {
198         TimeScope timescope("TypeLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
199         bool enableLog = data->GetLog()->EnableMethodCIRLog();
200         TypeLowering lowering(data->GetCircuit(), data->GetCompilerConfig(), data->GetTSManager(),
201                               enableLog, data->GetMethodName());
202         lowering.RunTypeLowering();
203         return true;
204     }
205 };
206 
207 class TSInlineLoweringPass {
208 public:
Run(PassData * data,PassInfo * info)209     bool Run(PassData *data, PassInfo *info)
210     {
211         TimeScope timescope("TSInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
212         bool enableLog = data->GetLog()->EnableMethodCIRLog();
213         TSInlineLowering inlining(data->GetCircuit(), info, enableLog, data->GetMethodName());
214         inlining.RunTSInlineLowering();
215         return true;
216     }
217 };
218 
219 class SlowPathLoweringPass {
220 public:
Run(PassData * data)221     bool Run(PassData* data)
222     {
223         TimeScope timescope("SlowPathLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
224         bool enableLog = data->GetLog()->EnableMethodCIRLog();
225         SlowPathLowering lowering(data->GetCircuit(), data->GetCompilerConfig(), data->GetTSManager(),
226                                   data->GetMethodLiteral(), enableLog, data->GetMethodName());
227         lowering.CallRuntimeLowering();
228         return true;
229     }
230 };
231 
232 class VerifierPass {
233 public:
Run(PassData * data)234     bool Run(PassData* data)
235     {
236         TimeScope timescope("VerifierPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
237         bool enableLog = data->GetLog()->EnableMethodCIRLog();
238         bool isQualified = Verifier::Run(data->GetCircuit(), data->GetMethodName(), enableLog);
239         if (!isQualified) {
240             LOG_FULL(FATAL) << "VerifierPass fail";
241             UNREACHABLE();
242         }
243         return isQualified;
244     }
245 };
246 
247 class EarlyEliminationPass {
248 public:
Run(PassData * data)249     bool Run(PassData* data)
250     {
251         TimeScope timescope("EarlyEliminationPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
252         bool enableLog = data->GetLog()->EnableMethodCIRLog();
253         EarlyElimination(data->GetCircuit(), enableLog, data->GetMethodName(), data->GetNativeAreaAllocator()).Run();
254         return true;
255     }
256 };
257 
258 class SchedulingPass {
259 public:
Run(PassData * data)260     bool Run(PassData* data)
261     {
262         TimeScope timescope("SchedulingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
263         bool enableLog = data->GetLog()->EnableMethodCIRLog();
264         Scheduler::Run(data->GetCircuit(), data->GetCfg(), data->GetMethodName(), enableLog);
265         return true;
266     }
267 };
268 
269 class LLVMIRGenPass {
270 public:
CreateCodeGen(LLVMModule * module,bool enableLog)271     void CreateCodeGen(LLVMModule *module, bool enableLog)
272     {
273         llvmImpl_ = std::make_unique<LLVMIRGeneratorImpl>(module, enableLog);
274     }
275 
Run(PassData * data)276     bool Run(PassData *data)
277     {
278         auto module = data->GetAotModule();
279         TimeScope timescope("LLVMIRGenPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
280         bool enableLog = data->GetLog()->EnableMethodCIRLog();
281         CreateCodeGen(module, enableLog);
282         CodeGenerator codegen(llvmImpl_, data->GetMethodName());
283         codegen.Run(data->GetCircuit(), data->GetConstScheduleResult(), module->GetCompilationConfig(),
284                     data->GetMethodLiteral(), data->GetJSPandaFile());
285         return true;
286     }
287 private:
288     std::unique_ptr<CodeGeneratorImpl> llvmImpl_ {nullptr};
289 };
290 
291 class AsyncFunctionLoweringPass {
292 public:
Run(PassData * data)293     bool Run(PassData* data)
294     {
295         TimeScope timescope("AsyncFunctionLoweringPass", data->GetMethodName(),
296                             data->GetMethodOffset(), data->GetLog());
297         bool enableLog = data->GetLog()->EnableMethodCIRLog();
298         AsyncFunctionLowering lowering(data->GetBuilder(), data->GetCircuit(), data->GetCompilerConfig(),
299                                        enableLog, data->GetMethodName());
300         if (lowering.IsAsyncRelated()) {
301             lowering.ProcessAll();
302         }
303         return true;
304     }
305 };
306 } // namespace panda::ecmascript::kungfu
307 #endif
308