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