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 14KB

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