1/* 2 * Copyright (c) 2023 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 16namespace panda::libllvmbackend { 17 18void RegisterPasses(llvm::PassInstrumentationCallbacks &passInstrumentation) 19{ 20 auto registerName = [&passInstrumentation](llvm::StringRef className, llvm::StringRef passName) { 21 passInstrumentation.addClassToPassName(className, passName); 22 }; 23 24% PassRegistry::llvm_passes.each do |pass| 25 registerName("<%= PassRegistry::passes_namespace %>::<%= pass.name %>", <%= PassRegistry::passes_namespace %>::<%= pass.name %>::ARG_NAME); 26% end 27} 28 29using StringRef = llvm::StringRef; 30using LLVMCompilerOptions = panda::llvmbackend::LLVMCompilerOptions; 31using PipelineElements = llvm::ArrayRef<llvm::PassBuilder::PipelineElement>; 32 33struct PassParser 34{ 35public: 36 explicit PassParser(panda::llvmbackend::LLVMArkInterface *arkInterface) : arkInterface_{arkInterface} 37 { 38 } 39 40 bool ParseModulePasses(StringRef name, llvm::ModulePassManager &modulePm, const LLVMCompilerOptions &options); 41 bool ParseFunctionPasses(StringRef name, llvm::FunctionPassManager &functionPm, const LLVMCompilerOptions &options); 42 bool ParseSCCPasses(StringRef name, llvm::CGSCCPassManager &sccPm, const LLVMCompilerOptions &options); 43 44 void RegisterParserCallbacks(llvm::PassBuilder &builder, const panda::llvmbackend::LLVMCompilerOptions &options) 45 { 46 builder.registerPipelineParsingCallback( 47 [&](StringRef name, llvm::ModulePassManager &modulePm, PipelineElements /*unused*/) -> bool { 48 return ParseModulePasses(name, modulePm, options); 49 }); 50 builder.registerPipelineParsingCallback( 51 [&](StringRef name, llvm::FunctionPassManager &functionPm, PipelineElements /*unused*/) -> bool { 52 return ParseFunctionPasses(name, functionPm, options); 53 }); 54 builder.registerPipelineParsingCallback( 55 [&](StringRef name, llvm::CGSCCPassManager &sccPm, PipelineElements /*unused*/) -> bool { 56 return ParseSCCPasses(name, sccPm, options); 57 }); 58 } 59private: 60 panda::llvmbackend::LLVMArkInterface *arkInterface_; 61}; 62 63bool PassParser::ParseModulePasses(StringRef name, llvm::ModulePassManager &modulePm, const LLVMCompilerOptions &options) 64{ 65 auto &pm = modulePm; 66 namespace pass = <%= PassRegistry::passes_namespace %>; 67 68% PassRegistry::llvm_passes.select{|p| p.type.include? 'module'}.each do |pass| 69 if (name.equals(pass::<%= pass.name %>::ARG_NAME)) { 70 if (pass::<%= pass.name %>::ShouldInsert(&options)) { 71% if pass.setup == 'default' 72 pm.addPass(pass::<%= pass.name %>()); 73% else 74 pm.addPass(pass::<%= pass.name %>::Create(arkInterface_, &options)); 75% end 76#ifndef NDEBUG 77 pm.addPass(llvm::VerifierPass()); 78#endif 79 } 80 return true; 81 } 82% end 83 84 return false; 85} 86 87bool PassParser::ParseFunctionPasses(StringRef name, llvm::FunctionPassManager &functionPm, const LLVMCompilerOptions &options) 88{ 89 auto &pm = functionPm; 90 namespace pass = <%= PassRegistry::passes_namespace %>; 91 92% PassRegistry::llvm_passes.select{|p| p.type.include? 'function'}.each do |pass| 93 if (name.equals(pass::<%= pass.name %>::ARG_NAME)) { 94 if (pass::<%= pass.name %>::ShouldInsert(&options)) { 95% if pass.setup == 'default' 96 pm.addPass(pass::<%= pass.name %>()); 97% else 98 pm.addPass(pass::<%= pass.name %>::Create(arkInterface_, &options)); 99% end 100#ifndef NDEBUG 101 pm.addPass(llvm::VerifierPass()); 102#endif 103 } 104 return true; 105 } 106% end 107 108 return false; 109} 110 111bool PassParser::ParseSCCPasses(StringRef name, llvm::CGSCCPassManager &sccPm, const LLVMCompilerOptions &options) 112{ 113 auto &pm = sccPm; 114 namespace pass = <%= PassRegistry::passes_namespace %>; 115 116% PassRegistry::llvm_passes.select{|p| p.type.include? 'scc'}.each do |pass| 117 if (name.equals(pass::<%= pass.name %>::ARG_NAME)) { 118 if (pass::<%= pass.name %>::ShouldInsert(&options)) { 119% if pass.setup == 'default' 120 pm.addPass(pass::<%= pass.name %>()); 121% else 122 pm.addPass(pass::<%= pass.name %>::Create(arkInterface_, &options)); 123% end 124 } 125 return true; 126 } 127% end 128 129 return false; 130} 131 132} // namespace panda::libllvmbackend 133