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