aboutsummaryrefslogtreecommitdiffstats
path: root/src/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm.c')
-rw-r--r--src/vm.c90
1 files changed, 65 insertions, 25 deletions
diff --git a/src/vm.c b/src/vm.c
index 574f4fa..cb1b6cd 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -17,10 +17,22 @@ typedef union Constant {
17 17
18typedef struct Chunk { 18typedef struct Chunk {
19 Instruction *code; 19 Instruction *code;
20
21 // Constant values that fit in 64 bits.
20 Constant *constants; 22 Constant *constants;
21 Str file_name; 23 IntIntMap *intmap;
22 sz reg_idx;
23 sz const_idx; 24 sz const_idx;
25
26 // Constant strings.
27 Str *strings;
28 StrIntMap *strmap;
29 sz str_idx;
30
31 // Number of registers currently used in this chunk.
32 sz reg_idx;
33
34 // Debugging.
35 Str file_name;
24 Arena *storage; 36 Arena *storage;
25 // TODO: line/col info for debugging. 37 // TODO: line/col info for debugging.
26} Chunk; 38} Chunk;
@@ -205,6 +217,12 @@ disassemble_chunk(Chunk chunk) {
205 chunk.constants[i]); 217 chunk.constants[i]);
206 } 218 }
207 } 219 }
220 if (array_size(chunk.strings) > 0) {
221 println("%s: ========== strings =========", chunk.file_name);
222 for (sz i = 0; i < array_size(chunk.strings); i++) {
223 println("%s: %x{2}: %s", chunk.file_name, i, chunk.strings[i]);
224 }
225 }
208} 226}
209 227
210#define N_CONST 256 228#define N_CONST 256
@@ -292,6 +310,7 @@ vm_run(VM *vm) {
292 310
293typedef enum { 311typedef enum {
294 COMP_CONST, 312 COMP_CONST,
313 COMP_STRING,
295 COMP_REG, 314 COMP_REG,
296 COMP_ERR, 315 COMP_ERR,
297} CompResultType; 316} CompResultType;
@@ -303,11 +322,19 @@ typedef struct CompResult {
303 322
304CompResult compile_expr(Chunk *chunk, Node *node); 323CompResult compile_expr(Chunk *chunk, Node *node);
305 324
306// #define EMIT_OP(OP, CHUNK, ARENA) 325#define EMIT_OP(OP, DST, A, B, NODE, CHUNK) \
326 do { \
327 Instruction inst = (Instruction){ \
328 .op = (OP), \
329 .dst = (DST), \
330 .a = (A), \
331 .b = (B), \
332 }; \
333 array_push((CHUNK)->code, inst, (CHUNK)->storage); \
334 } while (0)
307 335
308CompResult 336CompResult
309compile_binary(OpCode op, Chunk *chunk, Node *node) { 337compile_binary(OpCode op, Chunk *chunk, Node *node) {
310 sz reg_dst = chunk->reg_idx++;
311 CompResult comp_a = compile_expr(chunk, node->left); 338 CompResult comp_a = compile_expr(chunk, node->left);
312 CompResult comp_b = compile_expr(chunk, node->right); 339 CompResult comp_b = compile_expr(chunk, node->right);
313 sz reg_a; 340 sz reg_a;
@@ -315,9 +342,7 @@ compile_binary(OpCode op, Chunk *chunk, Node *node) {
315 switch (comp_a.type) { 342 switch (comp_a.type) {
316 case COMP_CONST: { 343 case COMP_CONST: {
317 reg_a = chunk->reg_idx++; 344 reg_a = chunk->reg_idx++;
318 Instruction inst = 345 EMIT_OP(OP_LD64K, reg_a, comp_a.idx, 0, node, chunk);
319 (Instruction){.op = OP_LD64K, .dst = reg_a, .a = comp_a.idx};
320 array_push(chunk->code, inst, chunk->storage);
321 } break; 346 } break;
322 case COMP_REG: { 347 case COMP_REG: {
323 reg_a = comp_a.idx; 348 reg_a = comp_a.idx;
@@ -329,9 +354,7 @@ compile_binary(OpCode op, Chunk *chunk, Node *node) {
329 switch (comp_b.type) { 354 switch (comp_b.type) {
330 case COMP_CONST: { 355 case COMP_CONST: {
331 reg_b = chunk->reg_idx++; 356 reg_b = chunk->reg_idx++;
332 Instruction inst = 357 EMIT_OP(OP_LD64K, reg_b, comp_b.idx, 0, node, chunk);
333 (Instruction){.op = OP_LD64K, .dst = reg_b, .a = comp_b.idx};
334 array_push(chunk->code, inst, chunk->storage);
335 } break; 358 } break;
336 case COMP_REG: { 359 case COMP_REG: {
337 reg_b = comp_b.idx; 360 reg_b = comp_b.idx;
@@ -340,9 +363,9 @@ compile_binary(OpCode op, Chunk *chunk, Node *node) {
340 return (CompResult){.type = COMP_ERR}; 363 return (CompResult){.type = COMP_ERR};
341 } break; 364 } break;
342 } 365 }
343 Instruction inst = 366 sz reg_dst = comp_a.idx; // Less registers
344 (Instruction){.op = op, .dst = reg_dst, .a = reg_a, .b = reg_b}; 367 // sz reg_dst = chunk->reg_idx++; // Better for optimization
345 array_push(chunk->code, inst, chunk->storage); 368 EMIT_OP(op, reg_dst, reg_a, reg_b, node, chunk);
346 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 369 return (CompResult){.type = COMP_REG, .idx = reg_dst};
347} 370}
348 371
@@ -354,26 +377,43 @@ compile_expr(Chunk *chunk, Node *node) {
354 case NODE_MUL: return compile_binary(OP_MUL, chunk, node); break; 377 case NODE_MUL: return compile_binary(OP_MUL, chunk, node); break;
355 case NODE_DIV: return compile_binary(OP_DIV, chunk, node); break; 378 case NODE_DIV: return compile_binary(OP_DIV, chunk, node); break;
356 case NODE_MOD: return compile_binary(OP_MOD, chunk, node); break; 379 case NODE_MOD: return compile_binary(OP_MOD, chunk, node); break;
380 case NODE_TRUE:
381 case NODE_FALSE:
357 case NODE_NUM_FLOAT: 382 case NODE_NUM_FLOAT:
358 case NODE_NUM_INT: { 383 case NODE_NUM_INT: {
384 sz value = node->value.i;
359 // Make sure we don't have duplicated constants. 385 // Make sure we don't have duplicated constants.
360 for (sz i = 0; i < chunk->const_idx; i++) { 386 IntIntMap *map = intintmap_lookup(&chunk->intmap, value);
361 if (node->value.i == chunk->constants[i].i) { 387 if (!map) {
362 return (CompResult){ 388 map = intintmap_insert(&chunk->intmap, value,
363 .type = COMP_CONST, 389 chunk->const_idx++, chunk->storage);
364 .idx = i, 390 Constant c = (Constant){.i = node->value.i};
365 }; 391 array_push(chunk->constants, c, chunk->storage);
366 }
367 } 392 }
368 Constant c = (Constant){.i = node->value.i};
369 array_push(chunk->constants, c, chunk->storage);
370 return (CompResult){ 393 return (CompResult){
371 .type = COMP_CONST, 394 .type = COMP_CONST,
372 .idx = chunk->const_idx++, 395 .idx = map->val,
396 };
397 } break;
398 case NODE_STRING: {
399 Str string = node->value.str;
400 // Make sure we don't have duplicated strings.
401 StrIntMap *map = strintmap_lookup(&chunk->strmap, string);
402 if (!map) {
403 map = strintmap_insert(&chunk->strmap, string, chunk->str_idx++,
404 chunk->storage);
405 array_push(chunk->strings, string, chunk->storage);
406 }
407 return (CompResult){
408 .type = COMP_STRING,
409 .idx = map->val,
373 }; 410 };
374 } break; 411 } break;
375 default: break; 412 default: {
413 eprintln("error: compilation not implemented for node %s",
414 node_str[node->kind]);
415 exit(EXIT_FAILURE);
416 } break;
376 } 417 }
377 return (CompResult){.type = COMP_ERR}; 418 return (CompResult){.type = COMP_ERR};
378} 419}
379