浏览代码

Interpreter - bounds checking

Ginger Bill 9 年之前
父节点
当前提交
fa0eb88b7b
共有 3 个文件被更改,包括 72 次插入14 次删除
  1. 3 1
      build.bat
  2. 3 5
      src/main.cpp
  3. 66 8
      src/vm/vm.cpp

+ 3 - 1
build.bat

@@ -24,7 +24,9 @@ set compiler_warnings= ^
 	-wd4505 -wd4512 -wd4550
 	-wd4505 -wd4512 -wd4550
 
 
 set compiler_includes=
 set compiler_includes=
-set libs= kernel32.lib
+set libs= ^
+	kernel32.lib ^
+	"src\dyncall\lib\*.lib"
 
 
 set linker_flags= -incremental:no -opt:ref -subsystem:console
 set linker_flags= -incremental:no -opt:ref -subsystem:console
 
 

+ 3 - 5
src/main.cpp

@@ -166,19 +166,17 @@ int main(int argc, char **argv) {
 
 
 	ssa_gen_tree(&ssa);
 	ssa_gen_tree(&ssa);
 
 
+#if 1
 	{
 	{
 		VirtualMachine vm = {};
 		VirtualMachine vm = {};
 		vm_init(&vm, &ssa.module);
 		vm_init(&vm, &ssa.module);
 		defer (vm_destroy(&vm));
 		defer (vm_destroy(&vm));
 
 
-		String name = make_string("main");
-		ssaValue *main_proc_value = *map_get(&vm.module->members, hash_string(name));
-		GB_ASSERT(main_proc_value->kind == ssaValue_Proc);
-
-		ssaProcedure *start_proc = &main_proc_value->Proc;
+		ssaProcedure *start_proc = vm_lookup_procedure(&vm, make_string("main"));
 		Array<vmValue> args = {}; // Empty
 		Array<vmValue> args = {}; // Empty
 		vm_call_procedure(&vm, start_proc, args);
 		vm_call_procedure(&vm, start_proc, args);
 	}
 	}
+#endif
 
 
 	{
 	{
 		ssaFileBuffer buf = {};
 		ssaFileBuffer buf = {};

+ 66 - 8
src/vm/vm.cpp

@@ -566,6 +566,12 @@ vmValue vm_load(VirtualMachine *vm, void *ptr, Type *type) {
 	return result;
 	return result;
 }
 }
 
 
+ssaProcedure *vm_lookup_procedure(VirtualMachine *vm, String name) {
+	ssaValue *v = ssa_lookup_member(vm->module, name);
+	GB_ASSERT(v->kind == ssaValue_Proc);
+	ssaProcedure *proc = &v->Proc;
+	return proc;
+}
 
 
 void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
 void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
 	GB_ASSERT(value->kind == ssaValue_Instr);
 	GB_ASSERT(value->kind == ssaValue_Instr);
@@ -581,9 +587,7 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
 	switch (instr->kind) {
 	switch (instr->kind) {
 	case ssaInstr_StartupRuntime: {
 	case ssaInstr_StartupRuntime: {
 #if 0
 #if 0
-		ssaValue *v = ssa_lookup_member(vm->module, make_string(SSA_STARTUP_RUNTIME_PROC_NAME));
-		GB_ASSERT(v->kind == ssaValue_Proc);
-		ssaProcedure *proc = &v->Proc;
+		ssaProcedure *proc = vm_lookup_procedure(vm, make_string(SSA_STARTUP_RUNTIME_PROC_NAME));
 		Array<vmValue> args = {}; // Empty
 		Array<vmValue> args = {}; // Empty
 		vm_call_procedure(vm, proc, args); // NOTE(bill): No return value
 		vm_call_procedure(vm, proc, args); // NOTE(bill): No return value
 #endif
 #endif
@@ -639,8 +643,8 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
 		i32 elem_index  = instr->StructElementPtr.elem_index;
 		i32 elem_index  = instr->StructElementPtr.elem_index;
 
 
 		Type *t = ssa_type(instr->StructElementPtr.address);
 		Type *t = ssa_type(instr->StructElementPtr.address);
-		i64 offset_in_bytes = vm_type_offset_of(vm, type_deref(t), elem_index);
-		void *ptr = cast(u8 *)address.val_ptr + offset_in_bytes;
+		i64 offset = vm_type_offset_of(vm, type_deref(t), elem_index);
+		void *ptr = cast(u8 *)address.val_ptr + offset;
 		vm_set_value(f, value, vm_make_value_ptr(ptr));
 		vm_set_value(f, value, vm_make_value_ptr(ptr));
 	} break;
 	} break;
 
 
@@ -788,7 +792,16 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
 		}
 		}
 
 
 		if (gb_is_between(bo->op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
 		if (gb_is_between(bo->op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
-			GB_PANIC("TODO(bill): Comparison operations");
+			switch (bo->op) {
+			case Token_CmpEq: break;
+			case Token_NotEq: break;
+			case Token_Lt:    break;
+			case Token_Gt:    break;
+			case Token_LtEq:  break;
+			case Token_GtEq:  break;
+			}
+			gb_printf_err("TODO(bill): Comparison operations %.*s\n", LIT(token_strings[bo->op]));
+			vm_set_value(f, value, vm_make_value_int(1)); // HACK(bill): always true
 		} else {
 		} else {
 			vmValue v = {};
 			vmValue v = {};
 			vmValue l = vm_operand_value(vm, bo->left);
 			vmValue l = vm_operand_value(vm, bo->left);
@@ -808,12 +821,31 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
 
 
 				case Token_AndNot: v.val_int = l.val_int & (~r.val_int); break;
 				case Token_AndNot: v.val_int = l.val_int & (~r.val_int); break;
 
 
+				// TODO(bill): Take into account size of integer and signedness
 				case Token_Quo: GB_PANIC("TODO(bill): BinaryOp Integer Token_Quo"); break;
 				case Token_Quo: GB_PANIC("TODO(bill): BinaryOp Integer Token_Quo"); break;
 				case Token_Mod: GB_PANIC("TODO(bill): BinaryOp Integer Token_Mod"); break;
 				case Token_Mod: GB_PANIC("TODO(bill): BinaryOp Integer Token_Mod"); break;
 
 
 				}
 				}
 			} else if (is_type_float(t)) {
 			} else if (is_type_float(t)) {
-				GB_PANIC("TODO(bill): Float BinaryOp");
+				if (t == t_f32) {
+					switch (bo->op) {
+					case Token_Add: v.val_f32 = l.val_f32 + r.val_f32;  break;
+					case Token_Sub: v.val_f32 = l.val_f32 - r.val_f32;  break;
+					case Token_Mul: v.val_f32 = l.val_f32 * r.val_f32;  break;
+					case Token_Quo: v.val_f32 = l.val_f32 / r.val_f32;  break;
+
+					case Token_Mod: GB_PANIC("TODO(bill): BinaryOp f32 Token_Mod"); break;
+					}
+				} else if (t == t_f64) {
+					switch (bo->op) {
+					case Token_Add: v.val_f64 = l.val_f64 + r.val_f64;  break;
+					case Token_Sub: v.val_f64 = l.val_f64 - r.val_f64;  break;
+					case Token_Mul: v.val_f64 = l.val_f64 * r.val_f64;  break;
+					case Token_Quo: v.val_f64 = l.val_f64 / r.val_f64;  break;
+
+					case Token_Mod: GB_PANIC("TODO(bill): BinaryOp f64 Token_Mod"); break;
+					}
+				}
 			} else {
 			} else {
 				GB_PANIC("TODO(bill): Vector BinaryOp");
 				GB_PANIC("TODO(bill): Vector BinaryOp");
 			}
 			}
@@ -863,14 +895,40 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
 	} break;
 	} break;
 
 
 	case ssaInstr_BoundsCheck: {
 	case ssaInstr_BoundsCheck: {
+		auto *bc = &instr->BoundsCheck;
+		Array<vmValue> args = {};
+		array_init(&args, vm->stack_allocator, 5);
+		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_string(bc->pos.file), t_string));
+		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.line), t_int));
+		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.column), t_int));
+		array_add(&args, vm_operand_value(vm, bc->index));
+		array_add(&args, vm_operand_value(vm, bc->len));
 
 
+		ssaProcedure *proc = vm_lookup_procedure(vm, make_string("__bounds_check_error"));
+		vm_call_procedure(vm, proc, args);
 	} break;
 	} break;
 
 
 	case ssaInstr_SliceBoundsCheck: {
 	case ssaInstr_SliceBoundsCheck: {
+		auto *bc = &instr->SliceBoundsCheck;
+		Array<vmValue> args = {};
+		ssaProcedure *proc;
+
+		array_init(&args, vm->stack_allocator, 7);
+		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_string(bc->pos.file), t_string));
+		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.line), t_int));
+		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.column), t_int));
+		array_add(&args, vm_operand_value(vm, bc->low));
+		array_add(&args, vm_operand_value(vm, bc->high));
+		if (!bc->is_substring) {
+			array_add(&args, vm_operand_value(vm, bc->max));
+			proc = vm_lookup_procedure(vm, make_string("__slice_expr_error"));
+		} else {
+			proc = vm_lookup_procedure(vm, make_string("__substring_expr_error"));
+		}
 
 
+		vm_call_procedure(vm, proc, args);
 	} break;
 	} break;
 
 
-
 	default: {
 	default: {
 		GB_PANIC("<unknown instr> %d\n", instr->kind);
 		GB_PANIC("<unknown instr> %d\n", instr->kind);
 	} break;
 	} break;