Browse Source

Improve vector math; Make bprint* return string

Ginger Bill 8 years ago
parent
commit
04f5fff7fa
7 changed files with 135 additions and 45 deletions
  1. 1 1
      build.bat
  2. 9 9
      core/fmt.odin
  3. 9 9
      core/math.odin
  4. 96 5
      src/check_expr.c
  5. 13 5
      src/ir.c
  6. 1 10
      src/ir_print.c
  7. 6 6
      src/types.c

+ 1 - 1
build.bat

@@ -4,7 +4,7 @@
 set exe_name=odin.exe
 set exe_name=odin.exe
 
 
 :: Debug = 0, Release = 1
 :: Debug = 0, Release = 1
-set release_mode=1
+set release_mode=0
 set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
 set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
 
 
 if %release_mode% EQU 0 ( rem Debug
 if %release_mode% EQU 0 ( rem Debug

+ 9 - 9
core/fmt.odin

@@ -151,15 +151,15 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
 
 
 // aprint* procedure return a string that was allocated with the current context
 // aprint* procedure return a string that was allocated with the current context
 // They must be freed accordingly
 // They must be freed accordingly
-bprint :: proc(buf: []byte, args: ..any) -> int {
+bprint :: proc(buf: []byte, args: ..any) -> string {
 	sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
 	sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
 	return sbprint(&sb, ..args);
 	return sbprint(&sb, ..args);
 }
 }
-bprintln :: proc(buf: []byte, args: ..any) -> int {
+bprintln :: proc(buf: []byte, args: ..any) -> string {
 	sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
 	sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
 	return sbprintln(&sb, ..args);
 	return sbprintln(&sb, ..args);
 }
 }
-bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> int {
+bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string {
 	sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
 	sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
 	return sbprintf(&sb, fmt, ..args);
 	return sbprintf(&sb, fmt, ..args);
 }
 }
@@ -1047,7 +1047,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
 
 
 
 
 
 
-sbprint :: proc(buf: ^String_Buffer, args: ..any) -> int {
+sbprint :: proc(buf: ^String_Buffer, args: ..any) -> string {
 	fi: Fmt_Info;
 	fi: Fmt_Info;
 	fi.buf = buf;
 	fi.buf = buf;
 
 
@@ -1060,10 +1060,10 @@ sbprint :: proc(buf: ^String_Buffer, args: ..any) -> int {
 		fmt_value(&fi, args[i], 'v');
 		fmt_value(&fi, args[i], 'v');
 		prev_string = is_string;
 		prev_string = is_string;
 	}
 	}
-	return len(string_buffer_data(buf));
+	return to_string(buf^);
 }
 }
 
 
-sbprintln :: proc(buf: ^String_Buffer, args: ..any) -> int {
+sbprintln :: proc(buf: ^String_Buffer, args: ..any) -> string {
 	fi: Fmt_Info;
 	fi: Fmt_Info;
 	fi.buf = buf;
 	fi.buf = buf;
 
 
@@ -1074,10 +1074,10 @@ sbprintln :: proc(buf: ^String_Buffer, args: ..any) -> int {
 		fmt_value(&fi, args[i], 'v');
 		fmt_value(&fi, args[i], 'v');
 	}
 	}
 	write_byte(buf, '\n');
 	write_byte(buf, '\n');
-	return len(string_buffer_data(buf));
+	return to_string(buf^);
 }
 }
 
 
-sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> int {
+sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> string {
 	fi := Fmt_Info{};
 	fi := Fmt_Info{};
 	end := len(fmt);
 	end := len(fmt);
 	arg_index := 0;
 	arg_index := 0;
@@ -1207,5 +1207,5 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> int {
 		write_string(b, ")");
 		write_string(b, ")");
 	}
 	}
 
 
-	return len(string_buffer_data(b));
+	return to_string(b^);
 }
 }

+ 9 - 9
core/math.odin

@@ -120,32 +120,32 @@ mag :: proc(v: Vec2) -> f32 { return sqrt(dot(v, v)); }
 mag :: proc(v: Vec3) -> f32 { return sqrt(dot(v, v)); }
 mag :: proc(v: Vec3) -> f32 { return sqrt(dot(v, v)); }
 mag :: proc(v: Vec4) -> f32 { return sqrt(dot(v, v)); }
 mag :: proc(v: Vec4) -> f32 { return sqrt(dot(v, v)); }
 
 
-norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{mag(v)}; }
-norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{mag(v)}; }
-norm :: proc(v: Vec4) -> Vec4 { return v / Vec4{mag(v)}; }
+norm :: proc(v: Vec2) -> Vec2 { return v / mag(v); }
+norm :: proc(v: Vec3) -> Vec3 { return v / mag(v); }
+norm :: proc(v: Vec4) -> Vec4 { return v / mag(v); }
 
 
 norm0 :: proc(v: Vec2) -> Vec2 {
 norm0 :: proc(v: Vec2) -> Vec2 {
 	m := mag(v);
 	m := mag(v);
 	if m == 0 {
 	if m == 0 {
-		return Vec2{0};
+		return 0;
 	}
 	}
-	return v / Vec2{m};
+	return v / m;
 }
 }
 
 
 norm0 :: proc(v: Vec3) -> Vec3 {
 norm0 :: proc(v: Vec3) -> Vec3 {
 	m := mag(v);
 	m := mag(v);
 	if m == 0 {
 	if m == 0 {
-		return Vec3{0};
+		return 0;
 	}
 	}
-	return v / Vec3{m};
+	return v / m;
 }
 }
 
 
 norm0 :: proc(v: Vec4) -> Vec4 {
 norm0 :: proc(v: Vec4) -> Vec4 {
 	m := mag(v);
 	m := mag(v);
 	if m == 0 {
 	if m == 0 {
-		return Vec4{0};
+		return 0;
 	}
 	}
-	return v / Vec4{m};
+	return v / m;
 }
 }
 
 
 
 

+ 96 - 5
src/check_expr.c

@@ -233,6 +233,14 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
 		}
 		}
 	}
 	}
 
 
+	if (is_type_vector(dst)) {
+		Type *elem = base_vector_type(dst);
+		i64 distance = check_distance_between_types(c, operand, elem);
+		if (distance >= 0) {
+			return distance + 5;
+		}
+	}
+
 
 
 	if (is_type_any(dst)) {
 	if (is_type_any(dst)) {
 		// NOTE(bill): Anything can cast to `Any`
 		// NOTE(bill): Anything can cast to `Any`
@@ -288,9 +296,13 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
 			add_type_info_type(c, target_type);
 			add_type_info_type(c, target_type);
 		}
 		}
 
 
-		convert_to_typed(c, operand, target_type, 0);
-		if (operand->mode == Addressing_Invalid) {
-			return;
+		if (target_type != NULL && is_type_vector(target_type)) {
+			// NOTE(bill): continue to below
+		} else {
+			convert_to_typed(c, operand, target_type, 0);
+			if (operand->mode == Addressing_Invalid) {
+				return;
+			}
 		}
 		}
 	}
 	}
 
 
@@ -1096,6 +1108,33 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
 			}
 			}
 		} break;
 		} break;
 		}
 		}
+	} else if (str_eq(build_context.ODIN_OS, str_lit("linux"))) {
+		Type *bt = core_type(original_type);
+		switch (bt->kind) {
+		// Okay to pass by value
+		// Especially the only Odin types
+		case Type_Basic:   break;
+		case Type_Pointer: break;
+		case Type_Proc:    break; // NOTE(bill): Just a pointer
+
+		// Odin only types
+		case Type_Slice:
+		case Type_DynamicArray:
+		case Type_Map:
+			break;
+
+		// Odin specific
+		case Type_Array:
+		case Type_Vector:
+		// Could be in C too
+		case Type_Record: {
+			i64 align = type_align_of(a, original_type);
+			i64 size  = type_size_of(a, original_type);
+			if (8*size > 16) {
+				new_type = make_type_pointer(a, original_type);
+			}
+		} break;
+		}
 	} else {
 	} else {
 		// IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for
 		// IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for
 		// their architectures
 		// their architectures
@@ -2453,6 +2492,8 @@ void check_cast(Checker *c, Operand *x, Type *type) {
 			x->mode = Addressing_Value;
 			x->mode = Addressing_Value;
 		} else if (is_type_slice(type) && is_type_string(x->type)) {
 		} else if (is_type_slice(type) && is_type_string(x->type)) {
 			x->mode = Addressing_Value;
 			x->mode = Addressing_Value;
+		} else if (!is_type_vector(x->type) && is_type_vector(type)) {
+			x->mode = Addressing_Value;
 		}
 		}
 		can_convert = true;
 		can_convert = true;
 	}
 	}
@@ -2481,6 +2522,16 @@ void check_cast(Checker *c, Operand *x, Type *type) {
 	x->type = type;
 	x->type = type;
 }
 }
 
 
+bool check_binary_vector_expr(Checker *c, Token op, Operand *x, Operand *y) {
+	if (is_type_vector(x->type) && !is_type_vector(y->type)) {
+		if (check_is_assignable_to(c, y, x->type)) {
+			if (check_binary_op(c, x, op)) {
+				return true;
+			}
+		}
+	}
+	return false;
+}
 
 
 
 
 void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
 void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
@@ -2560,6 +2611,17 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
 		return;
 		return;
 	}
 	}
 
 
+
+	if (check_binary_vector_expr(c, op, x, y)) {
+		x->mode = Addressing_Value;
+		x->type = x->type;
+		return;
+	}
+	if (check_binary_vector_expr(c, op, y, x)) {
+		x->mode = Addressing_Value;
+		x->type = y->type;
+		return;
+	}
 	if (!are_types_identical(x->type, y->type)) {
 	if (!are_types_identical(x->type, y->type)) {
 		if (x->type != t_invalid &&
 		if (x->type != t_invalid &&
 		    y->type != t_invalid) {
 		    y->type != t_invalid) {
@@ -2737,6 +2799,24 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) {
 	operand->mode = Addressing_Invalid;
 	operand->mode = Addressing_Invalid;
 }
 }
 
 
+ExactValue convert_exact_value_for_type(ExactValue v, Type *type) {
+	Type *t = core_type(type);
+	if (is_type_boolean(t)) {
+		// v = exact_value_to_boolean(v);
+	} else if (is_type_float(t)) {
+		v = exact_value_to_float(v);
+	} else if (is_type_integer(t)) {
+		v = exact_value_to_integer(v);
+	} else if (is_type_pointer(t)) {
+		v = exact_value_to_integer(v);
+	} else if (is_type_complex(t)) {
+		v = exact_value_to_complex(v);
+	} else if (is_type_quaternion(t)) {
+		v = exact_value_to_quaternion(v);
+	}
+	return v;
+}
+
 // NOTE(bill): Set initial level to 0
 // NOTE(bill): Set initial level to 0
 void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level) {
 void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level) {
 	GB_ASSERT_NOT_NULL(target_type);
 	GB_ASSERT_NOT_NULL(target_type);
@@ -2747,7 +2827,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
 		return;
 		return;
 	}
 	}
 
 
-
 	if (is_type_untyped(target_type)) {
 	if (is_type_untyped(target_type)) {
 		GB_ASSERT(operand->type->kind == Type_Basic);
 		GB_ASSERT(operand->type->kind == Type_Basic);
 		GB_ASSERT(target_type->kind == Type_Basic);
 		GB_ASSERT(target_type->kind == Type_Basic);
@@ -2809,6 +2888,18 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
 		}
 		}
 		break;
 		break;
 
 
+	case Type_Vector: {
+		Type *elem = base_vector_type(t);
+		if (check_is_assignable_to(c, operand, elem)) {
+			operand->mode = Addressing_Value;
+		} else {
+			operand->mode = Addressing_Invalid;
+			convert_untyped_error(c, operand, target_type);
+			return;
+		}
+	} break;
+
+
 	default:
 	default:
 		if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
 		if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
 			operand->mode = Addressing_Invalid;
 			operand->mode = Addressing_Invalid;
@@ -5361,7 +5452,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 			isize index = 0;
 			isize index = 0;
 			isize elem_count = cl->elems.count;
 			isize elem_count = cl->elems.count;
 
 
-			if (base_type(elem_type) == t_any) {
+			if (is_type_any(base_type(elem_type))) {
 				is_constant = false;
 				is_constant = false;
 			}
 			}
 
 

+ 13 - 5
src/ir.c

@@ -1450,13 +1450,12 @@ irValue *ir_emit_comment(irProcedure *p, String text) {
 	return ir_emit(p, ir_instr_comment(p, text));
 	return ir_emit(p, ir_instr_comment(p, text));
 }
 }
 
 
-irValue *ir_copy_value_to_ptr(irProcedure *proc, irValue *val, i64 alignment) {
-	Type *t = ir_type(val);
-	i64 type_alignment = type_align_of(proc->module->allocator, t);
+irValue *ir_copy_value_to_ptr(irProcedure *proc, irValue *val, Type *new_type, i64 alignment) {
+	i64 type_alignment = type_align_of(proc->module->allocator, new_type);
 	if (alignment < type_alignment) {
 	if (alignment < type_alignment) {
 		alignment = type_alignment;
 		alignment = type_alignment;
 	}
 	}
-	irValue *ptr = ir_add_local_generated(proc, t);
+	irValue *ptr = ir_add_local_generated(proc, new_type);
 	ptr->Instr.Local.alignment = alignment;
 	ptr->Instr.Local.alignment = alignment;
 	ir_emit_store(proc, ptr, val);
 	ir_emit_store(proc, ptr, val);
 	return ptr;
 	return ptr;
@@ -1480,7 +1479,7 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, irValue **args, isize arg_
 		Type *new_type = pt->Proc.abi_compat_params[i];
 		Type *new_type = pt->Proc.abi_compat_params[i];
 		if (original_type != new_type) {
 		if (original_type != new_type) {
 			if (is_type_pointer(new_type)) {
 			if (is_type_pointer(new_type)) {
-				args[i] = ir_copy_value_to_ptr(p, args[i], 16);
+				args[i] = ir_copy_value_to_ptr(p, args[i], original_type, 16);
 			} else if (is_type_integer(new_type)) {
 			} else if (is_type_integer(new_type)) {
 				args[i] = ir_emit_transmute(p, args[i], new_type);
 				args[i] = ir_emit_transmute(p, args[i], new_type);
 			}
 			}
@@ -3546,6 +3545,15 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 	GB_ASSERT_NOT_NULL(tv);
 	GB_ASSERT_NOT_NULL(tv);
 
 
 	if (tv->value.kind != ExactValue_Invalid) {
 	if (tv->value.kind != ExactValue_Invalid) {
+		// NOTE(bill): Edge case
+		if (tv->value.kind != ExactValue_Compound &&
+		    is_type_vector(tv->type)) {
+			Type *elem = base_vector_type(tv->type);
+			ExactValue value = convert_exact_value_for_type(tv->value, elem);
+			irValue *x = ir_add_module_constant(proc->module, elem, value);
+			return ir_emit_conv(proc, x, tv->type);
+		}
+
 		return ir_add_module_constant(proc->module, tv->type, tv->value);
 		return ir_add_module_constant(proc->module, tv->type, tv->value);
 	}
 	}
 
 

+ 1 - 10
src/ir_print.c

@@ -354,13 +354,7 @@ void ir_print_compound_element(irFileBuffer *f, irModule *m, ExactValue v, Type
 
 
 void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) {
 void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) {
 	type = core_type(type);
 	type = core_type(type);
-	if (is_type_float(type)) {
-		value = exact_value_to_float(value);
-	} else if (is_type_integer(type)) {
-		value = exact_value_to_integer(value);
-	} else if (is_type_pointer(type)) {
-		value = exact_value_to_integer(value);
-	}
+	value = convert_exact_value_for_type(value, type);
 
 
 	switch (value.kind) {
 	switch (value.kind) {
 	case ExactValue_Bool:
 	case ExactValue_Bool:
@@ -1076,9 +1070,6 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		Type *type = base_type(ir_type(bo->left));
 		Type *type = base_type(ir_type(bo->left));
 		Type *elem_type = type;
 		Type *elem_type = type;
 		GB_ASSERT(!is_type_vector(elem_type));
 		GB_ASSERT(!is_type_vector(elem_type));
-		while (elem_type->kind == Type_Vector) {
-			elem_type = base_type(elem_type->Vector.elem);
-		}
 
 
 		ir_fprintf(f, "%%%d = ", value->index);
 		ir_fprintf(f, "%%%d = ", value->index);
 
 

+ 6 - 6
src/types.c

@@ -1437,16 +1437,16 @@ void type_path_free(TypePath *tp) {
 TypePath *type_path_push(TypePath *tp, Type *t) {
 TypePath *type_path_push(TypePath *tp, Type *t) {
 	GB_ASSERT(tp != NULL);
 	GB_ASSERT(tp != NULL);
 
 
-	for (isize i = 0; i < tp->path.count; i++) {
+	for (isize i = 1; i < tp->path.count; i++) {
 		if (tp->path.e[i] == t) {
 		if (tp->path.e[i] == t) {
 			// TODO(bill):
 			// TODO(bill):
-			GB_ASSERT(is_type_named(t));
+			GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t));
 			Entity *e = t->Named.type_name;
 			Entity *e = t->Named.type_name;
 			error(e->token, "Illegal declaration cycle of `%.*s`", LIT(t->Named.name));
 			error(e->token, "Illegal declaration cycle of `%.*s`", LIT(t->Named.name));
 			// NOTE(bill): Print cycle, if it's deep enough
 			// NOTE(bill): Print cycle, if it's deep enough
-			for (isize j = 0; j < tp->path.count; j++) {
+			for (isize j = i; j < tp->path.count; j++) {
 				Type *t = tp->path.e[j];
 				Type *t = tp->path.e[j];
-				GB_ASSERT(is_type_named(t));
+				GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t));
 				Entity *e = t->Named.type_name;
 				Entity *e = t->Named.type_name;
 				error(e->token, "\t%.*s refers to", LIT(t->Named.name));
 				error(e->token, "\t%.*s refers to", LIT(t->Named.name));
 			}
 			}
@@ -1461,14 +1461,14 @@ TypePath *type_path_push(TypePath *tp, Type *t) {
 		}
 		}
 	}
 	}
 
 
-	if (!tp->failure) {
+	if (!tp->failure && is_type_named(t)) {
 		array_add(&tp->path, t);
 		array_add(&tp->path, t);
 	}
 	}
 	return tp;
 	return tp;
 }
 }
 
 
 void type_path_pop(TypePath *tp) {
 void type_path_pop(TypePath *tp) {
-	if (tp != NULL) {
+	if (tp != NULL && tp->path.count > 0) {
 		array_pop(&tp->path);
 		array_pop(&tp->path);
 	}
 	}
 }
 }