From 9cdb7b2584492a76fec6a49998e2937e4b1a78c3 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:16:33 -0400 Subject: [PATCH 01/16] Fix discrepancy with pthread cancelability state --- core/thread/thread_unix.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin index c75710873..290f86eac 100644 --- a/core/thread/thread_unix.odin +++ b/core/thread/thread_unix.odin @@ -25,7 +25,7 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { when ODIN_OS != .Darwin { // We need to give the thread a moment to start up before we enable cancellation. - can_set_thread_cancel_state := unix.pthread_setcancelstate(unix.PTHREAD_CANCEL_DISABLE, nil) == 0 + can_set_thread_cancel_state := unix.pthread_setcancelstate(unix.PTHREAD_CANCEL_ENABLE, nil) == 0 } sync.lock(&t.mutex) @@ -40,7 +40,7 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { // Enable thread's cancelability. if can_set_thread_cancel_state { unix.pthread_setcanceltype (unix.PTHREAD_CANCEL_ASYNCHRONOUS, nil) - unix.pthread_setcancelstate(unix.PTHREAD_CANCEL_DISABLE, nil) + unix.pthread_setcancelstate(unix.PTHREAD_CANCEL_ENABLE, nil) } } From 30ff15e53805590ac48560080aa56a5e540ea22e Mon Sep 17 00:00:00 2001 From: Su3h7aM Date: Tue, 30 Apr 2024 16:17:19 -0300 Subject: [PATCH 02/16] build: uses correct `clang++` binary for non-standard versions --- build_odin.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_odin.sh b/build_odin.sh index aca98a36d..11ae830c7 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -2,7 +2,6 @@ set -eu : ${CPPFLAGS=} -: ${CXX=clang++} : ${CXXFLAGS=} : ${LDFLAGS=} : ${LLVM_CONFIG=} @@ -44,6 +43,8 @@ if [ -z "$LLVM_CONFIG" ]; then fi fi +: ${CXX=$($LLVM_CONFIG --bindir)/clang++} + LLVM_VERSION="$($LLVM_CONFIG --version)" LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')" LLVM_VERSION_MINOR="$(echo $LLVM_VERSION | awk -F. '{print $2}')" From 8e4f9cb777b91ade22fc1f00d166af1ea06624c5 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Sun, 5 May 2024 21:08:33 -0400 Subject: [PATCH 03/16] Fix: Fixed #soa arrays --- src/check_expr.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index c143cfce0..939466a64 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -102,6 +102,7 @@ gb_internal Type * check_init_variable (CheckerContext *c, Entity * gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o, Type *type, i64 max_bit_size=0); gb_internal void add_map_key_type_dependencies(CheckerContext *ctx, Type *key); +gb_internal Type *make_soa_struct_fixed(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem, i64 count, Type *generic_type); gb_internal Type *make_soa_struct_slice(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem); gb_internal Type *make_soa_struct_dynamic_array(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem); @@ -1409,11 +1410,19 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T poly->Struct.soa_kind != StructSoa_None) { bool ok = is_polymorphic_type_assignable(c, poly->Struct.soa_elem, source->Struct.soa_elem, true, modify_type); if (ok) switch (source->Struct.soa_kind) { - case StructSoa_Fixed: default: GB_PANIC("Unhandled SOA Kind"); break; - + case StructSoa_Fixed: + if (modify_type) { + bool breakpoint = true; + Type *type = make_soa_struct_fixed( + c, nullptr, poly->Struct.node, + poly->Struct.soa_elem, poly->Struct.soa_count, + nullptr); + gb_memmove(poly, type, gb_size_of(*type)); + } + break; case StructSoa_Slice: if (modify_type) { Type *type = make_soa_struct_slice(c, nullptr, poly->Struct.node, poly->Struct.soa_elem); From a9b18c1ec02e6bf0db337accf3edcd9fa7984250 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Sun, 5 May 2024 21:15:41 -0400 Subject: [PATCH 04/16] Formatting --- src/check_expr.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 939466a64..c11021a4f 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1416,10 +1416,7 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T case StructSoa_Fixed: if (modify_type) { bool breakpoint = true; - Type *type = make_soa_struct_fixed( - c, nullptr, poly->Struct.node, - poly->Struct.soa_elem, poly->Struct.soa_count, - nullptr); + Type *type = make_soa_struct_fixed(c, nullptr, poly->Struct.node, poly->Struct.soa_elem, poly->Struct.soa_count, nullptr); gb_memmove(poly, type, gb_size_of(*type)); } break; From df53fec828e79f73fc540a88d000dc1ba245281f Mon Sep 17 00:00:00 2001 From: Hiroaki Nakamura Date: Mon, 6 May 2024 21:44:59 +0900 Subject: [PATCH 05/16] sys/linux: Pass size to epoll_create Without this fix, you can see a random size value is passed to epoll_create by using strace. --- core/sys/linux/sys.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 63fb3b776..413c8742b 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -2314,7 +2314,7 @@ futex :: proc { */ epoll_create :: proc(size: i32 = 1) -> (Fd, Errno) { when ODIN_ARCH != .arm64 { - ret := syscall(SYS_epoll_create) + ret := syscall(SYS_epoll_create, i32(1)) return errno_unwrap(ret, Fd) } else { ret := syscall(SYS_epoll_create1, i32(0)) From 6cb0f5d8c5aa71acf28870afe10295e939a8979d Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Mon, 6 May 2024 18:04:35 -0400 Subject: [PATCH 06/16] Explicitly handle previously implicitly handled case --- src/check_expr.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index c11021a4f..04464d09f 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1410,6 +1410,7 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T poly->Struct.soa_kind != StructSoa_None) { bool ok = is_polymorphic_type_assignable(c, poly->Struct.soa_elem, source->Struct.soa_elem, true, modify_type); if (ok) switch (source->Struct.soa_kind) { + case StructSoa_None: default: GB_PANIC("Unhandled SOA Kind"); break; From 56b62996c35ac364f545c034cd731e808b35da20 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Mon, 6 May 2024 18:20:20 -0400 Subject: [PATCH 07/16] Remove breakpoint hook --- src/check_expr.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 04464d09f..013638e63 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1416,7 +1416,6 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T break; case StructSoa_Fixed: if (modify_type) { - bool breakpoint = true; Type *type = make_soa_struct_fixed(c, nullptr, poly->Struct.node, poly->Struct.soa_elem, poly->Struct.soa_count, nullptr); gb_memmove(poly, type, gb_size_of(*type)); } From 6ec7845249d2e77e68f2e802e3bebe5b5fc3480f Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Mon, 6 May 2024 18:27:34 -0400 Subject: [PATCH 08/16] Fix #3531 Individual `bit_field` size was not being added to the total size. Error message was changed to be more explicit. --- src/check_type.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 61c502a68..457375779 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1080,6 +1080,8 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, array_add(&tags, tag); add_entity_use(ctx, field, e); + + total_bit_size += bit_size_u8; } } @@ -1094,7 +1096,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, if (total_bit_size > maximum_bit_size) { gbString s = type_to_string(backing_type); - error(node, "The numbers required %llu exceeds the backing type's (%s) bit size %llu", + error(node, "The total bit size of a bit_field's fields (%llu) must fit into its backing type's (%s) bit size of %llu", cast(unsigned long long)total_bit_size, s, cast(unsigned long long)maximum_bit_size); From b23f1dd5ffd0f1d3e74dc48b7f4b13d441cea3ff Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 May 2024 11:19:16 +0100 Subject: [PATCH 09/16] Merge neighbouring error messages with the same location --- src/error.cpp | 91 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 34 deletions(-) diff --git a/src/error.cpp b/src/error.cpp index 1009bb7cd..08675c4be 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -12,7 +12,7 @@ struct ErrorValue { }; struct ErrorCollector { - TokenPos prev; + // TokenPos prev; // no point collecting because of the mulithreaded nature std::atomic count; std::atomic warning_count; std::atomic in_block; @@ -383,14 +383,13 @@ gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va } push_error_value(pos, ErrorValue_Error); - // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { error_out_empty(); error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red); error_out_va(fmt, va); error_out("\n"); - } else if (global_error_collector.prev != pos) { - global_error_collector.prev = pos; + } else { + // global_error_collector.prev = pos; if (json_errors()) { error_out_empty(); } else { @@ -402,10 +401,6 @@ gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va error_out_va(fmt, va); error_out("\n"); show_error_on_line(pos, end); - } else { - global_error_collector.curr_error_value = {}; - global_error_collector.curr_error_value_set.store(false); - global_error_collector.count.fetch_sub(1); } try_pop_error_value(); mutex_unlock(&global_error_collector.mutex); @@ -422,14 +417,13 @@ gb_internal void warning_va(TokenPos const &pos, TokenPos end, char const *fmt, push_error_value(pos, ErrorValue_Warning); if (!global_ignore_warnings()) { - // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { error_out_empty(); error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow); error_out_va(fmt, va); error_out("\n"); - } else if (global_error_collector.prev != pos) { - global_error_collector.prev = pos; + } else { + // global_error_collector.prev = pos; if (json_errors()) { error_out_empty(); } else { @@ -460,13 +454,12 @@ gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_li push_error_value(pos, ErrorValue_Error); - // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { error_out_empty(); error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red); error_out_va(fmt, va); - } else if (global_error_collector.prev != pos) { - global_error_collector.prev = pos; + } else { + // global_error_collector.prev = pos; if (json_errors()) { error_out_empty(); } else { @@ -493,9 +486,13 @@ gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const * push_error_value(pos, ErrorValue_Warning); - // NOTE(bill): Duplicate error, skip it - if (global_error_collector.prev != pos) { - global_error_collector.prev = pos; + if (pos.line == 0) { + error_out_empty(); + error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red); + error_out_va(fmt, va); + error_out("\n"); + } else { + // global_error_collector.prev = pos; if (json_errors()) { error_out_empty(); } else { @@ -505,11 +502,6 @@ gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const * error_out_va(fmt, va); error_out("\n"); show_error_on_line(pos, end); - } else if (pos.line == 0) { - error_out_empty(); - error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red); - error_out_va(fmt, va); - error_out("\n"); } try_pop_error_value(); @@ -526,14 +518,13 @@ gb_internal void syntax_error_with_verbose_va(TokenPos const &pos, TokenPos end, push_error_value(pos, ErrorValue_Warning); - // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { error_out_empty(); error_out_coloured("Syntax_Error: ", TerminalStyle_Normal, TerminalColour_Red); error_out_va(fmt, va); error_out("\n"); - } else if (global_error_collector.prev != pos) { - global_error_collector.prev = pos; + } else { + // global_error_collector.prev = pos; if (json_errors()) { error_out_empty(); } else { @@ -564,9 +555,13 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const push_error_value(pos, ErrorValue_Warning); if (!global_ignore_warnings()) { - // NOTE(bill): Duplicate error, skip it - if (global_error_collector.prev != pos) { - global_error_collector.prev = pos; + if (pos.line == 0) { + error_out_empty(); + error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow); + error_out_va(fmt, va); + error_out("\n"); + } else { + // global_error_collector.prev = pos; if (json_errors()) { error_out_empty(); } else { @@ -576,11 +571,6 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const error_out_va(fmt, va); error_out("\n"); // show_error_on_line(pos, end); - } else if (pos.line == 0) { - error_out_empty(); - error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow); - error_out_va(fmt, va); - error_out("\n"); } } @@ -705,9 +695,41 @@ gb_internal void print_all_errors(void) { GB_ASSERT(any_errors() || any_warnings()); - array_sort(global_error_collector.error_values, error_value_cmp); + + { // NOTE(bill): merge neighbouring errors + isize default_lines_to_skip = 1; + if (show_error_line()) { + // NOTE(bill): this will always be 2 extra lines + default_lines_to_skip += 2; + } + + ErrorValue *prev_ev = nullptr; + for (isize i = 0; i < global_error_collector.error_values.count; /**/) { + ErrorValue &ev = global_error_collector.error_values[i]; + + if (prev_ev && prev_ev->pos == ev.pos) { + String_Iterator it = {{ev.msg.data, ev.msg.count}, 0}; + + for (isize lines_to_skip = default_lines_to_skip; lines_to_skip > 0; lines_to_skip -= 1) { + String line = string_split_iterator(&it, '\n'); + if (line.len == 0) { + break; + } + } + + if (it.str.len-it.pos > 0) { + array_add_elems(&prev_ev->msg, it.str.text+it.pos, it.str.len-it.pos); + } + array_ordered_remove(&global_error_collector.error_values, i); + } else { + prev_ev = &ev; + i += 1; + } + } + } + gbString res = gb_string_make(heap_allocator(), ""); defer (gb_string_free(res)); @@ -715,6 +737,7 @@ gb_internal void print_all_errors(void) { res = gb_string_append_fmt(res, "{\n"); res = gb_string_append_fmt(res, "\t\"error_count\": %td,\n", global_error_collector.error_values.count); res = gb_string_append_fmt(res, "\t\"errors\": [\n"); + for_array(i, global_error_collector.error_values) { ErrorValue ev = global_error_collector.error_values[i]; From 1818df786dbd8595bb58719ce849350b354c60a7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 May 2024 11:21:12 +0100 Subject: [PATCH 10/16] Free memory for the error messages just in case --- src/error.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/error.cpp b/src/error.cpp index 08675c4be..1877a672b 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -722,6 +722,7 @@ gb_internal void print_all_errors(void) { if (it.str.len-it.pos > 0) { array_add_elems(&prev_ev->msg, it.str.text+it.pos, it.str.len-it.pos); } + array_free(&ev.msg); array_ordered_remove(&global_error_collector.error_values, i); } else { prev_ev = &ev; From 05a17048982dea73ac0c7db1e743582abf73233b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 May 2024 11:24:21 +0100 Subject: [PATCH 11/16] Fix #3464 --- src/check_builtin.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 825fc6448..3d31ec75d 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -2023,6 +2023,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As Selection sel = lookup_field(type, field_name, false); if (sel.entity == nullptr) { + ERROR_BLOCK(); gbString type_str = type_to_string_shorthand(type); error(ce->args[0], "'%s' has no field named '%.*s'", type_str, LIT(field_name)); @@ -2096,6 +2097,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As Selection sel = lookup_field(type, field_name, false); if (sel.entity == nullptr) { + ERROR_BLOCK(); gbString type_str = type_to_string_shorthand(type); error(ce->args[0], "'%s' has no field named '%.*s'", type_str, LIT(field_name)); @@ -5837,6 +5839,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As Selection sel = lookup_field(type, field_name, false); if (sel.entity == nullptr) { + ERROR_BLOCK(); gbString type_str = type_to_string(bt); error(ce->args[0], "'%s' has no field named '%.*s'", type_str, LIT(field_name)); From 0da6a3e214c66e2955307e2aad12d844a051f8d8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 May 2024 11:42:48 +0100 Subject: [PATCH 12/16] Fix #3530 --- src/check_type.cpp | 9 +++++++-- src/parser.cpp | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 457375779..6efac54d6 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -797,11 +797,11 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam enum_type->Enum.scope = ctx->scope; Type *base_type = t_int; - if (et->base_type != nullptr) { + if (unparen_expr(et->base_type) != nullptr) { base_type = check_type(ctx, et->base_type); } - if (base_type == nullptr || !is_type_integer(base_type)) { + if (base_type == nullptr || base_type == t_invalid || !is_type_integer(base_type)) { error(node, "Base type for enumeration must be an integer"); return; } @@ -3265,6 +3265,11 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T case_end; case_ast_node(pe, ParenExpr, e); + if (pe->expr == nullptr) { + error(e, "Expected an expression or type within the parentheses"); + *type = t_invalid; + return true; + } *type = check_type_expr(ctx, pe->expr, named_type); set_base_type(named_type, *type); return true; diff --git a/src/parser.cpp b/src/parser.cpp index 2bf25c768..04505cbd7 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3499,6 +3499,10 @@ gb_internal Ast *parse_type(AstFile *f) { Token token = advance_token(f); syntax_error(token, "Expected a type"); return ast_bad_expr(f, token, f->curr_token); + } else if (type->kind == Ast_ParenExpr && + unparen_expr(type) == nullptr) { + syntax_error(type, "Expected a type within the parentheses"); + return ast_bad_expr(f, type->ParenExpr.open, type->ParenExpr.close); } return type; } From 0cec2d7827a537557555bf6c92c2f090113806a4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 May 2024 11:51:06 +0100 Subject: [PATCH 13/16] Fix #3527 --- src/check_type.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/check_type.cpp b/src/check_type.cpp index 6efac54d6..ea249c293 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1430,6 +1430,10 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special bool can_convert = check_cast_internal(ctx, &o, specialization); return can_convert; } else if (t->kind == Type_Struct) { + if (t->Struct.polymorphic_parent == nullptr && + t == s) { + return true; + } if (t->Struct.polymorphic_parent == specialization) { return true; } @@ -1479,6 +1483,10 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special return true; } } else if (t->kind == Type_Union) { + if (t->Union.polymorphic_parent == nullptr && + t == s) { + return true; + } if (t->Union.polymorphic_parent == specialization) { return true; } From 3f7a369aa1ff90ec1c71e6b4805778d4899790a5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 May 2024 14:53:02 +0100 Subject: [PATCH 14/16] Check for specialization in `typeid/T` for parapoly records --- src/check_type.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index ea249c293..c119ce6b5 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -381,6 +381,7 @@ gb_internal Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *poly Type *type = nullptr; bool is_type_param = false; bool is_type_polymorphic_type = false; + Type *specialization = nullptr; if (type_expr == nullptr && default_value == nullptr) { error(param, "Expected a type for this parameter"); continue; @@ -393,7 +394,6 @@ gb_internal Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *poly } if (type_expr->kind == Ast_TypeidType) { is_type_param = true; - Type *specialization = nullptr; if (type_expr->TypeidType.specialization != nullptr) { Ast *s = type_expr->TypeidType.specialization; specialization = check_type(ctx, s); @@ -471,6 +471,15 @@ gb_internal Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *poly if (is_type_polymorphic(base_type(operand.type))) { *is_polymorphic_ = true; can_check_fields = false; + } else if (specialization && + !check_type_specialization_to(ctx, specialization, operand.type, false, /*modify_type*/true)) { + if (!ctx->no_polymorphic_errors) { + gbString t = type_to_string(operand.type); + gbString s = type_to_string(specialization); + error(operand.expr, "Cannot convert type '%s' to the specialization '%s'", t, s); + gb_string_free(s); + gb_string_free(t); + } } e = alloc_entity_type_name(scope, token, operand.type); e->TypeName.is_type_alias = true; From de5ce90fa70c8ae4b859b50704dd0ffacbeedb1e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 May 2024 15:28:09 +0100 Subject: [PATCH 15/16] Add metadata to packed structs field accesses to state it is packed --- src/llvm_backend.hpp | 6 +++++- src/llvm_backend_general.cpp | 6 ++++++ src/llvm_backend_utility.cpp | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 7dc5f6b63..975aa17c5 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -581,6 +581,10 @@ gb_internal LLVMTypeRef llvm_array_type(LLVMTypeRef ElementType, uint64_t Elemen #endif } + +gb_internal void lb_set_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name, u64 value); +gb_internal u64 lb_get_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name); + #define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime" #define LB_CLEANUP_RUNTIME_PROC_NAME "__$cleanup_runtime" #define LB_TYPE_INFO_DATA_NAME "__$type_info_data" @@ -719,4 +723,4 @@ gb_global char const *llvm_linkage_strings[] = { "linker private weak linkage" }; -#define ODIN_METADATA_REQUIRE "odin-metadata-require", 21 +#define ODIN_METADATA_IS_PACKED str_lit("odin-is-packed") \ No newline at end of file diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 15cbb7c71..22ffbd89c 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1107,6 +1107,12 @@ gb_internal lbValue lb_emit_load(lbProcedure *p, lbValue value) { GB_ASSERT(is_type_pointer(value.type)); Type *t = type_deref(value.type); LLVMValueRef v = LLVMBuildLoad2(p->builder, lb_type(p->module, t), value.value, ""); + + u64 is_packed = lb_get_metadata_custom_u64(p->module, v, ODIN_METADATA_IS_PACKED); + if (is_packed != 0) { + LLVMSetAlignment(v, 1); + } + return lbValue{v, t}; } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index db99ebc99..8b046c784 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -57,6 +57,29 @@ gb_internal lbValue lb_correct_endianness(lbProcedure *p, lbValue value) { return value; } + +gb_internal void lb_set_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name, u64 value) { + unsigned md_id = LLVMGetMDKindIDInContext(m->ctx, cast(char const *)name.text, cast(unsigned)name.len); + LLVMMetadataRef md = LLVMValueAsMetadata(LLVMConstInt(lb_type(m, t_u64), value, false)); + LLVMValueRef node = LLVMMetadataAsValue(m->ctx, LLVMMDNodeInContext2(m->ctx, &md, 1)); + LLVMSetMetadata(v_ref, md_id, node); +} +gb_internal u64 lb_get_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name) { + unsigned md_id = LLVMGetMDKindIDInContext(m->ctx, cast(char const *)name.text, cast(unsigned)name.len); + LLVMValueRef v_md = LLVMGetMetadata(v_ref, md_id); + if (v_md == nullptr) { + return 0; + } + unsigned node_count = LLVMGetMDNodeNumOperands(v_md); + if (node_count == 0) { + return 0; + } + GB_ASSERT(node_count == 1); + LLVMValueRef value = nullptr; + LLVMGetMDNodeOperands(v_md, &value); + return LLVMConstIntGetZExtValue(value); +} + gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile) { return lb_mem_zero_ptr_internal(p, ptr, LLVMConstInt(lb_type(p->module, t_uint), len, false), alignment, is_volatile); } @@ -1148,7 +1171,15 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { GB_ASSERT_MSG(result_type != nullptr, "%s %d", type_to_string(t), index); - return lb_emit_struct_ep_internal(p, s, index, result_type); + lbValue gep = lb_emit_struct_ep_internal(p, s, index, result_type); + + Type *bt = base_type(t); + if (bt->kind == Type_Struct && bt->Struct.is_packed) { + lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1); + GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1); + } + + return gep; } gb_internal lbValue lb_emit_tuple_ev(lbProcedure *p, lbValue value, i32 index) { From 1d3c061add30bf517bd7bffbbdfc0a7900bef2fd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 May 2024 15:52:13 +0100 Subject: [PATCH 16/16] Fix typo --- src/llvm_backend_general.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 22ffbd89c..9caddfb51 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1108,7 +1108,7 @@ gb_internal lbValue lb_emit_load(lbProcedure *p, lbValue value) { Type *t = type_deref(value.type); LLVMValueRef v = LLVMBuildLoad2(p->builder, lb_type(p->module, t), value.value, ""); - u64 is_packed = lb_get_metadata_custom_u64(p->module, v, ODIN_METADATA_IS_PACKED); + u64 is_packed = lb_get_metadata_custom_u64(p->module, value.value, ODIN_METADATA_IS_PACKED); if (is_packed != 0) { LLVMSetAlignment(v, 1); }