diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-11-06 21:22:05 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-11-06 21:22:05 +0000 |
| commit | 7ba0f259433a03ca930dfb55e1927ce1a0c06cf2 (patch) | |
| tree | a2a3c78ec47c25b6f880fddccca266f2b791638c /src/vm.cpp | |
| parent | 6c2772d09338f044096240eeb01aa09d11ddda59 (diff) | |
Separate SSA opt; Basic Timings for sections only
Diffstat (limited to 'src/vm.cpp')
| -rw-r--r-- | src/vm.cpp | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/src/vm.cpp b/src/vm.cpp index a3f1f7f98..db9941553 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -1,2 +1,356 @@ +#if 0 // TODO(bill): COMPLETELY REWORK THIS ENTIRE INTERPRETER #include "dyncall/include/dyncall.h" + +struct vmInterpreter; + +/* +Types: +boolean +integer +float +pointer +string +any +array +vector +slice +maybe +struct +union +raw_union +enum +tuple +proc +*/ + +struct vmProcedure { + Type * type; + String name; + b32 is_external; +}; + +struct vmValue { + void *data; + i32 id; + Type *type; + union { + i64 v_int; + f32 v_f32; + f64 v_f64; + vmProcedure * v_proc; + }; +}; + +Array<vmValue> vm_empty_args = {}; + +struct vmFrame { + vmInterpreter *i; + vmFrame * caller; + ssaProcedure * proc; + ssaBlock * block; + ssaBlock * prev_block; + isize instr_index; // For the current block + + Array<void *> env; // Index == instr id + vmValue result; +}; + +struct vmInterpreter { + ssaModule * module; + BaseTypeSizes sizes; + gbArena stack_arena; + gbAllocator stack_allocator; + gbAllocator heap_allocator; + + Array<vmFrame> frame_stack; + Map<vmValue> globals; +}; + +enum vmContinuation { + vmContinuation_Next, + vmContinuation_Return, + vmContinuation_Branch, +}; + + + + +i64 vm_size_of(vmInterpreter *i, Type *type) { + return type_size_of(i->sizes, i->heap_allocator, type); +} +i64 vm_align_of(vmInterpreter *i, Type *type) { + return type_align_of(i->sizes, i->heap_allocator, type); +} +i64 vm_offset_of(vmInterpreter *i, Type *type, i64 index) { + return type_offset_of(i->sizes, i->heap_allocator, type, index); +} + + + + + + +Array<vmValue> vm_prepare_call(vmFrame *f, ssaInstr *instr, vmValue *proc) { + GB_ASSERT(instr->kind == ssaInstr_Call); + + *proc = vm_get_value(f, instr->Call.value); + + Array<vmValue> args = {}; + array_init_count(&args, f->i->stack_allocator, instr->Call.arg_count); + + for (isize i = 0; i < instr->Call.arg_count; i++) { + args[i] = vm_get_value(f, instr->Call.args[i]); + } + + return args; +} + + +vmContinuation vm_visit_instr(vmFrame *f, ssaValue *value) { + ssaInstr *instr = &value->Instr; +#if 1 + if (instr->kind != ssaInstr_Comment) { + gb_printf("instr: %.*s\n", LIT(ssa_instr_strings[instr->kind])); + } +#endif + switch (instr->kind) { + case ssaInstr_StartupRuntime: { + + } break; + + case ssaInstr_Comment: break; + + case ssaInstr_Local: { + Type *type = ssa_type(value); + GB_ASSERT(is_type_pointer(type)); + i64 size = gb_max(1, vm_size_of(f->i, type)); + i64 align = gb_max(1, vm_align_of(f->i, type)); + void *mem = gb_alloc_align(f->i->stack_allocator, size, align); + + array_add(&f->locals, mem); + } break; + + case ssaInstr_ZeroInit: { + Type *pt = ssa_type(instr->ZeroInit.address); + GB_ASSERT(is_type_pointer(pt)); + vmValue addr = vm_get_value(f, instr->ZeroInit.address); + GB_ASSERT(are_types_identical(addr.type, ptr)); + i64 size = vm_size_of(vm, type_deref(pt)); + gb_zero(addr.v_ptr, size); + } break; + + case ssaInstr_Store: { + ssaValue *addr = instr->Store.Address; + ssaValue *value = instr->Store.Value; + } break; + + case ssaInstr_Load: { + ssaValue *addr = instr->Load.Address; + } break; + + case ssaInstr_ArrayElementPtr: { + + } break; + + case ssaInstr_StructElementPtr: { + + } break; + + case ssaInstr_PtrOffset: { + + } break; + + case ssaInstr_Phi: + for_array(i, f->block->preds) { + ssaBlock *pred = f->block->preds[i]; + if (f->prev_block == pred) { + vmValue edge = vm_get_value(f, instr->Phi.edges[i]); + // vm_set_value(f, value, edge); + break; + } + } + break; + + case ssaInstr_ArrayExtractValue: { + + } break; + + case ssaInstr_StructExtractValue: { + + } break; + + case ssaInstr_Jump: + f->prev_block = f->block; + f->block = instr->Jump.block; + return vmContinuation_Branch; + + case ssaInstr_If: + f->prev_block = f->block; + if (vm_get_value(f, instr->If.cond).v_int != 0) { + f->block = instr->If.true_block; + } else { + f->block = instr->If.false_block; + } + return vmContinuation_Branch; + + case ssaInstr_Return: + if (instr->Return.value != NULL) { + Type *type = base_type(ssa_type(instr->Return.value)); + GB_ASSERT(is_type_tuple(type)); + f->result = vm_get_value(f, instr->Return.value); + if (type->Tuple.variable_count == 1) { + f->result.type = type->Tuple.variables[0]->type; + } + } + f->block = NULL; + return vmContinuation_Return; + + case ssaInstr_Conv: { + + } break; + + case ssaInstr_Unreachable: { + GB_PANIC("Unreachable"); + } break; + + case ssaInstr_BinaryOp: { + + } break; + + case ssaInstr_Call: { + + } break; + + case ssaInstr_Select: { + + } break; + + case ssaInstr_VectorExtractElement: { + + } break; + + case ssaInstr_VectorInsertElement: { + + } break; + + case ssaInstr_VectorShuffle: { + + } break; + + case ssaInstr_BoundsCheck: { + + } break; + + case ssaInstr_SliceBoundsCheck: { + + } break; + + default: { + GB_PANIC("<unknown instr> %d\n", instr->kind); + } break; + } + + return vmContinuation_Next; +} + + +void vm_run_frame(vmFrame *f) { + for (;;) { + for_array(i, f->block->instrs) { + ssaValue *v = f->block->instrs[i]; + GB_ASSERT(v->kind == ssaValue_Instr); + switch (vm_visit_instr(f, v)) { + case vmContinuation_Return: + return; + case vmContinuation_Next: + // Do nothing + break; + case vmContinuation_Branch: + goto end; + } + } + end: + ; + } +} + +ssaProcedure *vm_lookup_proc(vmInterpreter *i, String name) { + ssaValue **found = map_get(&i->module->members, hash_string(name)); + if (found == NULL) { + return NULL; + } + ssaValue *v = *found; + if (v->kind != ssaValue_Proc) { + return NULL; + } + + return &v->Proc; +} + +vmValue vm_ext(vmFrame *caller, Array<vmValue> args) { + GB_PANIC("TODO(bill): vm_ext"); + vmValue v = {}; + return v; +} + +vmValue vm_call(vmInterpreter *i, vmFrame *caller, ssaProcedure *proc, Array<vmValue> args) { + if (proc == NULL) { + GB_PANIC("Call to NULL procedure"); + } + + gb_printf("Call: %.*s", LIT(proc->name)); + + vmFrame f = {}; + f.i = i; + f.caller = caller; + f.proc = proc; + if (proc->body == NULL) { + return vm_ext(&f, args); + } + f.block = proc->blocks[0]; + + map_init_with_reserve(&f.env, i->heap_allocator, 1.5*proc->instr_count); + defer (map_destroy(&f.env)); + + array_init_count(&f.locals, i->heap_allocator, proc->local_count); + defer (array_free(&f.locals)); + + for_array(i, proc->params) { + map_set(&f.env, hash_pointer(proc->params[i]), args[i]); + } + + while (f.block != NULL) { + vm_run_frame(&f); + } + + return f.result; +} + +i32 vm_interpret(ssaModule *m) { + i32 exit_code = 2; + + vmInterpreter i = {}; + + i.module = m; + i.sizes = m->sizes; + + gb_arena_init_from_allocator(&i.stack_arena, heap_allocator(), gb_megabytes(64)); + defer (gb_arena_free(&i.stack_arena)); + + i.stack_allocator = gb_arena_allocator(&i.stack_arena); + i.heap_allocator = heap_allocator(); + + ssaProcedure *main_proc = vm_lookup_proc(&i, make_string("main")); + if (main_proc != NULL) { + vm_call(&i, NULL, main_proc, vm_empty_args); + exit_code = 0; + } else { + gb_printf_err("No main procedure."); + exit_code = 1; + } + + return exit_code; +} + +#endif |