Răsfoiți Sursa

Merge branch 'master' into windows-llvm-13.0.0

gingerBill 2 ani în urmă
părinte
comite
5bd1358ce9

+ 82 - 16
core/math/math_basic.odin

@@ -3,44 +3,110 @@ package math
 
 import "core:intrinsics"
 
-@(default_calling_convention="none")
+@(default_calling_convention="none", private="file")
 foreign _ {
 	@(link_name="llvm.sin.f16", require_results)
-	sin_f16 :: proc(θ: f16) -> f16 ---
+	_sin_f16 :: proc(θ: f16) -> f16 ---
 	@(link_name="llvm.sin.f32", require_results)
-	sin_f32 :: proc(θ: f32) -> f32 ---
+	_sin_f32 :: proc(θ: f32) -> f32 ---
 	@(link_name="llvm.sin.f64", require_results)
-	sin_f64 :: proc(θ: f64) -> f64 ---
+	_sin_f64 :: proc(θ: f64) -> f64 ---
 
 	@(link_name="llvm.cos.f16", require_results)
-	cos_f16 :: proc(θ: f16) -> f16 ---
+	_cos_f16 :: proc(θ: f16) -> f16 ---
 	@(link_name="llvm.cos.f32", require_results)
-	cos_f32 :: proc(θ: f32) -> f32 ---
+	_cos_f32 :: proc(θ: f32) -> f32 ---
 	@(link_name="llvm.cos.f64", require_results)
-	cos_f64 :: proc(θ: f64) -> f64 ---
+	_cos_f64 :: proc(θ: f64) -> f64 ---
 
 	@(link_name="llvm.pow.f16", require_results)
-	pow_f16 :: proc(x, power: f16) -> f16 ---
+	_pow_f16 :: proc(x, power: f16) -> f16 ---
 	@(link_name="llvm.pow.f32", require_results)
-	pow_f32 :: proc(x, power: f32) -> f32 ---
+	_pow_f32 :: proc(x, power: f32) -> f32 ---
 	@(link_name="llvm.pow.f64", require_results)
-	pow_f64 :: proc(x, power: f64) -> f64 ---
+	_pow_f64 :: proc(x, power: f64) -> f64 ---
 
 	@(link_name="llvm.fmuladd.f16", require_results)
-	fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---
+	_fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---
 	@(link_name="llvm.fmuladd.f32", require_results)
-	fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---
+	_fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---
 	@(link_name="llvm.fmuladd.f64", require_results)
-	fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
+	_fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
 
 	@(link_name="llvm.exp.f16", require_results)
-	exp_f16 :: proc(x: f16) -> f16 ---
+	_exp_f16 :: proc(x: f16) -> f16 ---
 	@(link_name="llvm.exp.f32", require_results)
-	exp_f32 :: proc(x: f32) -> f32 ---
+	_exp_f32 :: proc(x: f32) -> f32 ---
 	@(link_name="llvm.exp.f64", require_results)
-	exp_f64 :: proc(x: f64) -> f64 ---
+	_exp_f64 :: proc(x: f64) -> f64 ---
 }
 
+@(require_results)
+sin_f16 :: proc "contextless" (θ: f16) -> f16 {
+	return _sin_f16(θ)
+}
+@(require_results)
+sin_f32 :: proc "contextless" (θ: f32) -> f32 {
+	return _sin_f32(θ)
+}
+@(require_results)
+sin_f64 :: proc "contextless" (θ: f64) -> f64 {
+	return _sin_f64(θ)
+}
+
+@(require_results)
+cos_f16 :: proc "contextless" (θ: f16) -> f16 {
+	return _cos_f16(θ)
+}
+@(require_results)
+cos_f32 :: proc "contextless" (θ: f32) -> f32 {
+	return _cos_f32(θ)
+}
+@(require_results)
+cos_f64 :: proc "contextless" (θ: f64) -> f64 {
+	return _cos_f64(θ)
+}
+
+@(require_results)
+pow_f16 :: proc "contextless" (x, power: f16) -> f16 {
+	return _pow_f16(x, power)
+}
+@(require_results)
+pow_f32 :: proc "contextless" (x, power: f32) -> f32 {
+	return _pow_f32(x, power)
+}
+@(require_results)
+pow_f64 :: proc "contextless" (x, power: f64) -> f64 {
+	return _pow_f64(x, power)
+}
+
+@(require_results)
+fmuladd_f16 :: proc "contextless" (a, b, c: f16) -> f16 {
+	return _fmuladd_f16(a, b, c)
+}
+@(require_results)
+fmuladd_f32 :: proc "contextless" (a, b, c: f32) -> f32 {
+	return _fmuladd_f32(a, b, c)
+}
+@(require_results)
+fmuladd_f64 :: proc "contextless" (a, b, c: f64) -> f64 {
+	return _fmuladd_f64(a, b, c)
+}
+
+@(require_results)
+exp_f16 :: proc "contextless" (x: f16) -> f16 {
+	return _exp_f16(x)
+}
+@(require_results)
+exp_f32 :: proc "contextless" (x: f32) -> f32 {
+	return _exp_f32(x)
+}
+@(require_results)
+exp_f64 :: proc "contextless" (x: f64) -> f64 {
+	return _exp_f64(x)
+}
+
+
 @(require_results)
 sqrt_f16 :: proc "contextless" (x: f16) -> f16 {
 	return intrinsics.sqrt(x)

+ 27 - 10
src/check_expr.cpp

@@ -664,6 +664,11 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
 				if (check_representable_as_constant(c, operand->value, dst, nullptr)) {
 					if (is_type_typed(dst) && src->kind == Type_Basic) {
 						switch (src->Basic.kind) {
+						case Basic_UntypedBool:
+							if (is_type_boolean(dst)) {
+								return 1;
+							}
+							break;
 						case Basic_UntypedRune:
 							if (is_type_integer(dst) || is_type_rune(dst)) {
 								return 1;
@@ -704,46 +709,55 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
 				return -1;
 			}
 			if (src->kind == Type_Basic) {
+				Type *d = base_array_type(dst);
 				i64 score = -1;
 				switch (src->Basic.kind) {
+				case Basic_UntypedBool:
+					if (is_type_boolean(d)) {
+						score = 1;
+					}
+					break;
 				case Basic_UntypedRune:
-					if (is_type_integer(dst) || is_type_rune(dst)) {
+					if (is_type_integer(d) || is_type_rune(d)) {
 						score = 1;
 					}
 					break;
 				case Basic_UntypedInteger:
-					if (is_type_integer(dst) || is_type_rune(dst)) {
+					if (is_type_integer(d) || is_type_rune(d)) {
 						score = 1;
 					}
 					break;
 				case Basic_UntypedString:
-					if (is_type_string(dst)) {
+					if (is_type_string(d)) {
 						score = 1;
 					}
 					break;
 				case Basic_UntypedFloat:
-					if (is_type_float(dst)) {
+					if (is_type_float(d)) {
 						score = 1;
 					}
 					break;
 				case Basic_UntypedComplex:
-					if (is_type_complex(dst)) {
+					if (is_type_complex(d)) {
 						score = 1;
 					}
-					if (is_type_quaternion(dst)) {
+					if (is_type_quaternion(d)) {
 						score = 2;
 					}
 					break;
 				case Basic_UntypedQuaternion:
-					if (is_type_quaternion(dst)) {
+					if (is_type_quaternion(d)) {
 						score = 1;
 					}
 					break;
 				}
 				if (score > 0) {
-					if (is_type_typed(dst)) {
+					if (is_type_typed(d)) {
 						score += 1;
 					}
+					if (d != dst) {
+						score += 6;
+					}
 				}
 				return score;
 			}
@@ -1705,7 +1719,7 @@ gb_internal bool check_unary_op(CheckerContext *c, Operand *o, Token op) {
 		break;
 
 	case Token_Not:
-		if (!is_type_boolean(type)) {
+		if (!is_type_boolean(type) || is_type_array_like(o->type)) {
 			ERROR_BLOCK();
 			str = expr_to_string(o->expr);
 			error(op, "Operator '%.*s' is only allowed on boolean expressions", LIT(op.string));
@@ -4760,7 +4774,10 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
 
 	if (entity == nullptr && selector->kind == Ast_Ident) {
 		String field_name = selector->Ident.token.string;
-		if (is_type_dynamic_array(type_deref(operand->type))) {
+		Type *t = type_deref(operand->type);
+		if (t == nullptr) {
+			error(operand->expr, "Cannot use a selector expression on 0-value expression");
+		} else if (is_type_dynamic_array(t)) {
 			init_mem_allocator(c->checker);
 		}
 		sel = lookup_field(operand->type, field_name, operand->mode == Addressing_Type);

+ 0 - 11
src/checker.cpp

@@ -285,17 +285,6 @@ gb_internal Scope *create_scope_from_package(CheckerContext *c, AstPackage *pkg)
 }
 
 gb_internal void destroy_scope(Scope *scope) {
-	for (auto const &entry : scope->elements) {
-		Entity *e = entry.value;
-		if (e->kind == Entity_Variable) {
-			if (!(e->flags & EntityFlag_Used)) {
-#if 0
-				warning(e->token, "Unused variable '%.*s'", LIT(e->token.string));
-#endif
-			}
-		}
-	}
-
 	for (Scope *child = scope->head_child; child != nullptr; child = child->next) {
 		destroy_scope(child);
 	}

+ 2 - 0
src/llvm_backend.hpp

@@ -346,6 +346,8 @@ struct lbProcedure {
 };
 
 
+#define ABI_PKG_NAME_SEPARATOR "."
+
 
 #if !ODIN_LLVM_MINIMUM_VERSION_14
 #define LLVMConstGEP2(Ty__, ConstantVal__, ConstantIndices__, NumIndices__) LLVMConstGEP(ConstantVal__, ConstantIndices__, NumIndices__)

+ 4 - 1
src/llvm_backend_const.cpp

@@ -483,7 +483,10 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
 		GB_ASSERT(res.value != nullptr);
 		GB_ASSERT(LLVMGetValueKind(res.value) == LLVMFunctionValueKind);
 
-		res.value = LLVMConstPointerCast(res.value, lb_type(m, res.type));
+		if (LLVMGetIntrinsicID(res.value) == 0) {
+			// NOTE(bill): do not cast intrinsics as they are not really procedures that can be casted
+			res.value = LLVMConstPointerCast(res.value, lb_type(m, res.type));
+		}
 		return res;
 	}
 

+ 11 - 4
src/llvm_backend_expr.cpp

@@ -1395,13 +1395,17 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
 			return lb_emit_conv(p, cmp, type);
 		} else if (lb_is_empty_string_constant(be->right)) {
 			// `x == ""` or `x != ""`
-			lbValue len = lb_string_len(p, lb_build_expr(p, be->left));
+			lbValue s = lb_build_expr(p, be->left);
+			s = lb_emit_conv(p, s, t_string);
+			lbValue len = lb_string_len(p, s);
 			lbValue cmp = lb_emit_comp(p, be->op.kind, len, lb_const_int(p->module, t_int, 0));
 			Type *type = default_type(tv.type);
 			return lb_emit_conv(p, cmp, type);
 		} else if (lb_is_empty_string_constant(be->left)) {
 			// `"" == x` or `"" != x`
-			lbValue len = lb_string_len(p, lb_build_expr(p, be->right));
+			lbValue s = lb_build_expr(p, be->right);
+			s = lb_emit_conv(p, s, t_string);
+			lbValue len = lb_string_len(p, s);
 			lbValue cmp = lb_emit_comp(p, be->op.kind, len, lb_const_int(p->module, t_int, 0));
 			Type *type = default_type(tv.type);
 			return lb_emit_conv(p, cmp, type);
@@ -2276,7 +2280,10 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
 	GB_ASSERT(gb_is_between(op_kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1));
 
 	lbValue nil_check = {};
-	if (is_type_untyped_nil(left.type)) {
+
+	if (is_type_array_like(left.type) || is_type_array_like(right.type)) {
+		// don't do `nil` check if it is array-like
+	} else if (is_type_untyped_nil(left.type)) {
 		nil_check = lb_emit_comp_against_nil(p, op_kind, right);
 	} else if (is_type_untyped_nil(right.type)) {
 		nil_check = lb_emit_comp_against_nil(p, op_kind, left);
@@ -2332,7 +2339,7 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
 		lbValue res = lb_emit_comp(p, op_kind, val, lb_const_nil(p->module, val.type));
 		return lb_emit_conv(p, res, t_bool);
 	}
-	if (is_type_array(a) || is_type_enumerated_array(a)) {
+	if (is_type_array_like(a)) {
 		Type *tl = base_type(a);
 		lbValue lhs = lb_address_from_load_or_generate_local(p, left);
 		lbValue rhs = lb_address_from_load_or_generate_local(p, right);

+ 6 - 3
src/llvm_backend_general.cpp

@@ -1403,7 +1403,7 @@ gb_internal String lb_mangle_name(lbModule *m, Entity *e) {
 	char *new_name = gb_alloc_array(permanent_allocator(), char, max_len);
 	isize new_name_len = gb_snprintf(
 		new_name, max_len,
-		"%.*s.%.*s", LIT(pkgn), LIT(name)
+		"%.*s" ABI_PKG_NAME_SEPARATOR "%.*s", LIT(pkgn), LIT(name)
 	);
 	if (require_suffix_id) {
 		char *str = new_name + new_name_len-1;
@@ -1453,7 +1453,7 @@ gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedur
 		isize name_len = p->name.len + 1 + ts_name.len + 1 + 10 + 1;
 		char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
 		u32 guid = 1+p->module->nested_type_name_guid.fetch_add(1);
-		name_len = gb_snprintf(name_text, name_len, "%.*s.%.*s-%u", LIT(p->name), LIT(ts_name), guid);
+		name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(p->name), LIT(ts_name), guid);
 
 		String name = make_string(cast(u8 *)name_text, name_len-1);
 		e->TypeName.ir_mangled_name = name;
@@ -1463,7 +1463,7 @@ gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedur
 		isize name_len = 9 + 1 + ts_name.len + 1 + 10 + 1;
 		char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
 		static std::atomic<u32> guid;
-		name_len = gb_snprintf(name_text, name_len, "_internal.%.*s-%u", LIT(ts_name), 1+guid.fetch_add(1));
+		name_len = gb_snprintf(name_text, name_len, "_internal" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(ts_name), 1+guid.fetch_add(1));
 
 		String name = make_string(cast(u8 *)name_text, name_len-1);
 		e->TypeName.ir_mangled_name = name;
@@ -2730,7 +2730,10 @@ gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e)
 	} else {
 		array_add(&m->missing_procedures_to_check, missing_proc);
 	}
+
+	rw_mutex_shared_lock(&m->values_mutex);
 	found = map_get(&m->values, e);
+	rw_mutex_shared_unlock(&m->values_mutex);
 	if (found) {
 		return *found;
 	}

+ 1 - 1
src/llvm_backend_proc.cpp

@@ -757,7 +757,7 @@ gb_internal void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e)
 	char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
 
 	i32 guid = cast(i32)p->children.count;
-	name_len = gb_snprintf(name_text, name_len, "%.*s.%.*s-%d", LIT(p->name), LIT(pd_name), guid);
+	name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%d", LIT(p->name), LIT(pd_name), guid);
 	String name = make_string(cast(u8 *)name_text, name_len-1);
 
 	e->Procedure.link_name = name;

+ 8 - 0
src/llvm_backend_stmt.cpp

@@ -1878,7 +1878,9 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
 	} else if (return_count == 1) {
 		Entity *e = tuple->variables[0];
 		if (res_count == 0) {
+			rw_mutex_shared_lock(&p->module->values_mutex);
 			lbValue found = map_must_get(&p->module->values, e);
+			rw_mutex_shared_unlock(&p->module->values_mutex);
 			res = lb_emit_load(p, found);
 		} else {
 			res = lb_build_expr(p, return_results[0]);
@@ -1887,7 +1889,9 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
 		if (p->type->Proc.has_named_results) {
 			// NOTE(bill): store the named values before returning
 			if (e->token.string != "") {
+				rw_mutex_shared_lock(&p->module->values_mutex);
 				lbValue found = map_must_get(&p->module->values, e);
+				rw_mutex_shared_unlock(&p->module->values_mutex);
 				lb_emit_store(p, found, lb_emit_conv(p, res, e->type));
 			}
 		}
@@ -1903,7 +1907,9 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
 		} else {
 			for (isize res_index = 0; res_index < return_count; res_index++) {
 				Entity *e = tuple->variables[res_index];
+				rw_mutex_shared_lock(&p->module->values_mutex);
 				lbValue found = map_must_get(&p->module->values, e);
+				rw_mutex_shared_unlock(&p->module->values_mutex);
 				lbValue res = lb_emit_load(p, found);
 				array_add(&results, res);
 			}
@@ -1925,7 +1931,9 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
 				if (e->token.string == "") {
 					continue;
 				}
+				rw_mutex_shared_lock(&p->module->values_mutex);
 				named_results[i] = map_must_get(&p->module->values, e);
+				rw_mutex_shared_unlock(&p->module->values_mutex);
 				values[i] = lb_emit_conv(p, results[i], e->type);
 			}