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/aot_compilation_env.h"
20 #include "ecmascript/compiler/jit_compilation_env.h"
21 #include "ecmascript/compiler/async_function_lowering.h"
22 #include "ecmascript/compiler/bytecode_circuit_builder.h"
23 #include "ecmascript/compiler/codegen/llvm/llvm_codegen.h"
24 #include "ecmascript/compiler/combined_pass_visitor.h"
25 #include "ecmascript/compiler/compiler_log.h"
26 #include "ecmascript/compiler/constant_folding.h"
27 #include "ecmascript/compiler/dead_code_elimination.h"
28 #include "ecmascript/compiler/early_elimination.h"
29 #include "ecmascript/compiler/escape_analysis.h"
30 #include "ecmascript/compiler/escape_analysis_editor.h"
31 #include "ecmascript/compiler/graph_editor.h"
32 #include "ecmascript/compiler/graph_linearizer.h"
33 #include "ecmascript/compiler/induction_variable_analysis.h"
34 #include "ecmascript/compiler/later_elimination.h"
35 #include "ecmascript/compiler/mcr_lowering.h"
36 #include "ecmascript/compiler/lexical_env_specialization_pass.h"
37 #include "ecmascript/compiler/loop_analysis.h"
38 #include "ecmascript/compiler/loop_peeling.h"
39 #include "ecmascript/compiler/native_inline_lowering.h"
40 #include "ecmascript/compiler/ntype_bytecode_lowering.h"
41 #include "ecmascript/compiler/ntype_hcr_lowering.h"
42 #include "ecmascript/compiler/number_speculative_runner.h"
43 #include "ecmascript/compiler/post_schedule.h"
44 #include "ecmascript/compiler/precompile_checker.h"
45 #include "ecmascript/compiler/scheduler.h"
46 #include "ecmascript/compiler/string_builder_optimizer.h"
47 #include "ecmascript/compiler/slowpath_lowering.h"
48 #include "ecmascript/compiler/state_split_linearizer.h"
49 #include "ecmascript/compiler/ts_inline_lowering.h"
50 #include "ecmascript/compiler/typed_bytecode_lowering.h"
51 #include "ecmascript/compiler/ts_hcr_opt_pass.h"
52 #include "ecmascript/compiler/type_inference/pgo_type_infer.h"
53 #include "ecmascript/compiler/typed_hcr_lowering.h"
54 #include "ecmascript/compiler/typed_native_inline_lowering.h"
55 #include "ecmascript/compiler/useless_gate_elimination.h"
56 #include "ecmascript/compiler/value_numbering.h"
57 #include "ecmascript/compiler/instruction_combine.h"
58 #include "ecmascript/compiler/verifier.h"
59 #include "ecmascript/js_runtime_options.h"
60 
61 #ifdef COMPILE_MAPLE
62 #include "ecmascript/compiler/codegen/maple/litecg_codegen.h"
63 #include "litecg.h"
64 #include "lmir_builder.h"
65 #endif
66 
67 namespace panda::ecmascript::kungfu {
68 class PassContext;
69 
70 class PassData {
71 public:
PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, PassContext *ctx, CompilerLog *log, std::string methodName, MethodInfo *methodInfo = nullptr, const CString &recordName = �, MethodLiteral *methodLiteral = nullptr, uint32_t methodOffset = 0, CallMethodFlagMap *callMethodFlagMap = nullptr, const CVector<AbcFileInfo> &fileInfos = CVector<AbcFileInfo>{}, NativeAreaAllocator *allocator = nullptr, PGOProfilerDecoder *decoder = nullptr, PassOptions *passOptions = nullptr, std::string optBCRange = �)72     PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, PassContext *ctx, CompilerLog *log,
73              std::string methodName, MethodInfo *methodInfo = nullptr,
74              const CString &recordName = "", MethodLiteral *methodLiteral = nullptr,
75              uint32_t methodOffset = 0, CallMethodFlagMap *callMethodFlagMap = nullptr,
76              const CVector<AbcFileInfo> &fileInfos = CVector<AbcFileInfo>{}, NativeAreaAllocator *allocator = nullptr,
77              PGOProfilerDecoder *decoder = nullptr, PassOptions *passOptions = nullptr,
78              std::string optBCRange = "")
79         : builder_(builder), circuit_(circuit), ctx_(ctx), log_(log), methodName_(methodName),
80           methodInfo_(methodInfo), recordName_(recordName), methodLiteral_(methodLiteral),
81           methodOffset_(methodOffset), callMethodFlagMap_(callMethodFlagMap), fileInfos_(fileInfos),
82           allocator_(allocator), decoder_(decoder), passOptions_(passOptions),
83           optBCRange_(optBCRange)
84     {
85     }
86 
87     virtual ~PassData() = default;
88 
GetConstScheduleResult() const89     const ControlFlowGraph &GetConstScheduleResult() const
90     {
91         return cfg_;
92     }
93 
GetCfg()94     ControlFlowGraph &GetCfg()
95     {
96         return cfg_;
97     }
98 
GetCircuit() const99     virtual Circuit* GetCircuit() const
100     {
101         return circuit_;
102     }
103 
GetBuilder() const104     BytecodeCircuitBuilder* GetBuilder() const
105     {
106         return builder_;
107     }
108 
GetPassContext() const109     PassContext* GetPassContext() const
110     {
111         return ctx_;
112     }
113 
GetCompilerConfig() const114     CompilationConfig* GetCompilerConfig() const
115     {
116         return ctx_->GetCompilerConfig();
117     }
118 
GetPTManager() const119     PGOTypeManager* GetPTManager() const
120     {
121         return ctx_->GetPTManager();
122     }
123 
GetJSPandaFile() const124     const JSPandaFile *GetJSPandaFile() const
125     {
126         return ctx_->GetJSPandaFile();
127     }
128 
GetAotModule() const129     IRModule* GetAotModule() const
130     {
131         return ctx_->GetAOTModule();
132     }
133 
GetLog() const134     CompilerLog* GetLog() const
135     {
136         return log_;
137     }
138 
GetMethodName() const139     const std::string& GetMethodName() const
140     {
141         return methodName_;
142     }
143 
GetMethodLiteral() const144     const MethodLiteral* GetMethodLiteral() const
145     {
146         return methodLiteral_;
147     }
148 
GetMethodOffset() const149     uint32_t GetMethodOffset() const
150     {
151         return methodOffset_;
152     }
153 
GetMethodInfo() const154     MethodInfo* GetMethodInfo() const
155     {
156         return methodInfo_;
157     }
158 
GetMethodInfoIndex() const159     size_t GetMethodInfoIndex() const
160     {
161         return methodInfo_->GetMethodInfoIndex();
162     }
163 
GetRecordName() const164     const CString &GetRecordName() const
165     {
166         return recordName_;
167     }
168 
GetNativeAreaAllocator() const169     NativeAreaAllocator* GetNativeAreaAllocator() const
170     {
171         return allocator_;
172     }
173 
GetPGOProfilerDecoder() const174     PGOProfilerDecoder *GetPGOProfilerDecoder() const
175     {
176         return decoder_;
177     }
178 
GetPassOptions() const179     PassOptions *GetPassOptions() const
180     {
181         return passOptions_;
182     }
183 
GetOptBCRange() const184     std::string GetOptBCRange() const
185     {
186         return optBCRange_;
187     }
188 
GetCallMethodFlagMap()189     CallMethodFlagMap *GetCallMethodFlagMap()
190     {
191         return callMethodFlagMap_;
192     }
193 
GetFileInfos() const194     const CVector<AbcFileInfo> &GetFileInfos() const
195     {
196         return fileInfos_;
197     }
198 
AbortCompilation()199     void AbortCompilation()
200     {
201         ctx_->GetBytecodeInfo().AddSkippedMethod(methodOffset_);
202         methodInfo_->SetIsCompiled(false);
203         log_->RemoveCompiledMethod(methodName_, recordName_);
204     }
205 
206 private:
207     BytecodeCircuitBuilder *builder_ {nullptr};
208     Circuit *circuit_ {nullptr};
209     ControlFlowGraph cfg_;
210     PassContext *ctx_ {nullptr};
211     CompilerLog *log_ {nullptr};
212     std::string methodName_;
213     MethodInfo *methodInfo_ {nullptr};
214     const CString &recordName_;
215     MethodLiteral *methodLiteral_ {nullptr};
216     uint32_t methodOffset_;
217     CallMethodFlagMap *callMethodFlagMap_ {nullptr};
218     const CVector<AbcFileInfo> &fileInfos_;
219     NativeAreaAllocator *allocator_ {nullptr};
220     PGOProfilerDecoder *decoder_ {nullptr};
221     PassOptions *passOptions_ {nullptr};
222     std::string optBCRange_;
223 };
224 
225 template<typename T1>
226 class PassRunner {
227 public:
PassRunner(T1* data)228     explicit PassRunner(T1* data) : data_(data) {}
229     virtual ~PassRunner() = default;
230     template<typename T2, typename... Args>
RunPass(Args.... args)231     bool RunPass(Args... args)
232     {
233         T2 pass;
234         return pass.Run(data_, std::forward<Args>(args)...);
235     }
236 
237 private:
238     T1* data_;
239 };
240 
241 class PreCompileCheckPass {
242 public:
Run(PassData* data)243     bool Run(PassData* data)
244     {
245         TimeScope timescope("PreCompileCheckPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
246         bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
247         PreCompileChecker preCompileChecker(data, data->GetCircuit(), data->GetMethodName(), enableLog);
248         if (!preCompileChecker.Run()) {
249             data->AbortCompilation();
250             return false;
251         }
252         return true;
253     }
254 };
255 
256 class PGOTypeInferPass {
257 public:
Run(PassData* data)258     bool Run(PassData* data)
259     {
260         TimeScope timescope("PGOTypeInferPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
261         bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
262         Chunk chunk(data->GetNativeAreaAllocator());
263         PGOTypeInfer pgoTypeInfer(data->GetCircuit(), data->GetBuilder(), data->GetMethodName(), &chunk, enableLog);
264         pgoTypeInfer.Run();
265         return true;
266     }
267 };
268 
269 class EscapeAnalysisPass {
270 public:
Run(PassData *data)271     bool Run(PassData *data)
272     {
273         PassOptions *passOptions = data->GetPassOptions();
274         if (!passOptions->EnableEscapeAnalysis()) {
275             return false;
276         }
277         TimeScope timescope("EscapeAnalysisPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
278         bool enableLog = data->GetLog()->EnableMethodCIRLog();
279         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
280         Chunk chunk(data->GetNativeAreaAllocator());
281         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
282         EscapeAnalysis escapeAnalysis(data->GetCircuit(), &visitor, &chunk, runtimeOption.GetTraceEscapeAnalysis());
283         visitor.AddPass(&escapeAnalysis);
284         visitor.VisitGraph();
285         CombinedPassVisitor Editvisitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
286         EscapeAnalysisEditor escapeAnalysisEditor(data->GetCircuit(), &visitor, &chunk,
287                                                   &escapeAnalysis, runtimeOption.GetTraceEscapeAnalysis());
288         Editvisitor.AddPass(&escapeAnalysisEditor);
289         Editvisitor.VisitGraph();
290         visitor.PrintLog("escape Analysis");
291         return true;
292     }
293 };
294 
295 class InductionVariableAnalysisPass {
296 public:
Run(PassData *data)297     bool Run(PassData *data)
298     {
299         PassOptions *passOptions = data->GetPassOptions();
300         if (!passOptions->EnableInductionVariableAnalysis()) {
301             return false;
302         }
303         TimeScope timescope("InductionVariableAnalysisPass", data->GetMethodName(),
304                             data->GetMethodOffset(), data->GetLog());
305         bool enableLog = data->GetLog()->EnableMethodCIRLog();
306         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
307         Chunk chunk(data->GetNativeAreaAllocator());
308         InductionVariableAnalysis inductionVariableAnalysis(data->GetCircuit(), data->GetPassContext(), enableLog,
309                                                             data->GetMethodName(), &chunk,
310                                                             runtimeOption.GetTraceInductionVariableAnalysis());
311         inductionVariableAnalysis.Run();
312         return true;
313     }
314 };
315 
316 class TypeBytecodeLoweringPass {
317 public:
Run(PassData* data)318     bool Run(PassData* data)
319     {
320         PassOptions *passOptions = data->GetPassOptions();
321         if (!passOptions->EnableTypeLowering()) {
322             return false;
323         }
324         TimeScope timescope("TypeBytecodeLoweringPass", data->GetMethodName(),
325             data->GetMethodOffset(), data->GetLog());
326         bool enableLog = data->GetLog()->EnableMethodCIRLog();
327         bool enableTypeLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
328         Chunk chunk(data->GetNativeAreaAllocator());
329         TypedBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), &chunk,
330                                       enableLog,
331                                       enableTypeLog,
332                                       data->GetMethodName(),
333                                       passOptions->EnableLoweringBuiltin(),
334                                       data->GetRecordName(),
335                                       data->GetCallMethodFlagMap(),
336                                       data->GetPGOProfilerDecoder(),
337                                       data->GetOptBCRange(),
338                                       data->GetMethodLiteral());
339         lowering.RunTypedBytecodeLowering();
340         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
341         DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk);
342         TSHCROptPass optimization(data->GetCircuit(), &visitor, &chunk, data->GetPassContext(), enableLog,
343                                   data->GetMethodName());
344 
345         visitor.AddPass(&optimization);
346         visitor.AddPass(&deadCodeElimination);
347         visitor.VisitGraph();
348         visitor.PrintLog("TSHCROptPass");
349         return true;
350     }
351 };
352 
353 class NTypeBytecodeLoweringPass {
354 public:
Run(PassData* data)355     bool Run(PassData* data)
356     {
357         PassOptions *passOptions = data->GetPassOptions();
358         if (!passOptions->EnableTypeLowering()) {
359             return false;
360         }
361         TimeScope timescope("NTypeBytecodeLoweringPass", data->GetMethodName(),
362             data->GetMethodOffset(), data->GetLog());
363         bool enableLog = data->GetLog()->EnableMethodCIRLog();
364         NTypeBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(),
365                                        data->GetRecordName());
366         lowering.RunNTypeBytecodeLowering();
367         Chunk chunk(data->GetNativeAreaAllocator());
368         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
369         DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk);
370         visitor.AddPass(&deadCodeElimination);
371         visitor.VisitGraph();
372         return true;
373     }
374 };
375 
376 class StringOptimizationPass {
377 public:
Run(PassData* data)378     bool Run(PassData* data)
379     {
380         PassOptions *passOptions = data->GetPassOptions();
381         if (!passOptions->EnableOptString()) {
382             return false;
383         }
384         TimeScope timescope("StringOptimizationPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
385         bool enableLog = data->GetLog()->EnableMethodCIRLog();
386         Chunk chunk(data->GetNativeAreaAllocator());
387         StringBuilderOptimizer stringBuilder(data->GetCircuit(),
388                                              enableLog,
389                                              data->GetMethodName(),
390                                              data->GetCompilerConfig(),
391                                              &chunk);
392         stringBuilder.Run();
393         return true;
394     }
395 };
396 
397 class TypeHCRLoweringPass {
398 public:
Run(PassData* data)399     bool Run(PassData* data)
400     {
401         PassOptions *passOptions = data->GetPassOptions();
402         if (!passOptions->EnableTypeLowering()) {
403             return false;
404         }
405         {
406             TimeScope timescope("TypeHCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
407             bool enableLog = data->GetLog()->EnableMethodCIRLog();
408             Chunk chunk(data->GetNativeAreaAllocator());
409             CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
410             TypedHCRLowering lowering(data->GetCircuit(),
411                                     data->GetPassContext()->GetCompilationEnv(),
412                                     &visitor,
413                                     data->GetCompilerConfig(),
414                                     &chunk,
415                                     passOptions->EnableLoweringBuiltin());
416             visitor.AddPass(&lowering);
417             visitor.VisitGraph();
418             visitor.PrintLog("TypedHCRLowering");
419         }
420 
421         {
422             TimeScope timescope("TypedNativeInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(),
423                                 data->GetLog());
424             bool enableLog = data->GetLog()->EnableMethodCIRLog();
425             Chunk chunk(data->GetNativeAreaAllocator());
426             CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
427             TypedNativeInlineLowering lowering(data->GetCircuit(),
428                                                &visitor,
429                                                data->GetPassContext(),
430                                                data->GetCompilerConfig(),
431                                                &chunk);
432             visitor.AddPass(&lowering);
433             visitor.VisitGraph();
434             visitor.PrintLog("TypedNativeInlineLowering");
435         }
436 
437         return true;
438     }
439 };
440 
441 class NTypeHCRLoweringPass {
442 public:
Run(PassData* data)443     bool Run(PassData* data)
444     {
445         PassOptions *passOptions = data->GetPassOptions();
446         if (!passOptions->EnableTypeLowering()) {
447             return false;
448         }
449         TimeScope timescope("NTypeHCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
450         bool enableLog = data->GetLog()->EnableMethodCIRLog();
451         Chunk chunk(data->GetNativeAreaAllocator());
452         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
453         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
454         NTypeHCRLowering lowering(data->GetCircuit(), &visitor, data->GetPassContext(),
455             data->GetRecordName(), data->GetMethodLiteral(), runtimeOption.IsCompilerEnablePgoSpace(), &chunk);
456         visitor.AddPass(&lowering);
457         visitor.VisitGraph();
458         visitor.PrintLog("NTypeHCRLowering");
459         return true;
460     }
461 };
462 
463 class LCRLoweringPass {
464 public:
Run(PassData* data)465     bool Run(PassData* data)
466     {
467         PassOptions *passOptions = data->GetPassOptions();
468         if (!passOptions->EnableTypeLowering()) {
469             return false;
470         }
471         TimeScope timescope("LCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
472         bool enableLog = data->GetLog()->EnableMethodCIRLog();
473         Chunk chunk(data->GetNativeAreaAllocator());
474         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
475         MCRLowering lowering(data->GetPassContext()->GetCompilationEnv(), data->GetCircuit(), &visitor,
476                              data->GetCompilerConfig(), &chunk);
477         visitor.AddPass(&lowering);
478         visitor.VisitGraph();
479         visitor.PrintLog("MCRLowering");
480         return true;
481     }
482 };
483 
484 class TSInlineLoweringPass {
485 public:
Run(PassData* data)486     bool Run(PassData* data)
487     {
488         PassOptions *passOptions = data->GetPassOptions();
489         if (!passOptions->EnableOptInlining() || !passOptions->EnableTypeLowering()) {
490             return false;
491         }
492         TimeScope timescope("TSInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
493         bool enableLog = data->GetLog()->EnableMethodCIRLog();
494         TSInlineLowering inlining(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(),
495                                   data->GetNativeAreaAllocator(), passOptions, data->GetMethodOffset(),
496                                   data->GetCallMethodFlagMap());
497         inlining.RunTSInlineLowering();
498         Chunk chunk(data->GetNativeAreaAllocator());
499         if (passOptions->EnableLexenvSpecialization()) {
500             {
501                 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
502                 GetEnvSpecializationPass getEnvSpecializationPass(data->GetCircuit(), &visitor, &chunk);
503                 visitor.AddPass(&getEnvSpecializationPass);
504                 visitor.VisitGraph();
505                 visitor.PrintLog("getEnvSpecializationPass");
506             }
507             {
508                 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
509                 LexicalEnvSpecializationPass lexicalEnvSpecializationPass(data->GetCircuit(), &visitor, &chunk,
510                                                                           enableLog);
511                 visitor.AddPass(&lexicalEnvSpecializationPass);
512                 visitor.VisitGraph();
513                 visitor.PrintLog("lexicalEnvSpecialization");
514                 lexicalEnvSpecializationPass.PrintSpecializeId();
515             }
516         }
517 
518         if (passOptions->EnableInlineNative()) {
519             NativeInlineLowering nativeInline(data->GetCircuit(), data->GetCompilerConfig(), data->GetPassContext(),
520                                               enableLog, data->GetMethodName(), &chunk);
521             nativeInline.RunNativeInlineLowering();
522         }
523         return true;
524     }
525 };
526 
527 class SlowPathLoweringPass {
528 public:
Run(PassData* data)529     bool Run(PassData* data)
530     {
531         TimeScope timescope("SlowPathLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
532         bool enableLog = data->GetLog()->EnableMethodCIRLog();
533         SlowPathLowering lowering(data->GetCircuit(), data->GetCompilerConfig(), data->GetPassContext(),
534                                   data->GetMethodLiteral(), enableLog, data->GetMethodName());
535         lowering.CallRuntimeLowering();
536         return true;
537     }
538 };
539 
540 class RunFlowCyclesVerifierPass {
541 public:
Run(PassData* data)542     bool Run(PassData* data)
543     {
544         TimeScope timescope("FlowCyclesVerifierPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
545         bool hasFlowCycle = Verifier::RunFlowCyclesFind(data->GetCircuit());
546         if (hasFlowCycle) {
547             LOG_FULL(FATAL) << "FlowCyclesVerifierPass fail";
548             UNREACHABLE();
549         }
550         return !hasFlowCycle;
551     }
552 };
553 
554 class VerifierPass {
555 public:
Run(PassData* data)556     bool Run(PassData* data)
557     {
558         TimeScope timescope("VerifierPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
559         bool enableLog = data->GetLog()->EnableMethodCIRLog();
560         bool isQualified = Verifier::Run(data->GetCircuit(), data->GetMethodName(), enableLog);
561         if (!isQualified) {
562             LOG_FULL(FATAL) << "VerifierPass fail";
563             UNREACHABLE();
564         }
565         return isQualified;
566     }
567 };
568 
569 class NumberSpeculativePass {
570 public:
Run(PassData* data)571     bool Run(PassData* data)
572     {
573         PassOptions *passOptions = data->GetPassOptions();
574         if (!passOptions->EnableTypeLowering()) {
575             return false;
576         }
577         TimeScope timescope("NumberSpeculativePass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
578         Chunk chunk(data->GetNativeAreaAllocator());
579         bool enableLog = data->GetLog()->EnableMethodCIRLog();
580         bool enableArrayBoundsCheckElimination = passOptions->EnableArrayBoundsCheckElimination();
581         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
582         NumberSpeculativeRunner(data->GetCircuit(), enableLog, enableArrayBoundsCheckElimination,
583                                 data->GetMethodName(), &chunk).Run();
584         return true;
585     }
586 };
587 
588 class ConstantFoldingPass {
589 public:
Run(PassData* data)590     bool Run(PassData* data)
591     {
592         PassOptions *passOptions = data->GetPassOptions();
593         if (!passOptions->EnableOptConstantFolding()) {
594             return false;
595         }
596         TimeScope timescope("ConstantFoldingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
597         Chunk chunk(data->GetNativeAreaAllocator());
598         bool enableLog = data->GetLog()->EnableMethodCIRLog();
599         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
600         ConstantFolding constantFolding(data->GetCircuit(), &visitor, data->GetCompilerConfig(), enableLog,
601                                         data->GetMethodName(), &chunk);
602         visitor.AddPass(&constantFolding);
603         visitor.VisitGraph();
604         constantFolding.Print();
605         return true;
606     }
607 };
608 
609 class LoopOptimizationPass {
610 public:
Run(PassData* data)611     bool Run(PassData* data)
612     {
613         TimeScope timescope("LoopOptimizationPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
614         Chunk chunk(data->GetNativeAreaAllocator());
615         LoopAnalysis loopAnalysis(data->GetBuilder(), data->GetCircuit(), &chunk);
616         loopAnalysis.Run();
617         bool enableLog = data->GetLog()->EnableMethodCIRLog();
618         for (auto loopInfo : loopAnalysis.GetLoopTree()) {
619             loopAnalysis.CollectLoopBody(loopInfo);
620             if (enableLog) {
621                 loopAnalysis.PrintLoop(loopInfo);
622             }
623             if (data->GetPassOptions()->EnableOptLoopPeeling()) {
624                 LoopPeeling(data->GetBuilder(), data->GetCircuit(), enableLog,
625                             data->GetMethodName(), &chunk, loopInfo).Peel();
626             }
627         }
628         loopAnalysis.LoopExitElimination();
629         return true;
630     }
631 };
632 
633 class RedundantPhiEliminationPass {
634 public:
Run(PassData* data)635     bool Run(PassData* data)
636     {
637         TimeScope timescope("RedundantPhiEliminationPass", data->GetMethodName(),
638             data->GetMethodOffset(), data->GetLog());
639         bool enableLog = data->GetLog()->EnableMethodCIRLog();
640         GraphEditor::EliminateRedundantPhi(data->GetCircuit(), enableLog, data->GetMethodName());
641         return true;
642     }
643 };
644 
645 class EarlyEliminationPass {
646 public:
Run(PassData* data)647     bool Run(PassData* data)
648     {
649         PassOptions *passOptions = data->GetPassOptions();
650         if (!passOptions->EnableTypeLowering() || !passOptions->EnableEarlyElimination()) {
651             return false;
652         }
653         TimeScope timescope("EarlyEliminationPass", data->GetMethodName(),
654                             data->GetMethodOffset(), data->GetLog());
655         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
656         Chunk chunk(data->GetNativeAreaAllocator());
657         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
658         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
659         EarlyElimination earlyElimination(data->GetCircuit(), &visitor, &chunk,
660             runtimeOption.IsEnableMemoryAnalysis(), runtimeOption.IsEnableFrameStateElimination());
661         visitor.AddPass(&earlyElimination);
662         visitor.VisitGraph();
663         visitor.PrintLog("early elimination");
664         return true;
665     }
666 };
667 
668 class LaterEliminationPass {
669 public:
Run(PassData* data)670     bool Run(PassData* data)
671     {
672         PassOptions *passOptions = data->GetPassOptions();
673         if (!passOptions->EnableTypeLowering() || !passOptions->EnableLaterElimination()) {
674             return false;
675         }
676         TimeScope timescope("LaterEliminationPass", data->GetMethodName(),
677                             data->GetMethodOffset(), data->GetLog());
678         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
679         Chunk chunk(data->GetNativeAreaAllocator());
680         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
681         LaterElimination laterElimination(data->GetCircuit(), &visitor, &chunk);
682         visitor.AddPass(&laterElimination);
683         visitor.VisitGraph();
684         visitor.PrintLog("later elimination");
685         return true;
686     }
687 };
688 
689 class UselessGateEliminationPass {
690 public:
Run(PassData* data)691     bool Run(PassData* data)
692     {
693         TimeScope timescope("UselessGateEliminationPass", data->GetMethodName(),
694                             data->GetMethodOffset(), data->GetLog());
695         bool enableLog = data->GetLog()->EnableMethodCIRLog();
696         UselessGateElimination uselessGateElimination(data->GetCircuit(), enableLog, data->GetMethodName());
697         uselessGateElimination.Run();
698         return true;
699     }
700 };
701 
702 class ValueNumberingPass {
703 public:
Run(PassData* data)704     bool Run(PassData* data)
705     {
706         PassOptions *passOptions = data->GetPassOptions();
707         if (!passOptions->EnableTypeLowering() || !passOptions->EnableValueNumbering()) {
708             return false;
709         }
710         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
711         TimeScope timescope("ValueNumberingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
712         Chunk chunk(data->GetNativeAreaAllocator());
713         bool enableLog = data->GetLog()->EnableMethodCIRLog();
714         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
715         ValueNumbering valueNumbering(data->GetCircuit(), &visitor, &chunk,
716                                       runtimeOption.IsEnableNewValueNumbering(),
717                                       runtimeOption.GetTraceValueNumbering());
718         visitor.AddPass(&valueNumbering);
719         visitor.VisitGraph();
720         visitor.PrintLog("value numbering");
721         return true;
722     }
723 };
724 
725 class InstructionCombinePass {
726 public:
Run(PassData *data)727     bool Run(PassData *data)
728     {
729         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions();
730         if (runtimeOption.IsEnableInstrcutionCombine()) {
731             TimeScope timescope("InstructionCombinePass", data->GetMethodName(), data->GetMethodOffset(),
732                                 data->GetLog());
733             Chunk chunk(data->GetNativeAreaAllocator());
734             bool enableLog = data->GetLog()->EnableMethodCIRLog();
735             CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
736             InstructionCombine instructionCombine(data->GetCircuit(), &visitor, &chunk,
737                                                   runtimeOption.GetTraceInstructionCombine());
738             visitor.AddPass(&instructionCombine);
739             visitor.VisitGraph();
740             visitor.PrintLog("Instruction Combine");
741         }
742         return true;
743     }
744 };
745 
746 class SchedulingPass {
747 public:
Run(PassData* data)748     bool Run(PassData* data)
749     {
750         TimeScope timescope("SchedulingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
751         bool enableLog = data->GetLog()->EnableMethodCIRLog();
752         Scheduler::Run(data->GetCircuit(), data->GetCfg(), data->GetMethodName(), enableLog);
753         Chunk chunk(data->GetNativeAreaAllocator());
754         PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, true).Run(data->GetCfg());
755         return true;
756     }
757 };
758 
759 class StateSplitLinearizerPass {
760 public:
Run(PassData* data)761     bool Run(PassData* data)
762     {
763         PassOptions *passOptions = data->GetPassOptions();
764         if (!passOptions->EnableTypeLowering()) {
765             return false;
766         }
767         TimeScope timescope("StateSplitLinearizerPass", data->GetMethodName(),
768                             data->GetMethodOffset(), data->GetLog());
769         Chunk chunk(data->GetNativeAreaAllocator());
770         bool enableLog = data->GetLog()->EnableMethodCIRLog();
771         StateSplitLinearizer(data->GetPassContext()->GetCompilationEnv(), data->GetCircuit(), nullptr,
772                              data->GetCompilerConfig(), enableLog, data->GetMethodName(), &chunk)
773             .Run();
774         return true;
775     }
776 };
777 
778 class GraphLinearizerPass {
779 public:
Run(PassData* data)780     bool Run(PassData* data)
781     {
782         TimeScope timescope("GraphLinearizerPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
783         Chunk chunk(data->GetNativeAreaAllocator());
784         bool enableLog = data->GetLog()->EnableMethodCIRLog();
785         bool licm = data->GetPassOptions()->EnableOptLoopInvariantCodeMotion();
786         bool liteCG = data->GetPassContext()->GetCompilationEnv()->GetJSOptions().IsCompilerEnableLiteCG();
787         GraphLinearizer(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, false, licm, liteCG)
788             .Run(data->GetCfg());
789         PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk).Run(data->GetCfg());
790         return true;
791     }
792 };
793 
794 class CGIRGenPass {
795 public:
CreateCodeGen(IRModule *module, bool enableLog)796     void CreateCodeGen(IRModule *module, bool enableLog)
797     {
798 #ifdef COMPILE_MAPLE
799         if (module->GetModuleKind() == MODULE_LLVM) {
800             cgImpl_ = std::make_unique<LLVMIRGeneratorImpl>(static_cast<LLVMModule*>(module), enableLog);
801         } else {
802             cgImpl_ = std::make_unique<LiteCGIRGeneratorImpl>(static_cast<LMIRModule*>(module), enableLog);
803         }
804 #else
805         cgImpl_ = std::make_unique<LLVMIRGeneratorImpl>(static_cast<LLVMModule*>(module), enableLog);
806 #endif
807     }
Run(PassData *data)808     bool Run(PassData *data)
809     {
810         auto module = data->GetAotModule();
811         TimeScope timescope("CGIRGenPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
812         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
813         PassOptions *passOptions = data->GetPassOptions();
814         bool enableOptInlining = passOptions->EnableOptInlining() && passOptions->EnableTypeLowering();
815         bool enableOptBranchProfiling = passOptions->EnableOptBranchProfiling();
816         CreateCodeGen(module, enableLog);
817         CodeGenerator codegen(cgImpl_, data->GetMethodName());
818         codegen.Run(data->GetCircuit(), data->GetConstScheduleResult(), data->GetCompilerConfig(),
819                     data->GetMethodLiteral(), data->GetJSPandaFile(), data->GetCircuit()->GetFrameType(),
820                     enableOptInlining, enableOptBranchProfiling);
821         return true;
822     }
823 private:
824     std::unique_ptr<CodeGeneratorImpl> cgImpl_ {nullptr};
825 };
826 
827 class AsyncFunctionLoweringPass {
828 public:
Run(PassData* data)829     bool Run(PassData* data)
830     {
831         TimeScope timescope("AsyncFunctionLoweringPass", data->GetMethodName(),
832                             data->GetMethodOffset(), data->GetLog());
833         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
834         AsyncFunctionLowering lowering(data->GetBuilder(), data->GetCircuit(), data->GetCompilerConfig(),
835                                        enableLog, data->GetMethodName());
836         if (lowering.IsAsyncRelated()) {
837             lowering.ProcessAll();
838         }
839         return true;
840     }
841 
842 private:
IsFunctionMain(PassData* data)843     bool IsFunctionMain(PassData* data)
844     {
845         auto methodName = data->GetMethodName();
846         auto pos = methodName.find(JSPandaFile::ENTRY_FUNCTION_NAME);
847         if (pos != std::string::npos) {
848             return true;
849         }
850         return false;
851     }
852 };
853 } // namespace panda::ecmascript::kungfu
854 #endif
855