• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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