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.

vm.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. #include "vm/vm.h"
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include "vm/builtins.h"
  5. static int stdio_inited = 0;
  6. static struct l2_io_file_writer std_output;
  7. static struct l2_io_file_writer std_error;
  8. static l2_word alloc_val(struct l2_vm *vm) {
  9. size_t id = l2_bitset_set_next(&vm->valueset);
  10. if (id >= vm->valuessize) {
  11. if (vm->valuessize == 0) {
  12. vm->valuessize = 16;
  13. }
  14. while (id >= vm->valuessize) {
  15. vm->valuessize *= 2;
  16. }
  17. vm->values = realloc(vm->values, sizeof(*vm->values) * vm->valuessize);
  18. }
  19. return (l2_word)id;
  20. }
  21. static double u32s_to_double(uint32_t high, uint32_t low) {
  22. double d;
  23. uint64_t num = (uint64_t)high << 32 | (uint64_t)low;
  24. memcpy(&d, &num, sizeof(num));
  25. return d;
  26. }
  27. static void gc_mark_array(struct l2_vm *vm, struct l2_vm_value *val);
  28. static void gc_mark_namespace(struct l2_vm *vm, struct l2_vm_value *val);
  29. static void gc_mark(struct l2_vm *vm, l2_word id) {
  30. struct l2_vm_value *val = &vm->values[id];
  31. if (val->flags & L2_VAL_MARKED) {
  32. return;
  33. }
  34. val->flags |= L2_VAL_MARKED;
  35. int typ = l2_vm_value_type(val);
  36. if (typ == L2_VAL_TYPE_ARRAY) {
  37. gc_mark_array(vm, val);
  38. } else if (typ == L2_VAL_TYPE_NAMESPACE) {
  39. gc_mark_namespace(vm, val);
  40. } else if (typ == L2_VAL_TYPE_FUNCTION) {
  41. gc_mark(vm, val->func.ns);
  42. }
  43. }
  44. static void gc_mark_array(struct l2_vm *vm, struct l2_vm_value *val) {
  45. if (val->array == NULL) {
  46. return;
  47. }
  48. for (size_t i = 0; i < val->array->len; ++i) {
  49. gc_mark(vm, val->array->data[i]);
  50. }
  51. }
  52. static void gc_mark_namespace(struct l2_vm *vm, struct l2_vm_value *val) {
  53. if (val->extra.ns_parent != 0) {
  54. gc_mark(vm, val->extra.ns_parent);
  55. }
  56. if (val->ns == NULL) {
  57. return;
  58. }
  59. for (size_t i = 0; i < val->ns->size; ++i) {
  60. l2_word key = val->ns->data[i];
  61. if (key == 0 || key == ~(l2_word)0) {
  62. continue;
  63. }
  64. gc_mark(vm, val->ns->data[val->ns->size + i]);
  65. }
  66. }
  67. static void gc_free(struct l2_vm *vm, l2_word id) {
  68. struct l2_vm_value *val = &vm->values[id];
  69. l2_bitset_unset(&vm->valueset, id);
  70. // Don't need to do anything more; the next round of GC will free
  71. // whichever values were only referenced by the array
  72. int typ = l2_vm_value_type(val);
  73. if (typ == L2_VAL_TYPE_ARRAY) {
  74. free(val->array);
  75. } else if (typ == L2_VAL_TYPE_BUFFER) {
  76. free(val->buffer);
  77. } else if (typ == L2_VAL_TYPE_NAMESPACE) {
  78. free(val->ns);
  79. }
  80. }
  81. static size_t gc_sweep(struct l2_vm *vm) {
  82. size_t freed = 0;
  83. // Skip ID 0, because that should always exist
  84. for (size_t i = 1; i < vm->valuessize; ++i) {
  85. if (!l2_bitset_get(&vm->valueset, i)) {
  86. continue;
  87. }
  88. struct l2_vm_value *val = &vm->values[i];
  89. if (!(val->flags & L2_VAL_MARKED)) {
  90. gc_free(vm, i);
  91. freed += 1;
  92. } else {
  93. val->flags &= ~L2_VAL_MARKED;
  94. }
  95. }
  96. return freed;
  97. }
  98. void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount) {
  99. if (!stdio_inited) {
  100. std_output.w.write = l2_io_file_write;
  101. std_output.f = stdout;
  102. std_error.w.write = l2_io_file_write;
  103. std_error.f = stderr;
  104. stdio_inited = 1;
  105. }
  106. vm->std_output = &std_output.w;
  107. vm->std_error = &std_error.w;
  108. vm->ops = ops;
  109. vm->opcount = opcount;
  110. vm->iptr = 0;
  111. vm->sptr = 0;
  112. vm->fsptr = 0;
  113. vm->values = NULL;
  114. vm->valuessize = 0;
  115. l2_bitset_init(&vm->valueset);
  116. // It's wasteful to allocate new 'none' variables all the time,
  117. // variable ID 0 should be the only 'none' variable in the system
  118. l2_word none_id = alloc_val(vm);
  119. vm->values[none_id].flags = L2_VAL_TYPE_NONE | L2_VAL_CONST;
  120. // Need to allocate a builtins namespace
  121. l2_word builtins = alloc_val(vm);
  122. vm->values[builtins].extra.ns_parent = 0;
  123. vm->values[builtins].ns = NULL; // Will be allocated on first insert
  124. vm->values[builtins].flags = L2_VAL_TYPE_NAMESPACE;
  125. vm->fstack[vm->fsptr].ns = builtins;
  126. vm->fstack[vm->fsptr].retptr = 0;
  127. vm->fsptr += 1;
  128. // Need to allocate a root namespace
  129. l2_word root = alloc_val(vm);
  130. vm->values[root].extra.ns_parent = builtins;
  131. vm->values[root].ns = NULL;
  132. vm->values[root].flags = L2_VAL_TYPE_NAMESPACE;
  133. vm->fstack[vm->fsptr].ns = root;
  134. vm->fstack[vm->fsptr].retptr = 0;
  135. vm->fsptr += 1;
  136. // Define a C function variable for every builtin
  137. l2_word id;
  138. l2_word key = 1;
  139. #define X(name, f) \
  140. id = alloc_val(vm); \
  141. vm->values[id].flags = L2_VAL_TYPE_CFUNCTION; \
  142. vm->values[id].cfunc = f; \
  143. l2_vm_namespace_set(&vm->values[builtins], key++, id);
  144. #include "builtins.x.h"
  145. #undef X
  146. }
  147. l2_word l2_vm_alloc(struct l2_vm *vm, enum l2_value_type typ, enum l2_value_flags flags) {
  148. l2_word id = alloc_val(vm);
  149. memset(&vm->values[id], 0, sizeof(vm->values[id]));
  150. vm->values[id].flags = typ | flags;
  151. return id;
  152. }
  153. void l2_vm_free(struct l2_vm *vm) {
  154. // Skip ID 0, because that's always NONE
  155. for (size_t i = 1; i < vm->valuessize; ++i) {
  156. if (!l2_bitset_get(&vm->valueset, i)) {
  157. continue;
  158. }
  159. gc_free(vm, i);
  160. }
  161. free(vm->values);
  162. l2_bitset_free(&vm->valueset);
  163. }
  164. size_t l2_vm_gc(struct l2_vm *vm) {
  165. for (l2_word sptr = 0; sptr < vm->sptr; ++sptr) {
  166. gc_mark(vm, vm->stack[sptr]);
  167. }
  168. for (l2_word fsptr = 0; fsptr < vm->fsptr; ++fsptr) {
  169. gc_mark(vm, vm->fstack[fsptr].ns);
  170. }
  171. return gc_sweep(vm);
  172. }
  173. void l2_vm_run(struct l2_vm *vm) {
  174. while ((enum l2_opcode)vm->ops[vm->iptr] != L2_OP_HALT) {
  175. l2_vm_step(vm);
  176. }
  177. }
  178. void l2_vm_step(struct l2_vm *vm) {
  179. enum l2_opcode opcode = (enum l2_opcode)vm->ops[vm->iptr++];
  180. l2_word word;
  181. switch (opcode) {
  182. case L2_OP_NOP:
  183. break;
  184. case L2_OP_POP:
  185. vm->sptr -= 1;
  186. break;
  187. case L2_OP_SWAP_POP:
  188. vm->stack[vm->sptr - 2] = vm->stack[vm->sptr - 1];
  189. vm->sptr -= 1;
  190. break;
  191. case L2_OP_DUP:
  192. vm->stack[vm->sptr] = vm->ops[vm->sptr - 1];
  193. vm->sptr += 1;
  194. break;
  195. case L2_OP_ADD:
  196. vm->stack[vm->sptr - 2] += vm->stack[vm->sptr - 1];
  197. vm->sptr -= 1;
  198. break;
  199. case L2_OP_FUNC_CALL:
  200. {
  201. l2_word argc = vm->ops[vm->iptr++];
  202. l2_word arr_id = alloc_val(vm);
  203. vm->values[arr_id].flags = L2_VAL_TYPE_ARRAY;
  204. vm->values[arr_id].array = malloc(
  205. sizeof(struct l2_vm_array) + sizeof(l2_word) * argc);
  206. struct l2_vm_array *arr = vm->values[arr_id].array;
  207. arr->len = argc;
  208. arr->size = argc;
  209. vm->sptr -= argc;
  210. for (l2_word i = 0; i < argc; ++i) {
  211. arr->data[i] = vm->stack[vm->sptr + i];
  212. }
  213. l2_word func_id = vm->stack[--vm->sptr];
  214. struct l2_vm_value *func = &vm->values[func_id];
  215. enum l2_value_type typ = l2_vm_value_type(func);
  216. // C functions are called differently from language functions
  217. if (typ == L2_VAL_TYPE_CFUNCTION) {
  218. vm->stack[vm->sptr++] = func->cfunc(vm, arr);
  219. break;
  220. }
  221. // Don't interpret a non-function as a function
  222. if (typ != L2_VAL_TYPE_FUNCTION) {
  223. // TODO: Error mechanism
  224. break;
  225. }
  226. vm->stack[vm->sptr++] = arr_id;
  227. l2_word ns_id = alloc_val(vm);
  228. func = &vm->values[func_id]; // func might be stale after alloc
  229. vm->values[ns_id].extra.ns_parent = func->func.ns;
  230. vm->values[ns_id].ns = NULL;
  231. vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE;
  232. vm->fstack[vm->fsptr].ns = ns_id;
  233. vm->fstack[vm->fsptr].retptr = vm->iptr;
  234. vm->fsptr += 1;
  235. vm->iptr = func->func.pos;
  236. }
  237. break;
  238. case L2_OP_RJMP:
  239. vm->iptr += vm->ops[vm->iptr] + 1;
  240. break;
  241. case L2_OP_STACK_FRAME_LOOKUP:
  242. {
  243. l2_word key = vm->ops[vm->iptr++];
  244. struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns];
  245. vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, ns, key);
  246. }
  247. break;
  248. case L2_OP_STACK_FRAME_SET:
  249. {
  250. l2_word key = vm->ops[vm->iptr++];
  251. l2_word val = vm->stack[vm->sptr - 1];
  252. struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns];
  253. l2_vm_namespace_set(ns, key, val);
  254. }
  255. break;
  256. case L2_OP_STACK_FRAME_REPLACE:
  257. {
  258. l2_word key = vm->ops[vm->iptr++];
  259. l2_word val = vm->stack[vm->sptr - 1];
  260. struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns];
  261. l2_vm_namespace_replace(vm, ns, key, val); // TODO: error if returns -1
  262. }
  263. break;
  264. case L2_OP_RET:
  265. {
  266. l2_word retval = vm->stack[--vm->sptr];
  267. vm->sptr -= 1; // Discard arguments array
  268. l2_word retptr = vm->fstack[--vm->fsptr].retptr;
  269. vm->stack[vm->sptr++] = retval;
  270. vm->iptr = retptr;
  271. }
  272. break;
  273. case L2_OP_ALLOC_NONE:
  274. vm->stack[vm->sptr++] = 0;
  275. break;
  276. case L2_OP_ALLOC_ATOM:
  277. word = alloc_val(vm);
  278. vm->values[word].flags = L2_VAL_TYPE_ATOM;
  279. vm->values[word].atom = vm->ops[vm->iptr++];
  280. vm->stack[vm->sptr++] = word;
  281. break;
  282. case L2_OP_ALLOC_REAL:
  283. {
  284. word = alloc_val(vm);
  285. l2_word high = vm->ops[vm->iptr++];
  286. l2_word low = vm->ops[vm->iptr++];
  287. vm->values[word].flags = L2_VAL_TYPE_REAL;
  288. vm->values[word].real = u32s_to_double(high, low);
  289. vm->stack[vm->sptr++] = word;
  290. }
  291. break;
  292. case L2_OP_ALLOC_BUFFER_STATIC:
  293. {
  294. word = alloc_val(vm);
  295. l2_word length = vm->ops[vm->iptr++];
  296. l2_word offset = vm->ops[vm->iptr++];
  297. vm->values[word].flags = L2_VAL_TYPE_BUFFER;
  298. vm->values[word].buffer = malloc(sizeof(struct l2_vm_buffer) + length);
  299. vm->values[word].buffer->len = length;
  300. memcpy(
  301. (unsigned char *)vm->values[word].buffer + sizeof(struct l2_vm_buffer),
  302. vm->ops + offset, length);
  303. vm->stack[vm->sptr] = word;
  304. vm->sptr += 1;
  305. }
  306. break;
  307. case L2_OP_ALLOC_ARRAY:
  308. {
  309. l2_word count = vm->ops[vm->iptr++];
  310. l2_word arr_id = alloc_val(vm);
  311. struct l2_vm_value *arr = &vm->values[arr_id];
  312. arr->flags = L2_VAL_TYPE_ARRAY;
  313. if (count == 0) {
  314. arr->array = NULL;
  315. vm->stack[vm->sptr++] = arr_id;
  316. break;
  317. }
  318. arr->array = malloc(sizeof(struct l2_vm_array) + count * sizeof(l2_word));
  319. arr->array->len = count;
  320. arr->array->size = count;
  321. for (l2_word i = 0; i < count; ++i) {
  322. arr->array->data[count - 1 - i] = vm->stack[--vm->sptr];
  323. }
  324. vm->stack[vm->sptr++] = arr_id;
  325. }
  326. break;
  327. case L2_OP_ALLOC_NAMESPACE:
  328. word = alloc_val(vm);
  329. vm->values[word].flags = L2_VAL_TYPE_NAMESPACE;
  330. vm->values[word].extra.ns_parent = 0;
  331. vm->values[word].ns = NULL; // Will be allocated on first insert
  332. vm->stack[vm->sptr] = word;
  333. vm->sptr += 1;
  334. break;
  335. case L2_OP_ALLOC_FUNCTION:
  336. word = alloc_val(vm);
  337. vm->values[word].flags = L2_VAL_TYPE_FUNCTION;
  338. vm->values[word].func.pos = vm->ops[vm->iptr++];
  339. vm->values[word].func.ns = vm->fstack[vm->fsptr - 1].ns;
  340. vm->stack[vm->sptr] = word;
  341. vm->sptr += 1;
  342. break;
  343. case L2_OP_NAMESPACE_SET:
  344. {
  345. l2_word key = vm->ops[vm->iptr++];
  346. l2_word val = vm->stack[vm->sptr - 1];
  347. l2_word ns = vm->stack[vm->sptr - 2];
  348. l2_vm_namespace_set(&vm->values[ns], key, val);
  349. }
  350. break;
  351. case L2_OP_NAMESPACE_LOOKUP:
  352. {
  353. l2_word key = vm->ops[vm->iptr++];
  354. l2_word ns = vm->stack[--vm->sptr];
  355. vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, &vm->values[ns], key);
  356. }
  357. break;
  358. case L2_OP_ARRAY_LOOKUP:
  359. {
  360. l2_word key = vm->ops[vm->iptr++];
  361. l2_word arr = vm->stack[--vm->sptr];
  362. // TODO: Error if out of bounds or incorrect type
  363. vm->stack[vm->sptr++] = vm->values[arr].array->data[key];
  364. }
  365. break;
  366. case L2_OP_ARRAY_SET:
  367. {
  368. l2_word key = vm->ops[vm->iptr++];
  369. l2_word val = vm->stack[vm->sptr - 1];
  370. l2_word arr = vm->stack[vm->sptr - 2];
  371. // TODO: Error if out of bounds or incorrect type
  372. vm->values[arr].array->data[key] = val;
  373. }
  374. break;
  375. case L2_OP_DYNAMIC_LOOKUP:
  376. {
  377. l2_word key_id = vm->stack[--vm->sptr];
  378. l2_word container_id = vm->stack[--vm->sptr];
  379. struct l2_vm_value *key = &vm->values[key_id];
  380. struct l2_vm_value *container = &vm->values[container_id];
  381. if (
  382. l2_vm_value_type(key) == L2_VAL_TYPE_REAL &&
  383. l2_vm_value_type(container) == L2_VAL_TYPE_ARRAY) {
  384. // TODO: Error if out of bounds
  385. vm->stack[vm->sptr++] = container->array->data[(size_t)key->real];
  386. } else if (
  387. l2_vm_value_type(key) == L2_VAL_TYPE_ATOM &&
  388. l2_vm_value_type(container) == L2_VAL_TYPE_NAMESPACE) {
  389. // TODO: Error if out of bounds
  390. vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, container, key->atom);
  391. } else {
  392. // TODO: error
  393. }
  394. }
  395. break;
  396. case L2_OP_DYNAMIC_SET:
  397. {
  398. l2_word val = vm->stack[--vm->sptr];
  399. l2_word key_id = vm->stack[--vm->sptr];
  400. l2_word container_id = vm->stack[--vm->sptr];
  401. vm->stack[vm->sptr++] = val;
  402. struct l2_vm_value *key = &vm->values[key_id];
  403. struct l2_vm_value *container = &vm->values[container_id];
  404. if (
  405. l2_vm_value_type(key) == L2_VAL_TYPE_REAL &&
  406. l2_vm_value_type(container) == L2_VAL_TYPE_ARRAY) {
  407. // TODO: Error if out of bounds
  408. container->array->data[(size_t)key->real] = val;
  409. } else if (
  410. l2_vm_value_type(key) == L2_VAL_TYPE_ATOM &&
  411. l2_vm_value_type(container) == L2_VAL_TYPE_NAMESPACE) {
  412. // TODO: Error if out of bounds
  413. l2_vm_namespace_set(container, key->atom, val);
  414. } else {
  415. // TODO: error
  416. }
  417. }
  418. break;
  419. case L2_OP_HALT:
  420. break;
  421. }
  422. }