| #pragma once |
| |
| #include "llvm/IR/Module.h" |
| |
| #include <string> |
| #include <vector> |
| |
| //============================================================================== |
| // Simplifies the creation of functions. |
| // |
| // To create a function 'void foo( userType, i32, float* )' use the following |
| // code: |
| // FunctionBuilder(module, "foo").voidTy().type(userType).i32().floatPtr().build() |
| // |
| // The first type specified is the return type. |
| class FunctionBuilder |
| { |
| public: |
| FunctionBuilder(llvm::Module* mod, const std::string& name) |
| : m_context(mod->getContext()) |
| , m_module(mod) |
| , m_name(name) |
| {} |
| |
| FunctionBuilder& voidTy() |
| { |
| m_argNames.push_back(""); |
| m_types.push_back(llvm::Type::getVoidTy(m_context)); |
| return *this; |
| } |
| FunctionBuilder& floatTy(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getFloatTy(m_context)); |
| return *this; |
| } |
| FunctionBuilder& floatPtr(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getFloatPtrTy(m_context)); |
| return *this; |
| } |
| FunctionBuilder& doubleTy(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getDoubleTy(m_context)); |
| return *this; |
| } |
| FunctionBuilder& doublePtr(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getDoublePtrTy(m_context)); |
| return *this; |
| } |
| FunctionBuilder& i32(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getInt32Ty(m_context)); |
| return *this; |
| } |
| FunctionBuilder& i32Ptr(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getInt32PtrTy(m_context)); |
| return *this; |
| } |
| FunctionBuilder& i16(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getInt16Ty(m_context)); |
| return *this; |
| } |
| FunctionBuilder& i16Ptr(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getInt16PtrTy(m_context)); |
| return *this; |
| } |
| FunctionBuilder& i8(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getInt8Ty(m_context)); |
| return *this; |
| } |
| FunctionBuilder& i8Ptr(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getInt8PtrTy(m_context)); |
| return *this; |
| } |
| FunctionBuilder& i1(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getInt1Ty(m_context)); |
| return *this; |
| } |
| FunctionBuilder& i1Ptr(const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(llvm::Type::getInt1PtrTy(m_context)); |
| return *this; |
| } |
| |
| FunctionBuilder& type(llvm::Type* ty, const std::string& argName = "") |
| { |
| m_argNames.push_back(argName); |
| m_types.push_back(ty); |
| return *this; |
| } |
| FunctionBuilder& types(const std::vector<llvm::Type*>& ty, const std::vector<std::string>& argNames) |
| { |
| if (argNames.empty()) |
| for (size_t i = 0; i < ty.size(); ++i) |
| m_argNames.push_back(""); |
| m_types.insert(m_types.end(), ty.begin(), ty.end()); |
| return *this; |
| } |
| |
| llvm::Function* build() |
| { |
| using namespace llvm; |
| |
| Type* retTy = m_types[0]; |
| AttributeSet attributes; |
| Type** argsBegin = (&m_types[0]) + 1; |
| Type** argsEnd = argsBegin + m_types.size() - 1; |
| Constant* funcC = |
| m_module->getOrInsertFunction(m_name, FunctionType::get(retTy, ArrayRef<Type*>(argsBegin, argsEnd), false), attributes); |
| Function* func = cast<Function>(funcC); |
| |
| std::string* argNamePtr = m_argNames.data() + 1; |
| for (auto& arg : func->args()) |
| arg.setName(*argNamePtr++); |
| |
| return func; |
| } |
| |
| private: |
| llvm::LLVMContext& m_context; |
| llvm::Module* m_module = nullptr; |
| std::string m_name; |
| std::vector<std::string> m_argNames; |
| std::vector<llvm::Type*> m_types; |
| |
| // forbidden |
| FunctionBuilder(); |
| FunctionBuilder(const FunctionBuilder&); |
| }; |