vm.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "vm.h"
  5. #include "gc.h"
  6. #include "builtins.h"
  7. //#define DEBUG_COUNT_BUILTINS
  8. #ifdef DEBUG_COUNT_BUILTINS
  9. int count_builtin[50] = { 0 };
  10. #endif
  11. //#define DEBUG
  12. void vm_put_place(unsigned char place_sort, scm place_index, scm obj) {
  13. switch(place_sort) {
  14. case 'r':
  15. vm_reg_ret = obj;
  16. break;
  17. case 'g':
  18. vm_set_global(place_index, obj);
  19. break;
  20. case 't':
  21. vm_set_stack_top(place_index, obj);
  22. break;
  23. case 'l':
  24. vm_set_stack_base(place_index, obj);
  25. break;
  26. case 'e':
  27. clos_set_env(vm_reg_env, place_index, obj);
  28. break;
  29. default:
  30. fprintf(stderr, "Unknown place sort %c\n", place_sort);
  31. exit(-1);
  32. }
  33. }
  34. void execute(void) {
  35. unsigned char c;
  36. while(1) {
  37. #ifdef DEBUG
  38. char tmp_buf[512];
  39. strncpy(tmp_buf, (char*)(bytecode+place), 32);
  40. printf("<<<%s>>>\n", tmp_buf);
  41. #endif
  42. c = bytecode[place++];
  43. switch(c) {
  44. case 'H':
  45. vm_halt();
  46. break;
  47. case 'Q':
  48. vm_quit();
  49. break;
  50. case 'B':
  51. vm_builtin();
  52. break;
  53. case 'A':
  54. vm_alloc();
  55. break;
  56. case 'c':
  57. vm_make_closure();
  58. break;
  59. case 'E':
  60. vm_set_closure();
  61. break;
  62. case 'C':
  63. vm_call();
  64. break;
  65. case 'T':
  66. vm_tail_call();
  67. break;
  68. case 'M':
  69. vm_move();
  70. break;
  71. case 'R':
  72. vm_return();
  73. break;
  74. case 'b':
  75. vm_branch();
  76. break;
  77. case 'J':
  78. vm_jump();
  79. break;
  80. default:
  81. fprintf(stderr, "Unknown VM instruction [%c] at %ld\n", c, place);
  82. //strncpy(tmp_buf, (char*)(bytecode), 32);
  83. //printf("<<<%s>>>\n", tmp_buf);
  84. //printf("%c %d\n", i1, blt_tsh);
  85. exit(-1);
  86. }
  87. }
  88. }
  89. void vm_halt() {
  90. #ifdef DEBUG
  91. fprintf(stderr, "VM [%s]\n", "HALT");
  92. #endif
  93. while(bytecode[place++] != '\n') {}
  94. }
  95. void vm_quit() {
  96. #ifdef DEBUG
  97. fprintf(stderr, "VM [%s]\n", "QUIT");
  98. #endif
  99. #ifdef DEBUG_COUNT_BUILTINS
  100. for(int i = 0; i < 50; i++) {
  101. printf("BLTN[%2d] used %4d times\n", i, count_builtin[i]);
  102. }
  103. #endif
  104. exit(0);
  105. }
  106. void vm_builtin() {
  107. #ifdef DEBUG
  108. fprintf(stderr, "VM [%s]\n", "BUILTIN");
  109. #endif
  110. unsigned char place_sort;
  111. scm place_index;
  112. scm n;
  113. bytecode_read_place(&place_sort, &place_index);
  114. n = bytecode_read_n(2);
  115. bytecode_read_args();
  116. #ifdef DEBUG
  117. fprintf(stderr, "VM [%s %ld]\n", "BUILTIN", n);
  118. for(int i = 0; i < bytecode_args_num; i++) {
  119. void builtin_display(scm);
  120. printf("ARG %d %ld\n", i, scm_get_tag(bytecode_args[i]));
  121. scm_display(bytecode_args[i]);
  122. puts("");
  123. }
  124. puts(".");
  125. #endif
  126. builtin_handler h;
  127. scm res;
  128. h = handler[n];
  129. if(!h) {
  130. fprintf(stderr, "unimplemented or missing builtin %ld\n", n);
  131. exit(-1);
  132. }
  133. #ifdef DEBUG_COUNT_BUILTINS
  134. count_builtin[n]++;
  135. #endif
  136. res = h();
  137. vm_put_place(place_sort, place_index, res);
  138. }
  139. void vm_alloc() {
  140. #ifdef DEBUG
  141. fprintf(stderr, "VM [%s]\n", "ALLOC");
  142. #endif
  143. scm n;
  144. n = bytecode_read_n(2);
  145. stack_grow(n);
  146. }
  147. void vm_make_closure() {
  148. #ifdef DEBUG
  149. fprintf(stderr, "VM [%s]\n", "MAKE-CLOSURE");
  150. #endif
  151. unsigned char place_sort;
  152. scm place_index;
  153. scm lbl;
  154. scm n;
  155. bytecode_read_place(&place_sort, &place_index);
  156. lbl = bytecode_read_n(6);
  157. n = bytecode_read_n(2);
  158. scm clo;
  159. scm *ptr;
  160. int i;
  161. clo = heap_alloc_closure(n, lbl);
  162. ptr = get_clos(clo);
  163. for(i = 0; i < n; i++) {
  164. ptr[2 + i] = 0;
  165. }
  166. vm_put_place(place_sort, place_index, clo);
  167. }
  168. void vm_set_closure() {
  169. #ifdef DEBUG
  170. fprintf(stderr, "VM [%s]\n", "SET-CLOSURE!");
  171. #endif
  172. scm clo;
  173. scm n;
  174. scm val;
  175. clo = bytecode_read_val();
  176. n = bytecode_read_n(2);
  177. val = bytecode_read_val();
  178. clos_set_env(clo, n, val);
  179. }
  180. void vm_call() {
  181. #ifdef DEBUG
  182. fprintf(stderr, "VM [%s]\n", "CALL");
  183. #endif
  184. scm clo;
  185. int i;
  186. clo = bytecode_read_val();
  187. bytecode_read_args();
  188. stack_push(0xC0DEDBADC0DEDBAD);
  189. stack_push(vm_stack_base_ptr);
  190. stack_push(vm_reg_env);
  191. stack_push(place);
  192. stack_push(0xC0FFEEEEEEEEEEEE);
  193. vm_stack_base_ptr = vm_stack_ptr;
  194. for(i = 0; i < bytecode_args_num; i++) {
  195. stack_push(bytecode_args[i]);
  196. }
  197. vm_reg_env = clo;
  198. place = clos_lbl(clo);
  199. }
  200. void vm_tail_call() {
  201. #ifdef DEBUG
  202. fprintf(stderr, "VM [%s]\n", "TAIL-CALL");
  203. #endif
  204. scm clo;
  205. int i;
  206. clo = bytecode_read_val();
  207. bytecode_read_args();
  208. vm_stack_ptr = vm_stack_base_ptr;
  209. for(i = 0; i < bytecode_args_num; i++) {
  210. stack_push(bytecode_args[i]);
  211. }
  212. vm_reg_env = clo;
  213. place = clos_lbl(clo);
  214. }
  215. void vm_move() {
  216. #ifdef DEBUG
  217. fprintf(stderr, "VM [%s]\n", "MOVE");
  218. #endif
  219. unsigned char place_sort;
  220. scm place_index;
  221. scm val;
  222. bytecode_read_place(&place_sort, &place_index);
  223. val = bytecode_read_val();
  224. vm_put_place(place_sort, place_index, val);
  225. }
  226. void vm_return() {
  227. #ifdef DEBUG
  228. fprintf(stderr, "VM [%s]\n", "RETURN");
  229. #endif
  230. scm tmp;
  231. vm_stack_ptr = vm_stack_base_ptr;
  232. tmp = stack_pop();
  233. assert(tmp == 0xC0FFEEEEEEEEEEEE);
  234. place = stack_pop();
  235. vm_reg_env = stack_pop();
  236. vm_stack_base_ptr = stack_pop();
  237. tmp = stack_pop();
  238. assert(tmp == 0xC0DEDBADC0DEDBAD);
  239. }
  240. void vm_branch() {
  241. #ifdef DEBUG
  242. fprintf(stderr, "VM [%s]\n", "BRANCH");
  243. #endif
  244. scm ip;
  245. ip = bytecode_read_n(6);
  246. if(vm_reg_ret != atom_tag_fals)
  247. place = ip;
  248. }
  249. void vm_jump() {
  250. #ifdef DEBUG
  251. fprintf(stderr, "VM [%s]\n", "JUMP");
  252. #endif
  253. scm ip;
  254. ip = bytecode_read_n(6);
  255. place = ip;
  256. }