123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- #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&);
- };
|