• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 LIBLLVMBACKEND_LLVM_AOT_COMPILER_H
17 #define LIBLLVMBACKEND_LLVM_AOT_COMPILER_H
18 
19 #include "compiler/code_info/code_info_builder.h"
20 #include "compiler/optimizer/ir/runtime_interface.h"
21 
22 #include "llvm_compiler.h"
23 #include "lowering/debug_data_builder.h"
24 #include "lowering/wrapped_module.h"
25 #include "object_code/ark_aot_linker.h"
26 #include "object_code/code_info_producer.h"
27 
28 #include <llvm/Object/StackMapParser.h>
29 #include <llvm/Support/Mutex.h>
30 #include <llvm/Support/ThreadPool.h>
31 
32 namespace ark::compiler {
33 class LLVMAotBuilder;
34 class CompiledMethod;
35 class Graph;
36 }  // namespace ark::compiler
37 
38 namespace ark::llvmbackend {
39 
40 /// Spreads methods to compile between modules
41 class Spreader {
42 public:
43     Spreader() = default;
44     virtual std::shared_ptr<WrappedModule> GetModuleForMethod(compiler::RuntimeInterface::MethodPtr method) = 0;
45 
46     /// Returns all modules, that this spreader has created
47     virtual std::unordered_set<std::shared_ptr<WrappedModule>> GetModules() = 0;
48 
49     virtual ~Spreader() = default;
50 
51     NO_COPY_SEMANTIC(Spreader);
52     NO_MOVE_SEMANTIC(Spreader);
53 };
54 
55 class AotBuilderOffsets {
56 public:
AotBuilderOffsets(std::unordered_map<std::string,size_t> sectionAddresses,std::unordered_map<std::string,size_t> methodOffsets)57     AotBuilderOffsets(std::unordered_map<std::string, size_t> sectionAddresses,
58                       std::unordered_map<std::string, size_t> methodOffsets)
59         : sectionAddresses_(std::move(sectionAddresses)), methodOffsets_(std::move(methodOffsets))
60     {
61     }
62 
GetSectionAddresses()63     const std::unordered_map<std::string, size_t> &GetSectionAddresses() const
64     {
65         return sectionAddresses_;
66     }
67 
GetMethodOffsets()68     const std::unordered_map<std::string, size_t> &GetMethodOffsets() const
69     {
70         return methodOffsets_;
71     }
72 
73 private:
74     std::unordered_map<std::string, size_t> sectionAddresses_;
75     std::unordered_map<std::string, size_t> methodOffsets_;
76 };
77 
78 class LLVMAotCompiler final : public LLVMCompiler {
79 public:
80     explicit LLVMAotCompiler(compiler::RuntimeInterface *runtime, ArenaAllocator *allocator,
81                              compiler::LLVMAotBuilder *aotBuilder, std::string cmdline, std::string filename);
82 
83     Expected<bool, std::string> TryAddGraph(compiler::Graph *graph) override;
84 
85     void FinishCompile() override;
86 
HasCompiledCode()87     bool HasCompiledCode() override
88     {
89         return compiled_;
90     }
91 
IsIrFailed()92     bool IsIrFailed() override
93     {
94         return irFailed_;
95     }
96 
97 private:
98     enum class AddGraphMode {
99         // Add graph to allow inlining only, the function created from this graph is discarded later
100         INLINE_FUNCTION,
101         // Add graph in a regular way, do not discard function created for it later
102         PRIMARY_FUNCTION,
103     };
104 
105     static std::vector<std::string> GetFeaturesForArch(Arch arch);
106 
107     bool RunArkPasses(compiler::Graph *graph);
108 
109     Expected<bool, std::string> AddGraphToModule(compiler::Graph *graph, WrappedModule &module,
110                                                  AddGraphMode addGraphMode);
111 
112     compiler::CompiledMethod AdaptCode(Method *method, Span<const uint8_t> machineCode);
113 
114     void PrepareAotGot(WrappedModule *wrappedModule);
115 
116     WrappedModule CreateModule(uint32_t moduleId);
117 
118     AotBuilderOffsets CollectAotBuilderOffsets(const std::unordered_set<std::shared_ptr<WrappedModule>> &modules);
119 
120     void DumpCodeInfo(compiler::CompiledMethod &method) const;
121 
122     void CompileModule(WrappedModule &module);
123 
124     ArkAotLinker::RoDataSections LinkModule(WrappedModule *wrappedModule, ArkAotLinker *linker,
125                                             AotBuilderOffsets *offsets);
126 
127     void AddInlineMethodByDepth(WrappedModule &module, compiler::Graph *caller,
128                                 compiler::RuntimeInterface::MethodPtr method, int32_t depth);
129 
130     void AddInlineFunctionsByDepth(WrappedModule &module, compiler::Graph *caller, int32_t depth);
131 
132     llvm::Expected<compiler::Graph *> CreateGraph(ArenaAllocator &allocator, ArenaAllocator &localAllocator,
133                                                   Method &method);
134 
135     void PreOpt2(compiler::Graph *graph);
136 
137 private:
138     llvm::ExitOnError exitOnErr_;
139 
140     ArenaVector<Method *> methods_;
141     compiler::LLVMAotBuilder *aotBuilder_;
142     std::string cmdline_;
143     std::string filename_;
144 
145     bool compiled_ {false};
146     bool irFailed_ {false};
147 
148     compiler::RuntimeInterface *runtime_;
149     std::unique_ptr<Spreader> spreader_;
150     std::atomic<uint32_t> compiledModules_ {0};
151     std::shared_ptr<WrappedModule> currentModule_;
152     llvm::sys::Mutex lock_ {};
153     std::unique_ptr<llvm::ThreadPool> threadPool_;
154 
155     int32_t semaphore_ {0};
156     std::condition_variable cv_;
157     std::mutex mutex_;
158 };
159 }  // namespace ark::llvmbackend
160 #endif  // LIBLLVMBACKEND_LLVM_AOT_COMPILER_H
161