interpreter.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "qcodes.h"
  6. #include "objects.h"
  7. #include "information.h"
  8. #include "symboltable.h"
  9. #include "glovars.h"
  10. #include "allocator.h"
  11. #include "vm.h"
  12. void vm_exec(scm *code) {
  13. static void* lbl[] = {
  14. [CODE_HALT] = &&lbl_halt,
  15. [CODE_DATUM_FALSE] = &&lbl_datum_false,
  16. [CODE_DATUM_TRUE] = &&lbl_datum_true,
  17. [CODE_DATUM_NULL] = &&lbl_datum_null,
  18. [CODE_DATUM_SYMBOL] = &&lbl_datum_symbol,
  19. [CODE_DATUM_CHAR] = &&lbl_datum_char,
  20. [CODE_DATUM_NUMBER] = &&lbl_datum_number,
  21. [CODE_DATUM_STRING] = &&lbl_datum_string,
  22. [CODE_ALLOCATE_CLOSURE] = &&lbl_allocate_closure,
  23. [CODE_CLOSURE_SET] = &&lbl_closure_set,
  24. [CODE_VAR_GLO] = &&lbl_var_glo,
  25. [CODE_SET_GLO] = &&lbl_set_glo,
  26. [CODE_VAR_LOC] = &&lbl_var_loc,
  27. [CODE_SET_LOC] = &&lbl_set_loc,
  28. [CODE_VAR_ENV] = &&lbl_var_env,
  29. [CODE_SET_ENV] = &&lbl_set_env,
  30. [CODE_CLO_SET_ACC] = &&lbl_clo_set_acc,
  31. [CODE_CLO_SET_LOC] = &&lbl_clo_set_loc,
  32. [CODE_SET_CLO_REG] = &&lbl_set_clo_reg,
  33. [CODE_JUMP] = &&lbl_jump,
  34. [CODE_BRANCH] = &&lbl_branch,
  35. [CODE_PUSH] = &&lbl_push,
  36. [CODE_STACK_GROW] = &&lbl_stack_grow,
  37. [CODE_STACKFRAME] = &&lbl_stackframe,
  38. [CODE_CALL] = &&lbl_call,
  39. [CODE_RET] = &&lbl_ret,
  40. [CODE_SHIFTBACK] = &&lbl_shiftback,
  41. [CODE_INFORMATION] = &&lbl_information,
  42. };
  43. struct global *glo;
  44. scm idx;
  45. scm num;
  46. #define CODEWORD (*(code++))
  47. #define NEXT goto *lbl[CODEWORD]
  48. //#define NEXT printf("[%ld]\n", *code); goto *lbl[CODEWORD]
  49. #define DBG(x) (void)0
  50. //#define DBG(x) x
  51. NEXT;
  52. lbl_halt:
  53. return;
  54. lbl_datum_false:
  55. reg_acc = ATOM_FLS;
  56. NEXT;
  57. lbl_datum_true:
  58. reg_acc = ATOM_TRU;
  59. NEXT;
  60. lbl_datum_null:
  61. reg_acc = ATOM_NUL;
  62. NEXT;
  63. lbl_datum_symbol:
  64. reg_acc = CODEWORD;
  65. NEXT;
  66. lbl_datum_char:
  67. reg_acc = CODEWORD;
  68. NEXT;
  69. lbl_datum_number:
  70. reg_acc = mk_numb(CODEWORD);
  71. NEXT;
  72. lbl_datum_string:
  73. reg_acc = CODEWORD;
  74. NEXT;
  75. lbl_allocate_closure:
  76. idx = CODEWORD;
  77. num = CODEWORD;
  78. reg_clo = allocate_clos(code + num, idx);
  79. NEXT;
  80. lbl_closure_set:
  81. idx = CODEWORD;
  82. scm_getptr(reg_clo)[2 + idx] = reg_acc;
  83. NEXT;
  84. lbl_var_glo:
  85. glo = (void*)CODEWORD;
  86. DBG(printf("[G:%p:%s]\n", glo, lookup(get_sym(glo->name))));
  87. reg_acc = glo->val;
  88. NEXT;
  89. lbl_set_glo:
  90. glo = (void*)CODEWORD;
  91. glo->val = reg_acc;
  92. NEXT;
  93. lbl_var_loc:
  94. idx = CODEWORD;
  95. reg_acc = stack[reg_rbp + 1 + idx];
  96. NEXT;
  97. lbl_set_loc:
  98. idx = CODEWORD;
  99. stack[reg_rbp + 1 + idx] = reg_acc;
  100. NEXT;
  101. lbl_var_env:
  102. idx = CODEWORD;
  103. reg_acc = reg_env[idx];
  104. NEXT;
  105. lbl_set_env:
  106. idx = CODEWORD;
  107. reg_env[idx] = reg_acc;
  108. NEXT;
  109. lbl_clo_set_acc:
  110. reg_acc = reg_clo;
  111. NEXT;
  112. lbl_clo_set_loc:
  113. idx = CODEWORD;
  114. stack[reg_rbp + 1 + idx] = reg_clo;
  115. NEXT;
  116. lbl_set_clo_reg:
  117. reg_clo = reg_acc;
  118. NEXT;
  119. lbl_jump:
  120. idx = CODEWORD;
  121. code += idx;
  122. NEXT;
  123. lbl_branch:
  124. idx = CODEWORD;
  125. if (reg_acc == ATOM_FLS)
  126. code += idx;
  127. NEXT;
  128. lbl_push:
  129. stack[++reg_rsp] = reg_acc;
  130. NEXT;
  131. lbl_stack_grow:
  132. reg_rsp += CODEWORD;
  133. NEXT;
  134. lbl_stackframe:
  135. idx = CODEWORD;
  136. stack[++reg_rsp] = 0xC0FFEEEEEEEEEEEE;
  137. stack[++reg_rsp] = (scm)(code + idx);
  138. stack[++reg_rsp] = (scm)reg_env;
  139. stack[++reg_rsp] = reg_rbp;
  140. stack[++reg_rsp] = 0xDEADBEEFDEADBEEF;
  141. reg_rbp_tmp = reg_rsp;
  142. NEXT;
  143. lbl_call:
  144. reg_rbp = reg_rbp_tmp;
  145. switch(scm_gettag(reg_acc)) {
  146. case TAG_BLTN:
  147. reg_acc = (get_bltn(reg_acc))();
  148. goto lbl_ret;
  149. break;
  150. case TAG_CLOS:
  151. code = PTR_SCM(get_clos(reg_acc)[1]);
  152. reg_env = get_clos(reg_acc)+2;
  153. break;
  154. default:
  155. stack_trace();
  156. fprintf(stderr, "call: not a closure 0x%lx %ld\n", reg_acc, scm_gettag(reg_acc));
  157. exit(1);
  158. }
  159. NEXT;
  160. lbl_ret:
  161. reg_rsp = reg_rbp;
  162. assert(stack[reg_rsp--] == 0xDEADBEEFDEADBEEF);
  163. reg_rbp = stack[reg_rsp--];
  164. reg_env = PTR_SCM(stack[reg_rsp--]);
  165. code = PTR_SCM(stack[reg_rsp--]);
  166. assert(stack[reg_rsp--] == 0xC0FFEEEEEEEEEEEE);
  167. NEXT;
  168. lbl_shiftback:
  169. num = CODEWORD;
  170. for(idx = 0; idx < num; idx++)
  171. stack[reg_rbp + 1 + idx] = stack[reg_rsp - num + 1 + idx];
  172. reg_rsp = reg_rbp + num + 1;
  173. reg_rbp_tmp = reg_rbp;
  174. NEXT;
  175. lbl_information:
  176. (void)CODEWORD;
  177. (void)CODEWORD;
  178. NEXT;
  179. }