Builtin.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include "Builtin.h"
  2. #include "Scope.h"
  3. #include "Type.h"
  4. #include "Context.h"
  5. #ifdef DEBUGGING
  6. #include <llvm/Support/raw_os_ostream.h>
  7. #endif
  8. using namespace qlow;
  9. sem::NativeScope qlow::sem::generateNativeScope(Context& context)
  10. {
  11. using sem::Class;
  12. using sem::NativeScope;
  13. NativeScope scope{ context };
  14. std::map<std::string, Type::Native> natives = {
  15. { "Void", Type::Native::VOID },
  16. { "Boolean", Type::Native::BOOLEAN },
  17. { "Integer", Type::Native::INTEGER },
  18. };
  19. for (auto [name, type] : natives) {
  20. TypeId id = context.createNativeType(name, type);
  21. scope.addNativeType(name, type, id);
  22. }
  23. /*std::map<std::string, NativeType::Type> natives = {
  24. { "Boolean", NativeType::BOOLEAN },
  25. { "Char", NativeType::CHAR },
  26. { "String", NativeType::STRING },
  27. { "Float32", NativeType::FLOAT32 },
  28. { "Float64", NativeType::FLOAT64 },
  29. };
  30. std::map<std::string, NativeType::Type> integers = {
  31. { "Integer", NativeType::INTEGER },
  32. { "Int8", NativeType::INT8 },
  33. { "Int16", NativeType::INT16 },
  34. { "Int32", NativeType::INT32 },
  35. { "Int64", NativeType::INT64 },
  36. { "Int128", NativeType::INT128 },
  37. { "UInt8", NativeType::UINT8 },
  38. { "UInt16", NativeType::UINT16 },
  39. { "UInt32", NativeType::UINT32 },
  40. { "UInt64", NativeType::UINT64 },
  41. { "UInt128", NativeType::UINT128 },
  42. };
  43. for (auto [name, type] : natives) {
  44. scope.types.insert({ name, std::make_unique
  45. <std::shared_ptr<NativeType>>(std::make_shared<NativeType>(type)) });
  46. }
  47. for (auto [name, type] : integers) {
  48. auto native = std::make_shared<NativeType>(type);
  49. native->nativeMethods.insert(
  50. { "+",
  51. std::make_unique<BinaryNativeMethod>(native, native,
  52. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  53. return builder.CreateAdd(a, b);
  54. })
  55. }
  56. );
  57. native->nativeMethods.insert(
  58. { "-",
  59. std::make_unique<BinaryNativeMethod>(native, native,
  60. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  61. return builder.CreateSub(a, b);
  62. })
  63. }
  64. );
  65. native->nativeMethods.insert(
  66. { "*",
  67. std::make_unique<BinaryNativeMethod>(native, native,
  68. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  69. return builder.CreateMul(a, b);
  70. })
  71. }
  72. );
  73. if (name[0] == 'U') {
  74. native->nativeMethods.insert(
  75. { "/",
  76. std::make_unique<BinaryNativeMethod>(native, native,
  77. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  78. return builder.CreateUDiv(a, b);
  79. })
  80. }
  81. );
  82. }
  83. else {
  84. native->nativeMethods.insert(
  85. { "/",
  86. std::make_unique<BinaryNativeMethod>(native, native,
  87. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  88. return builder.CreateSDiv(a, b);
  89. })
  90. }
  91. );
  92. }
  93. native->nativeMethods.insert(
  94. { "==",
  95. std::make_unique<BinaryNativeMethod>(std::make_shared<NativeType>(NativeType::BOOLEAN), native,
  96. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  97. return builder.CreateICmpEQ(a, b);
  98. })
  99. }
  100. );
  101. native->nativeMethods.insert(
  102. { "!=",
  103. std::make_unique<BinaryNativeMethod>(std::make_shared<NativeType>(NativeType::BOOLEAN), native,
  104. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  105. return builder.CreateICmpNE(a, b);
  106. })
  107. }
  108. );
  109. scope.types.insert({ name, std::make_unique
  110. <std::shared_ptr<NativeType>>(std::move(native)) });
  111. }*/
  112. return scope;
  113. }
  114. void qlow::sem::fillNativeScope(NativeScope& scope)
  115. {
  116. Context& context = scope.getContext();
  117. TypeId integer = context.getNativeTypeId(Type::Native::INTEGER);
  118. context.getType(integer).setTypeScope(
  119. std::make_unique<NativeTypeScope>(generateNativeTypeScope(context, Type::Native::INTEGER))
  120. );
  121. }
  122. sem::NativeTypeScope qlow::sem::generateNativeTypeScope(Context& context, Type::Native native)
  123. {
  124. NativeTypeScope scope{ context, context.getNativeTypeId(native) };
  125. scope.nativeMethods.insert(
  126. { "+",
  127. std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
  128. context.getNativeTypeId(Type::Native::INTEGER),
  129. context.getNativeTypeId(native),
  130. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  131. return builder.CreateAdd(a, b);
  132. }
  133. )
  134. }
  135. );
  136. scope.nativeMethods.insert(
  137. { "-",
  138. std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
  139. context.getNativeTypeId(Type::Native::INTEGER),
  140. context.getNativeTypeId(native),
  141. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  142. return builder.CreateSub(a, b);
  143. }
  144. )
  145. }
  146. );
  147. scope.nativeMethods.insert(
  148. { "*",
  149. std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
  150. context.getNativeTypeId(Type::Native::INTEGER),
  151. context.getNativeTypeId(native),
  152. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  153. return builder.CreateMul(a, b);
  154. }
  155. )
  156. }
  157. );
  158. scope.nativeMethods.insert(
  159. { "/",
  160. std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
  161. context.getNativeTypeId(Type::Native::INTEGER),
  162. context.getNativeTypeId(native),
  163. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  164. return builder.CreateSDiv(a, b);
  165. }
  166. )
  167. }
  168. );
  169. scope.nativeMethods.insert(
  170. { "==",
  171. std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
  172. context.getNativeTypeId(Type::Native::BOOLEAN),
  173. context.getNativeTypeId(native),
  174. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  175. return builder.CreateICmpEQ(a, b);
  176. }
  177. )
  178. }
  179. );
  180. scope.nativeMethods.insert(
  181. { "!=",
  182. std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
  183. context.getNativeTypeId(Type::Native::BOOLEAN),
  184. context.getNativeTypeId(native),
  185. [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
  186. return builder.CreateICmpNE(a, b);
  187. }
  188. )
  189. }
  190. );
  191. return scope;
  192. }
  193. llvm::Value* qlow::sem::UnaryNativeMethod::generateCode(llvm::IRBuilder<>& builder,
  194. std::vector<llvm::Value*> arguments)
  195. {
  196. if (arguments.size() != 1)
  197. throw "invalid unary operation";
  198. return generator(builder, arguments[0]);
  199. }
  200. llvm::Value* qlow::sem::BinaryNativeMethod::generateCode(llvm::IRBuilder<>& builder,
  201. std::vector<llvm::Value*> arguments)
  202. {
  203. if (arguments.size() != 2)
  204. throw "invalid binary operation";
  205. #ifdef DEBUGGING
  206. Printer& p = Printer::getInstance();
  207. llvm::raw_os_ostream pp(p);
  208. p << "creating native binop with llvm-types ";
  209. arguments[0]->getType()->print(pp); pp.flush();
  210. p << ", ";
  211. arguments[1]->getType()->print(pp); pp.flush();
  212. p << std::endl;
  213. #endif
  214. return generator(builder, arguments[0], arguments[1]);
  215. }