A Hugo incarnation of the blog.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

llvm_context.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #include "llvm_context.hpp"
  2. #include <llvm/IR/DerivedTypes.h>
  3. using namespace llvm;
  4. void llvm_context::create_types() {
  5. stack_type = StructType::create(ctx, "stack");
  6. gmachine_type = StructType::create(ctx, "gmachine");
  7. stack_ptr_type = PointerType::getUnqual(stack_type);
  8. gmachine_ptr_type = PointerType::getUnqual(gmachine_type);
  9. tag_type = IntegerType::getInt8Ty(ctx);
  10. struct_types["node_base"] = StructType::create(ctx, "node_base");
  11. struct_types["node_app"] = StructType::create(ctx, "node_app");
  12. struct_types["node_num"] = StructType::create(ctx, "node_num");
  13. struct_types["node_global"] = StructType::create(ctx, "node_global");
  14. struct_types["node_ind"] = StructType::create(ctx, "node_ind");
  15. struct_types["node_data"] = StructType::create(ctx, "node_data");
  16. node_ptr_type = PointerType::getUnqual(struct_types.at("node_base"));
  17. function_type = FunctionType::get(Type::getVoidTy(ctx), { gmachine_ptr_type }, false);
  18. gmachine_type->setBody(
  19. stack_ptr_type,
  20. node_ptr_type,
  21. IntegerType::getInt64Ty(ctx),
  22. IntegerType::getInt64Ty(ctx)
  23. );
  24. struct_types.at("node_base")->setBody(
  25. IntegerType::getInt32Ty(ctx),
  26. IntegerType::getInt8Ty(ctx),
  27. node_ptr_type
  28. );
  29. struct_types.at("node_app")->setBody(
  30. struct_types.at("node_base"),
  31. node_ptr_type,
  32. node_ptr_type
  33. );
  34. struct_types.at("node_num")->setBody(
  35. struct_types.at("node_base"),
  36. IntegerType::getInt32Ty(ctx)
  37. );
  38. struct_types.at("node_global")->setBody(
  39. struct_types.at("node_base"),
  40. FunctionType::get(Type::getVoidTy(ctx), { stack_ptr_type }, false)
  41. );
  42. struct_types.at("node_ind")->setBody(
  43. struct_types.at("node_base"),
  44. node_ptr_type
  45. );
  46. struct_types.at("node_data")->setBody(
  47. struct_types.at("node_base"),
  48. IntegerType::getInt8Ty(ctx),
  49. PointerType::getUnqual(node_ptr_type)
  50. );
  51. }
  52. void llvm_context::create_functions() {
  53. auto void_type = Type::getVoidTy(ctx);
  54. auto sizet_type = IntegerType::get(ctx, sizeof(size_t) * 8);
  55. functions["stack_init"] = Function::Create(
  56. FunctionType::get(void_type, { stack_ptr_type }, false),
  57. Function::LinkageTypes::ExternalLinkage,
  58. "stack_init",
  59. &module
  60. );
  61. functions["stack_free"] = Function::Create(
  62. FunctionType::get(void_type, { stack_ptr_type }, false),
  63. Function::LinkageTypes::ExternalLinkage,
  64. "stack_free",
  65. &module
  66. );
  67. functions["stack_push"] = Function::Create(
  68. FunctionType::get(void_type, { stack_ptr_type, node_ptr_type }, false),
  69. Function::LinkageTypes::ExternalLinkage,
  70. "stack_push",
  71. &module
  72. );
  73. functions["stack_pop"] = Function::Create(
  74. FunctionType::get(node_ptr_type, { stack_ptr_type }, false),
  75. Function::LinkageTypes::ExternalLinkage,
  76. "stack_pop",
  77. &module
  78. );
  79. functions["stack_peek"] = Function::Create(
  80. FunctionType::get(node_ptr_type, { stack_ptr_type, sizet_type }, false),
  81. Function::LinkageTypes::ExternalLinkage,
  82. "stack_peek",
  83. &module
  84. );
  85. functions["stack_popn"] = Function::Create(
  86. FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false),
  87. Function::LinkageTypes::ExternalLinkage,
  88. "stack_popn",
  89. &module
  90. );
  91. functions["gmachine_slide"] = Function::Create(
  92. FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false),
  93. Function::LinkageTypes::ExternalLinkage,
  94. "gmachine_slide",
  95. &module
  96. );
  97. functions["gmachine_update"] = Function::Create(
  98. FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false),
  99. Function::LinkageTypes::ExternalLinkage,
  100. "gmachine_update",
  101. &module
  102. );
  103. functions["gmachine_alloc"] = Function::Create(
  104. FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false),
  105. Function::LinkageTypes::ExternalLinkage,
  106. "gmachine_alloc",
  107. &module
  108. );
  109. functions["gmachine_pack"] = Function::Create(
  110. FunctionType::get(void_type, { gmachine_ptr_type, sizet_type, tag_type }, false),
  111. Function::LinkageTypes::ExternalLinkage,
  112. "gmachine_pack",
  113. &module
  114. );
  115. functions["gmachine_split"] = Function::Create(
  116. FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false),
  117. Function::LinkageTypes::ExternalLinkage,
  118. "gmachine_split",
  119. &module
  120. );
  121. functions["gmachine_track"] = Function::Create(
  122. FunctionType::get(node_ptr_type, { gmachine_ptr_type, node_ptr_type }, false),
  123. Function::LinkageTypes::ExternalLinkage,
  124. "gmachine_track",
  125. &module
  126. );
  127. auto int32_type = IntegerType::getInt32Ty(ctx);
  128. functions["alloc_app"] = Function::Create(
  129. FunctionType::get(node_ptr_type, { node_ptr_type, node_ptr_type }, false),
  130. Function::LinkageTypes::ExternalLinkage,
  131. "alloc_app",
  132. &module
  133. );
  134. functions["alloc_num"] = Function::Create(
  135. FunctionType::get(node_ptr_type, { int32_type }, false),
  136. Function::LinkageTypes::ExternalLinkage,
  137. "alloc_num",
  138. &module
  139. );
  140. functions["alloc_global"] = Function::Create(
  141. FunctionType::get(node_ptr_type, { function_type, int32_type }, false),
  142. Function::LinkageTypes::ExternalLinkage,
  143. "alloc_global",
  144. &module
  145. );
  146. functions["alloc_ind"] = Function::Create(
  147. FunctionType::get(node_ptr_type, { node_ptr_type }, false),
  148. Function::LinkageTypes::ExternalLinkage,
  149. "alloc_ind",
  150. &module
  151. );
  152. functions["unwind"] = Function::Create(
  153. FunctionType::get(void_type, { gmachine_ptr_type }, false),
  154. Function::LinkageTypes::ExternalLinkage,
  155. "unwind",
  156. &module
  157. );
  158. }
  159. IRBuilder<>& llvm_context::get_builder() {
  160. return builder;
  161. }
  162. Module& llvm_context::get_module() {
  163. return module;
  164. }
  165. BasicBlock* llvm_context::create_basic_block(const std::string& name, llvm::Function* f) {
  166. return BasicBlock::Create(ctx, name, f);
  167. }
  168. ConstantInt* llvm_context::create_i8(int8_t i) {
  169. return ConstantInt::get(ctx, APInt(8, i));
  170. }
  171. ConstantInt* llvm_context::create_i32(int32_t i) {
  172. return ConstantInt::get(ctx, APInt(32, i));
  173. }
  174. ConstantInt* llvm_context::create_size(size_t i) {
  175. return ConstantInt::get(ctx, APInt(sizeof(size_t) * 8, i));
  176. }
  177. Value* llvm_context::create_pop(Function* f) {
  178. auto pop_f = functions.at("stack_pop");
  179. return builder.CreateCall(pop_f, { unwrap_gmachine_stack_ptr(f->arg_begin()) });
  180. }
  181. Value* llvm_context::create_peek(Function* f, Value* off) {
  182. auto peek_f = functions.at("stack_peek");
  183. return builder.CreateCall(peek_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off });
  184. }
  185. void llvm_context::create_push(Function* f, Value* v) {
  186. auto push_f = functions.at("stack_push");
  187. builder.CreateCall(push_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), v });
  188. }
  189. void llvm_context::create_popn(Function* f, Value* off) {
  190. auto popn_f = functions.at("stack_popn");
  191. builder.CreateCall(popn_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off });
  192. }
  193. void llvm_context::create_update(Function* f, Value* off) {
  194. auto update_f = functions.at("gmachine_update");
  195. builder.CreateCall(update_f, { f->arg_begin(), off });
  196. }
  197. void llvm_context::create_pack(Function* f, Value* c, Value* t) {
  198. auto pack_f = functions.at("gmachine_pack");
  199. builder.CreateCall(pack_f, { f->arg_begin(), c, t });
  200. }
  201. void llvm_context::create_split(Function* f, Value* c) {
  202. auto split_f = functions.at("gmachine_split");
  203. builder.CreateCall(split_f, { f->arg_begin(), c });
  204. }
  205. void llvm_context::create_slide(Function* f, Value* off) {
  206. auto slide_f = functions.at("gmachine_slide");
  207. builder.CreateCall(slide_f, { f->arg_begin(), off });
  208. }
  209. void llvm_context::create_alloc(Function* f, Value* n) {
  210. auto alloc_f = functions.at("gmachine_alloc");
  211. builder.CreateCall(alloc_f, { f->arg_begin(), n });
  212. }
  213. Value* llvm_context::create_track(Function* f, Value* v) {
  214. auto track_f = functions.at("gmachine_track");
  215. return builder.CreateCall(track_f, { f->arg_begin(), v });
  216. }
  217. void llvm_context::create_unwind(Function* f) {
  218. auto unwind_f = functions.at("unwind");
  219. builder.CreateCall(unwind_f, { f->args().begin() });
  220. }
  221. Value* llvm_context::unwrap_gmachine_stack_ptr(Value* g) {
  222. auto offset_0 = create_i32(0);
  223. return builder.CreateGEP(g, { offset_0, offset_0 });
  224. }
  225. Value* llvm_context::unwrap_num(Value* v) {
  226. auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num"));
  227. auto cast = builder.CreatePointerCast(v, num_ptr_type);
  228. auto offset_0 = create_i32(0);
  229. auto offset_1 = create_i32(1);
  230. auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 });
  231. return builder.CreateLoad(int_ptr);
  232. }
  233. Value* llvm_context::create_num(Function* f, Value* v) {
  234. auto alloc_num_f = functions.at("alloc_num");
  235. auto alloc_num_call = builder.CreateCall(alloc_num_f, { v });
  236. return create_track(f, alloc_num_call);
  237. }
  238. Value* llvm_context::unwrap_data_tag(Value* v) {
  239. auto data_ptr_type = PointerType::getUnqual(struct_types.at("node_data"));
  240. auto cast = builder.CreatePointerCast(v, data_ptr_type);
  241. auto offset_0 = create_i32(0);
  242. auto offset_1 = create_i32(1);
  243. auto tag_ptr = builder.CreateGEP(cast, { offset_0, offset_1 });
  244. return builder.CreateLoad(tag_ptr);
  245. }
  246. Value* llvm_context::create_global(Function* f, Value* gf, Value* a) {
  247. auto alloc_global_f = functions.at("alloc_global");
  248. auto alloc_global_call = builder.CreateCall(alloc_global_f, { gf, a });
  249. return create_track(f, alloc_global_call);
  250. }
  251. Value* llvm_context::create_app(Function* f, Value* l, Value* r) {
  252. auto alloc_app_f = functions.at("alloc_app");
  253. auto alloc_app_call = builder.CreateCall(alloc_app_f, { l, r });
  254. return create_track(f, alloc_app_call);
  255. }
  256. llvm::Function* llvm_context::create_custom_function(const std::string& name, int32_t arity) {
  257. auto void_type = llvm::Type::getVoidTy(ctx);
  258. auto new_function = llvm::Function::Create(
  259. function_type,
  260. llvm::Function::LinkageTypes::ExternalLinkage,
  261. "f_" + name,
  262. &module
  263. );
  264. auto start_block = llvm::BasicBlock::Create(ctx, "entry", new_function);
  265. auto new_custom_f = custom_function_ptr(new custom_function());
  266. new_custom_f->arity = arity;
  267. new_custom_f->function = new_function;
  268. custom_functions["f_" + name] = std::move(new_custom_f);
  269. return new_function;
  270. }
  271. llvm_context::custom_function& llvm_context::get_custom_function(const std::string& name) {
  272. return *custom_functions.at("f_" + name);
  273. }