| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| #ifndef KUDU_CODEGEN_FUNCTION_BUILDER_H |
| #define KUDU_CODEGEN_FUNCTION_BUILDER_H |
| |
| #include <memory> |
| #include <string> |
| #include <unordered_set> |
| #include <vector> |
| |
| #include <llvm/IR/IRBuilder.h> |
| |
| #include "kudu/gutil/macros.h" |
| #include "kudu/util/status.h" |
| |
| namespace llvm { |
| |
| class ExecutionEngine; |
| class Function; |
| class FunctionType; |
| class LLVMContext; |
| class Module; |
| class TargetMachine; |
| class Type; |
| class Value; |
| |
| } // namespace llvm |
| |
| namespace kudu { |
| namespace codegen { |
| |
| // A ModuleBuilder provides an interface to generate code for procedures |
| // given a CodeGenerator to refer to. Builder can be used to create multiple |
| // functions. It is intended to make building functions easier than using |
| // LLVM's IRBuilder<> directly. Finally, a builder also provides an interface |
| // to precompiled functions and makes sure that the bytecode is linked to |
| // the working module. |
| // |
| // This class is not thread-safe. It is intended to be used by a single |
| // thread to build a set of functions. |
| // |
| // This class is just a helper for other classes within the codegen |
| // directory. It is intended to be used within *.cc files, and not to be |
| // included in outward-facing classes so other directories do not have a |
| // dependency on LLVM (this class is necessary because the templated |
| // IRBuilder<> cannot be forward-declared since it has default arguments). |
| // This class, however, can easily be forward-declared. |
| class ModuleBuilder { |
| private: |
| typedef void* FunctionAddress; |
| |
| public: |
| // Provide alias so template arguments can be changed in one place |
| typedef llvm::IRBuilder<> LLVMBuilder; |
| |
| // Creates a builder with a fresh module and context. |
| ModuleBuilder(); |
| |
| // Deletes own module and context if they have not been compiled. |
| ~ModuleBuilder(); |
| |
| // Inits a new module with parsed precompiled IR from precompiled.cc. |
| // TODO: with multiple *.ll files, each file should be loaded on demand |
| Status Init(); |
| |
| // Create a new, empty function in the module with external linkage |
| llvm::Function* Create(llvm::FunctionType* fty, const std::string& name); |
| // Retrieve a precompiled type |
| llvm::Type* GetType(const std::string& name); |
| // Retrieve a precompiled function |
| llvm::Function* GetFunction(const std::string& name); |
| // Get the LLVM wrapper for a constant pointer value of type i8* |
| llvm::Value* GetPointerValue(void* ptr) const; |
| |
| LLVMBuilder* builder() { return &builder_; } |
| |
| // Once a function is complete, it may be offered to the module builder |
| // along with the location of the function pointer to be written to |
| // with the value of the JIT-compiled function pointer. Once the module |
| // builder's Compile() method is called, these value are filled. |
| // Requires that llvm::Function belong to this ModuleBuilder's module. |
| template<class FuncPtr> |
| void AddJITPromise(llvm::Function* llvm_f, FuncPtr* actual_f) { |
| // The below cast is technically yields undefined behavior for |
| // versions of the standard prior to C++0x. However, the llvm |
| // interface forces us to use object-pointer to function-pointer |
| // casting. |
| AddJITPromise(llvm_f, reinterpret_cast<FunctionAddress*>(actual_f)); |
| } |
| |
| // Compiles all promised functions. Builder may not be used after |
| // this method, only destructed. Upon success, releases ownership |
| // of the execution engine through the 'out' parameter. |
| // |
| // After this method has been called, the jit-compiled code may be |
| // called as long as 'out' remains alive. Once 'out' destructs, |
| // the code will be freed. |
| Status Compile(std::unique_ptr<llvm::ExecutionEngine>* out); |
| |
| // Retrieves the TargetMachine that the engine builder guessed was |
| // the native target. Requires compilation is complete. |
| // Pointer is valid while Compile()'s ExecutionEngine is. |
| llvm::TargetMachine* GetTargetMachine() const; |
| |
| private: |
| // The different states a ModuleBuilder can be in. |
| enum MBState { |
| kUninitialized, |
| kBuilding, |
| kCompiled |
| }; |
| // Basic POD which associates an llvm::Function to the location where its |
| // function pointer should be written to after compilation. |
| struct JITFuture { |
| llvm::Function* llvm_f_; |
| FunctionAddress* actual_f_; |
| }; |
| |
| void AddJITPromise(llvm::Function* llvm_f, FunctionAddress* actual_f); |
| |
| // Returns the function names for the functions stored in the JITFutures. |
| std::unordered_set<std::string> GetFunctionNames() const; |
| |
| MBState state_; |
| std::vector<JITFuture> futures_; |
| std::unique_ptr<llvm::LLVMContext> context_; |
| std::unique_ptr<llvm::Module> module_; |
| LLVMBuilder builder_; |
| llvm::TargetMachine* target_; // not owned |
| |
| DISALLOW_COPY_AND_ASSIGN(ModuleBuilder); |
| }; |
| |
| } // namespace codegen |
| } // namespace kudu |
| |
| #endif |