Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

259 righe
8.5 KiB

  1. #include "molasses/parser_primitives.h"
  2. #include "molasses/generator_primitives.h"
  3. namespace molasses {
  4. parser_context register_integers(parser_context ctx)
  5. requires (architecture == architecture_t::x86_64_linux) {
  6. ctx.types.push_back(std::make_shared<primitive_type>("i8", 1));
  7. ctx.types.push_back(std::make_shared<primitive_type>("i16", 2));
  8. ctx.types.push_back(std::make_shared<primitive_type>("i32", 4));
  9. ctx.types.push_back(std::make_shared<primitive_type>("i64", 8));
  10. ctx.types.push_back(std::make_shared<primitive_type>("u8", 1));
  11. ctx.types.push_back(std::make_shared<primitive_type>("u16", 2));
  12. ctx.types.push_back(std::make_shared<primitive_type>("u32", 4));
  13. ctx.types.push_back(std::make_shared<primitive_type>("u64", 8));
  14. return ctx;
  15. }
  16. parser_context register_i32_operations(parser_context ctx)
  17. requires (architecture == architecture_t::x86_64_linux) {
  18. ctx.operations.emplace_back(
  19. std::make_shared<molasses::primitive_operation>(
  20. std::string{"+"},
  21. std::vector<std::string>({"i32", "i32"}),
  22. std::vector<std::string>({"i32"}),
  23. std::vector<std::string>({
  24. " popq %rax\n",
  25. " popq %rbx\n",
  26. " addl %ebx, %eax\n",
  27. " andl $0xFFFFFFFF, %eax\n",
  28. " pushq %rax\n"
  29. })
  30. )
  31. );
  32. ctx.operations.emplace_back(
  33. std::make_shared<molasses::primitive_operation>(
  34. std::string{"*"},
  35. std::vector<std::string>({"i32", "i32"}),
  36. std::vector<std::string>({"i32"}),
  37. std::vector<std::string>({
  38. " popq %rax\n",
  39. " popq %rbx\n",
  40. " imull %ebx, %eax\n",
  41. " andl $0xFFFFFFFF, %eax\n",
  42. " pushq %rax\n"
  43. })
  44. )
  45. );
  46. ctx.operations.emplace_back(
  47. std::make_shared<molasses::primitive_operation>(
  48. std::string{"-"},
  49. std::vector<std::string>({"i32", "i32"}),
  50. std::vector<std::string>({"i32"}),
  51. std::vector<std::string>({
  52. " popq %rax\n",
  53. " popq %rbx\n",
  54. " subl %ebx, %eax\n",
  55. " andl $0xFFFFFFFF, %eax\n",
  56. " pushq %rax\n"
  57. })
  58. )
  59. );
  60. ctx.operations.emplace_back(
  61. std::make_shared<molasses::primitive_operation>(
  62. std::string{"i32-to-i64"},
  63. std::vector<std::string>({"i32"}),
  64. std::vector<std::string>({"i64"}),
  65. std::vector<std::string>({
  66. " popq %rax\n",
  67. " movslq %eax, %rax\n",
  68. " pushq %rax\n"
  69. })
  70. )
  71. );
  72. ctx.operations.emplace_back(
  73. std::make_shared<molasses::primitive_operation>(
  74. std::string{"drop_i64"},
  75. std::vector<std::string>({"i64"}),
  76. std::vector<std::string>({}),
  77. std::vector<std::string>({
  78. " popq %rax\n"
  79. })
  80. )
  81. );
  82. ctx.operations.emplace_back(
  83. std::make_shared<molasses::primitive_operation>(
  84. std::string{"syscall1"},
  85. std::vector<std::string>({"i64", "i64"}),
  86. std::vector<std::string>({"i64"}),
  87. std::vector<std::string>({
  88. " popq %rax\n",
  89. " popq %rdi\n",
  90. " syscall\n",
  91. " pushq %rax\n"
  92. })
  93. )
  94. );
  95. ctx.operations.emplace_back(
  96. std::make_shared<molasses::primitive_operation>(
  97. std::string{"syscall2"},
  98. std::vector<std::string>({"i64", "i64", "i64"}),
  99. std::vector<std::string>({"i64"}),
  100. std::vector<std::string>({
  101. " popq %rax\n",
  102. " popq %rdi\n",
  103. " popq %rsi\n",
  104. " syscall\n",
  105. " pushq %rax\n"
  106. })
  107. )
  108. );
  109. ctx.operations.emplace_back(
  110. std::make_shared<molasses::primitive_operation>(
  111. std::string{"syscall3"},
  112. std::vector<std::string>({"i64", "i64", "i64", "i64"}),
  113. std::vector<std::string>({"i64"}),
  114. std::vector<std::string>({
  115. " popq %rax\n",
  116. " popq %rdi\n",
  117. " popq %rsi\n",
  118. " popq %rdx\n",
  119. " syscall\n",
  120. " pushq %rax\n"
  121. })
  122. )
  123. );
  124. ctx.operations.emplace_back(
  125. std::make_shared<molasses::primitive_operation>(
  126. std::string{"syscall4"},
  127. std::vector<std::string>({"i64", "i64", "i64", "i64", "i64"}),
  128. std::vector<std::string>({"i64"}),
  129. std::vector<std::string>({
  130. " popq %rax\n",
  131. " popq %rdi\n",
  132. " popq %rsi\n",
  133. " popq %rdx\n",
  134. " popq %r10\n",
  135. " syscall\n",
  136. " pushq %rax\n"
  137. })
  138. )
  139. );
  140. ctx.operations.emplace_back(
  141. std::make_shared<molasses::primitive_operation>(
  142. std::string{"syscall5"},
  143. std::vector<std::string>({"i64", "i64", "i64", "i64", "i64", "i64"}),
  144. std::vector<std::string>({"i64"}),
  145. std::vector<std::string>({
  146. " popq %rax\n",
  147. " popq %rdi\n",
  148. " popq %rsi\n",
  149. " popq %rdx\n",
  150. " popq %r10\n",
  151. " popq %r8\n",
  152. " syscall\n",
  153. " pushq %rax\n"
  154. })
  155. )
  156. );
  157. ctx.operations.emplace_back(
  158. std::make_shared<molasses::primitive_operation>(
  159. std::string{"syscall6"},
  160. std::vector<std::string>({"i64", "i64", "i64", "i64", "i64", "i64", "i64"}),
  161. std::vector<std::string>({"i64"}),
  162. std::vector<std::string>({
  163. " popq %rax\n",
  164. " popq %rdi\n",
  165. " popq %rsi\n",
  166. " popq %rdx\n",
  167. " popq %r10\n",
  168. " popq %r8\n",
  169. " popq %r9\n",
  170. " syscall\n",
  171. " pushq %rax\n"
  172. })
  173. )
  174. );
  175. return ctx;
  176. }
  177. std::vector<std::string> generate_call(const std::string& target)
  178. requires (architecture == architecture_t::x86_64_linux) {
  179. return {
  180. " call "+target+"\n",
  181. };
  182. }
  183. std::vector<std::string> generate_push_int32(int32_t target)
  184. requires (architecture == architecture_t::x86_64_linux) {
  185. return {
  186. " pushq $" +std::to_string(target)+ "\n"
  187. };
  188. }
  189. std::vector<std::string> generate_label(const std::string& target)
  190. requires (architecture == architecture_t::x86_64_linux) {
  191. return {
  192. target+":\n"
  193. };
  194. }
  195. std::vector<std::string> generate_return()
  196. requires (architecture == architecture_t::x86_64_linux) {
  197. return {
  198. " // Return to caller\n",
  199. " addq $-8, %r10\n",
  200. " pushq (%r10)\n",
  201. " retq\n"
  202. };
  203. }
  204. std::vector<std::string> generate_enter()
  205. requires (architecture == architecture_t::x86_64_linux) {
  206. return {
  207. " // Prepare the function stack\n",
  208. " popq (%r10)\n"
  209. " addq $8, %r10\n",
  210. };
  211. }
  212. std::vector<std::string> initialize_stack()
  213. requires (architecture == architecture_t::x86_64_linux) {
  214. std::vector<std::string> operations = {
  215. "code:\n",
  216. " .skip 1000000\n",
  217. ".text\n",
  218. " .globl _start\n",
  219. "initialize_callstack:\n",
  220. " movq $9, %rax\n",
  221. " movq $0, %rdi\n",
  222. " movq $8192, %rsi\n",
  223. " movq $3, %rdx\n",
  224. " movq $34, %r10\n",
  225. " movq $-1, %r8\n",
  226. " movq $0, %r9\n",
  227. " syscall\n",
  228. " movq %rax, %r10\n",
  229. " retq\n",
  230. "_start:\n",
  231. " call initialize_callstack\n"
  232. };
  233. for(const auto& op : generate_call("main")) {
  234. operations.push_back(op);
  235. }
  236. for(const auto& op : std::vector<std::string>{
  237. " movq $0, %rdi\n",
  238. " movq $60, %rax\n",
  239. " syscall\n"
  240. }
  241. ) {
  242. operations.push_back(op);
  243. }
  244. return operations;
  245. }
  246. }