FunctionBuilder.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #pragma once
  2. #include "llvm/IR/Module.h"
  3. #include <string>
  4. #include <vector>
  5. //==============================================================================
  6. // Simplifies the creation of functions.
  7. //
  8. // To create a function 'void foo( userType, i32, float* )' use the following
  9. // code:
  10. // FunctionBuilder(module, "foo").voidTy().type(userType).i32().floatPtr().build()
  11. //
  12. // The first type specified is the return type.
  13. class FunctionBuilder
  14. {
  15. public:
  16. FunctionBuilder(llvm::Module* mod, const std::string& name)
  17. : m_context(mod->getContext())
  18. , m_module(mod)
  19. , m_name(name)
  20. {}
  21. FunctionBuilder& voidTy()
  22. {
  23. m_argNames.push_back("");
  24. m_types.push_back(llvm::Type::getVoidTy(m_context));
  25. return *this;
  26. }
  27. FunctionBuilder& floatTy(const std::string& argName = "")
  28. {
  29. m_argNames.push_back(argName);
  30. m_types.push_back(llvm::Type::getFloatTy(m_context));
  31. return *this;
  32. }
  33. FunctionBuilder& floatPtr(const std::string& argName = "")
  34. {
  35. m_argNames.push_back(argName);
  36. m_types.push_back(llvm::Type::getFloatPtrTy(m_context));
  37. return *this;
  38. }
  39. FunctionBuilder& doubleTy(const std::string& argName = "")
  40. {
  41. m_argNames.push_back(argName);
  42. m_types.push_back(llvm::Type::getDoubleTy(m_context));
  43. return *this;
  44. }
  45. FunctionBuilder& doublePtr(const std::string& argName = "")
  46. {
  47. m_argNames.push_back(argName);
  48. m_types.push_back(llvm::Type::getDoublePtrTy(m_context));
  49. return *this;
  50. }
  51. FunctionBuilder& i32(const std::string& argName = "")
  52. {
  53. m_argNames.push_back(argName);
  54. m_types.push_back(llvm::Type::getInt32Ty(m_context));
  55. return *this;
  56. }
  57. FunctionBuilder& i32Ptr(const std::string& argName = "")
  58. {
  59. m_argNames.push_back(argName);
  60. m_types.push_back(llvm::Type::getInt32PtrTy(m_context));
  61. return *this;
  62. }
  63. FunctionBuilder& i16(const std::string& argName = "")
  64. {
  65. m_argNames.push_back(argName);
  66. m_types.push_back(llvm::Type::getInt16Ty(m_context));
  67. return *this;
  68. }
  69. FunctionBuilder& i16Ptr(const std::string& argName = "")
  70. {
  71. m_argNames.push_back(argName);
  72. m_types.push_back(llvm::Type::getInt16PtrTy(m_context));
  73. return *this;
  74. }
  75. FunctionBuilder& i8(const std::string& argName = "")
  76. {
  77. m_argNames.push_back(argName);
  78. m_types.push_back(llvm::Type::getInt8Ty(m_context));
  79. return *this;
  80. }
  81. FunctionBuilder& i8Ptr(const std::string& argName = "")
  82. {
  83. m_argNames.push_back(argName);
  84. m_types.push_back(llvm::Type::getInt8PtrTy(m_context));
  85. return *this;
  86. }
  87. FunctionBuilder& i1(const std::string& argName = "")
  88. {
  89. m_argNames.push_back(argName);
  90. m_types.push_back(llvm::Type::getInt1Ty(m_context));
  91. return *this;
  92. }
  93. FunctionBuilder& i1Ptr(const std::string& argName = "")
  94. {
  95. m_argNames.push_back(argName);
  96. m_types.push_back(llvm::Type::getInt1PtrTy(m_context));
  97. return *this;
  98. }
  99. FunctionBuilder& type(llvm::Type* ty, const std::string& argName = "")
  100. {
  101. m_argNames.push_back(argName);
  102. m_types.push_back(ty);
  103. return *this;
  104. }
  105. FunctionBuilder& types(const std::vector<llvm::Type*>& ty, const std::vector<std::string>& argNames)
  106. {
  107. if (argNames.empty())
  108. for (size_t i = 0; i < ty.size(); ++i)
  109. m_argNames.push_back("");
  110. m_types.insert(m_types.end(), ty.begin(), ty.end());
  111. return *this;
  112. }
  113. llvm::Function* build()
  114. {
  115. using namespace llvm;
  116. Type* retTy = m_types[0];
  117. AttributeSet attributes;
  118. Type** argsBegin = (&m_types[0]) + 1;
  119. Type** argsEnd = argsBegin + m_types.size() - 1;
  120. Constant* funcC =
  121. m_module->getOrInsertFunction(m_name, FunctionType::get(retTy, ArrayRef<Type*>(argsBegin, argsEnd), false), attributes);
  122. Function* func = cast<Function>(funcC);
  123. std::string* argNamePtr = m_argNames.data() + 1;
  124. for (auto& arg : func->args())
  125. arg.setName(*argNamePtr++);
  126. return func;
  127. }
  128. private:
  129. llvm::LLVMContext& m_context;
  130. llvm::Module* m_module = nullptr;
  131. std::string m_name;
  132. std::vector<std::string> m_argNames;
  133. std::vector<llvm::Type*> m_types;
  134. // forbidden
  135. FunctionBuilder();
  136. FunctionBuilder(const FunctionBuilder&);
  137. };