From 3758be55f562cadae17845bfdda1df0431b2a5df Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 7 Jul 2023 22:56:20 +0100 Subject: [PATCH 1/9] Fix #2630 --- src/check_expr.cpp | 30 ++++++++++++++++++++++-------- src/checker.cpp | 11 ----------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7b3ddfc73..77c351cce 100644 --- a/src/check_expr.cpp +++ b/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; } diff --git a/src/checker.cpp b/src/checker.cpp index 354cdadd3..396a04d7a 100644 --- a/src/checker.cpp +++ b/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); } From 759f846b2b56844b3f1a7e04a0adf78fec9379d0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 7 Jul 2023 23:03:46 +0100 Subject: [PATCH 2/9] Fix `[2]union{T}` comparison against `nil` --- src/llvm_backend_expr.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 68ad9e6e0..b250a32e1 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2276,7 +2276,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 +2335,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); From bf848637aa73ed1fd31484cca3802e1cd0c14f93 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 7 Jul 2023 23:06:15 +0100 Subject: [PATCH 3/9] Fix #2629 --- src/llvm_backend_expr.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index b250a32e1..c30170553 100644 --- a/src/llvm_backend_expr.cpp +++ b/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); From ea20b644cc82401c3e6e76c55cb8aac7ed655e56 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 7 Jul 2023 23:07:41 +0100 Subject: [PATCH 4/9] Fix #2624 --- src/check_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 77c351cce..4e39b83bd 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1719,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)); From 6495f2cf989351470b92e6cab3881c7cb85a6a5c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 7 Jul 2023 23:09:46 +0100 Subject: [PATCH 5/9] Fix #2593 --- src/check_expr.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 4e39b83bd..b662c231f 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4774,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); From 17562e476f9b2ab4177fbe301df66b98f588413e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 7 Jul 2023 23:13:37 +0100 Subject: [PATCH 6/9] Remove math usage of raw LLVM intrinsic prototypes --- core/math/math_basic.odin | 98 ++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/core/math/math_basic.odin b/core/math/math_basic.odin index 785c43b10..95e0a93ec 100644 --- a/core/math/math_basic.odin +++ b/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) From aa38889704f3518878aeb82cb03d63c8b592ac0e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 7 Jul 2023 23:23:47 +0100 Subject: [PATCH 7/9] Fix issue with pointer casting internal llvm intrinsics --- src/llvm_backend_const.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index efe1e4d45..2a121ff5d 100644 --- a/src/llvm_backend_const.cpp +++ b/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; } From 62031c24a2afeb9dd15a85e3e15a78860900be6a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 7 Jul 2023 23:35:16 +0100 Subject: [PATCH 8/9] Add extra mutex guards around module value access --- src/llvm_backend_general.cpp | 3 +++ src/llvm_backend_stmt.cpp | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 676069120..f0bbaafb7 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -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; } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index ae6adb0e2..60420402a 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1878,7 +1878,9 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice 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 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 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 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); } From 3072479c3c3c4818b0a41dc2aed288e8b3ec0582 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 7 Jul 2023 23:52:56 +0100 Subject: [PATCH 9/9] Generalize name mangling rule to have a singular definition for a name separator --- src/llvm_backend.hpp | 2 ++ src/llvm_backend_general.cpp | 6 +++--- src/llvm_backend_proc.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 3aa13b488..ce01485ff 100644 --- a/src/llvm_backend.hpp +++ b/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__) diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index f0bbaafb7..ad8a1816a 100644 --- a/src/llvm_backend_general.cpp +++ b/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 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; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 42ca90828..c27c55337 100644 --- a/src/llvm_backend_proc.cpp +++ b/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;