From 33c6f75a2ea8ba1b21c64767914d5faf4e2d22b0 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Fri, 10 May 2024 17:00:07 -0400 Subject: [PATCH 01/27] Fix joining non-`Started` threads from blocking main thread --- core/thread/thread_unix.odin | 9 +++++++++ core/thread/thread_windows.odin | 12 ++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin index 290f86eac..7c353fd33 100644 --- a/core/thread/thread_unix.odin +++ b/core/thread/thread_unix.odin @@ -36,6 +36,10 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { sync.wait(&t.cond, &t.mutex) } + if .Joined in t.flags { + return nil + } + when ODIN_OS != .Darwin { // Enable thread's cancelability. if can_set_thread_cancel_state { @@ -143,6 +147,11 @@ _join :: proc(t: ^Thread) { if res, ok := CAS(&t.flags, unjoined, joined); res == joined && !ok { return } + // Prevent non-started threads from blocking main thread with initial wait + // condition. + if .Started not_in unjoined { + _start(t) + } unix.pthread_join(t.unix_thread, nil) } diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin index e85b2b62a..4e5e8c07a 100644 --- a/core/thread/thread_windows.odin +++ b/core/thread/thread_windows.odin @@ -24,6 +24,10 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { __windows_thread_entry_proc :: proc "system" (t_: rawptr) -> win32.DWORD { t := (^Thread)(t_) + if .Joined in t.flags { + return 0 + } + t.id = sync.current_thread_id() { @@ -93,11 +97,15 @@ _join :: proc(t: ^Thread) { return } + t.flags += {.Joined} + + if .Started not_in t.flags { + _start(t) + } + win32.WaitForSingleObject(t.win32_thread, win32.INFINITE) win32.CloseHandle(t.win32_thread) t.win32_thread = win32.INVALID_HANDLE - - t.flags += {.Joined} } _join_multiple :: proc(threads: ..^Thread) { From f8581537e496e9854a40f07a87543fc1357404fb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 12 May 2024 20:25:13 +0100 Subject: [PATCH 02/27] Fix `>=` for strings How did this not get noticed?!?! --- src/llvm_backend_expr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 030926079..ad02ff7dd 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2514,7 +2514,7 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left case Token_Lt: runtime_procedure = "cstring_lt"; break; case Token_Gt: runtime_procedure = "cstring_gt"; break; case Token_LtEq: runtime_procedure = "cstring_le"; break; - case Token_GtEq: runtime_procedure = "cstring_gt"; break; + case Token_GtEq: runtime_procedure = "cstring_ge"; break; } GB_ASSERT(runtime_procedure != nullptr); @@ -2537,7 +2537,7 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left case Token_Lt: runtime_procedure = "string_lt"; break; case Token_Gt: runtime_procedure = "string_gt"; break; case Token_LtEq: runtime_procedure = "string_le"; break; - case Token_GtEq: runtime_procedure = "string_gt"; break; + case Token_GtEq: runtime_procedure = "string_ge"; break; } GB_ASSERT(runtime_procedure != nullptr); From 55d21f4c2fc1872f1e7a491b6a5c645f5559f9d8 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 12 May 2024 23:38:17 +0200 Subject: [PATCH 03/27] Test string compare To avoid regression of the bug fixed in f8581537e496e9854a40f07a87543fc1357404fb. --- tests/internal/Makefile | 3 + tests/internal/build.bat | 8 ++- tests/internal/test_string_compare.odin | 91 +++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 tests/internal/test_string_compare.odin diff --git a/tests/internal/Makefile b/tests/internal/Makefile index c5c612cdd..83080140d 100644 --- a/tests/internal/Makefile +++ b/tests/internal/Makefile @@ -16,3 +16,6 @@ pow_test: asan_test: $(ODIN) run test_asan.odin -file -sanitize:address -debug + +string_compare_test: + $(ODIN) run test_string_compare.odin -file -vet -strict-style -o:minimal \ No newline at end of file diff --git a/tests/internal/build.bat b/tests/internal/build.bat index da4fe890d..29b3e36c3 100644 --- a/tests/internal/build.bat +++ b/tests/internal/build.bat @@ -1,8 +1,10 @@ @echo off set PATH_TO_ODIN==..\..\odin rem %PATH_TO_ODIN% run test_rtti.odin -file -vet -strict-style -o:minimal || exit /b -%PATH_TO_ODIN% run test_map.odin -file -vet -strict-style -o:minimal || exit /b +%PATH_TO_ODIN% run test_map.odin -file -vet -strict-style -o:minimal || exit /b rem -define:SEED=42 -%PATH_TO_ODIN% run test_pow.odin -file -vet -strict-style -o:minimal || exit /b +%PATH_TO_ODIN% run test_pow.odin -file -vet -strict-style -o:minimal || exit /b -%PATH_TO_ODIN% run test_128.odin -file -vet -strict-style -o:minimal || exit /b +%PATH_TO_ODIN% run test_128.odin -file -vet -strict-style -o:minimal || exit /b + +%PATH_TO_ODIN% run test_string_compare.odin -file -vet -strict-style -o:minimal || exit /b \ No newline at end of file diff --git a/tests/internal/test_string_compare.odin b/tests/internal/test_string_compare.odin new file mode 100644 index 000000000..a8ced485d --- /dev/null +++ b/tests/internal/test_string_compare.odin @@ -0,0 +1,91 @@ +package test_internal_string_compare + +import "core:fmt" +import "core:os" +import "core:testing" + +Op :: enum { Eq, Lt, Gt } + +Test :: struct { + a: cstring, + b: cstring, + res: [Op]bool, +} + +CASES := []Test{ + {"hellope", "hellope", {.Eq=true, .Lt=false, .Gt=false}}, + {"Hellope", "hellope", {.Eq=false, .Lt=true, .Gt=false}}, // H < h + {"Hellope!", "Hellope", {.Eq=false, .Lt=false, .Gt=true }}, +} + +@test +string_compare :: proc(t: ^testing.T) { + for v in CASES { + s_a := string(v.a) + s_b := string(v.b) + + for res, op in v.res { + switch op { + case .Eq: + expect(t, (v.a == v.b) == res, fmt.tprintf("Expected cstring(\"%v\") == cstring(\"%v\") to be %v", v.a, v.b, res)) + expect(t, (s_a == s_b) == res, fmt.tprintf("Expected string(\"%v\") == string(\"%v\") to be %v", v.a, v.b, res)) + + // If a == b then a != b + expect(t, (v.a != v.b) == !res, fmt.tprintf("Expected cstring(\"%v\") != cstring(\"%v\") to be %v", v.a, v.b, !res)) + expect(t, (s_a != s_b) == !res, fmt.tprintf("Expected string(\"%v\") != string(\"%v\") to be %v", v.a, v.b, !res)) + + case .Lt: + expect(t, (v.a < v.b) == res, fmt.tprintf("Expected cstring(\"%v\") < cstring(\"%v\") to be %v", v.a, v.b, res)) + expect(t, (s_a < s_b) == res, fmt.tprintf("Expected string(\"%v\") < string(\"%v\") to be %v", v.a, v.b, res)) + + // .Lt | .Eq == .LtEq + lteq := v.res[.Eq] | res + expect(t, (v.a <= v.b) == lteq, fmt.tprintf("Expected cstring(\"%v\") <= cstring(\"%v\") to be %v", v.a, v.b, lteq)) + expect(t, (s_a <= s_b) == lteq, fmt.tprintf("Expected string(\"%v\") <= string(\"%v\") to be %v", v.a, v.b, lteq)) + + case .Gt: + expect(t, (v.a > v.b) == res, fmt.tprintf("Expected cstring(\"%v\") > cstring(\"%v\") to be %v", v.a, v.b, res)) + expect(t, (s_a > s_b) == res, fmt.tprintf("Expected string(\"%v\") > string(\"%v\") to be %v", v.a, v.b, res)) + + // .Gt | .Eq == .GtEq + gteq := v.res[.Eq] | res + expect(t, (v.a >= v.b) == gteq, fmt.tprintf("Expected cstring(\"%v\") >= cstring(\"%v\") to be %v", v.a, v.b, gteq)) + expect(t, (s_a >= s_b) == gteq, fmt.tprintf("Expected string(\"%v\") >= string(\"%v\") to be %v", v.a, v.b, gteq)) + } + } + } +} + +// -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- + +main :: proc() { + t := testing.T{} + + string_compare(&t) + + fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count) + if TEST_fail > 0 { + os.exit(1) + } +} + +TEST_count := 0 +TEST_fail := 0 + +when ODIN_TEST { + expect :: testing.expect + log :: testing.log +} else { + expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) { + TEST_count += 1 + if !condition { + TEST_fail += 1 + fmt.printf("[%v] %v\n", loc, message) + return + } + } + log :: proc(t: ^testing.T, v: any, loc := #caller_location) { + fmt.printf("[%v] ", loc) + fmt.printf("log: %v\n", v) + } +} \ No newline at end of file From 41b8f06f51fd8cf67696a95446c0e3273d6c7eeb Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 12 May 2024 23:43:05 +0200 Subject: [PATCH 04/27] Add 1 more each for < and > --- tests/internal/test_string_compare.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/internal/test_string_compare.odin b/tests/internal/test_string_compare.odin index a8ced485d..ff65b41c2 100644 --- a/tests/internal/test_string_compare.odin +++ b/tests/internal/test_string_compare.odin @@ -15,7 +15,9 @@ Test :: struct { CASES := []Test{ {"hellope", "hellope", {.Eq=true, .Lt=false, .Gt=false}}, {"Hellope", "hellope", {.Eq=false, .Lt=true, .Gt=false}}, // H < h + {"Hell", "Hellope", {.Eq=false, .Lt=true, .Gt=false}}, {"Hellope!", "Hellope", {.Eq=false, .Lt=false, .Gt=true }}, + {"Hellopf", "Hellope", {.Eq=false, .Lt=false, .Gt=true }}, } @test From 23545c3f37833e77cd82ed9dd6c7a0e06278deda Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 12 May 2024 23:47:42 +0200 Subject: [PATCH 05/27] Enable in Makefile --- tests/internal/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/internal/Makefile b/tests/internal/Makefile index 83080140d..d17b9d012 100644 --- a/tests/internal/Makefile +++ b/tests/internal/Makefile @@ -1,6 +1,6 @@ ODIN=../../odin -all: rtti_test map_test pow_test 128_test asan_test +all: rtti_test map_test pow_test 128_test asan_test string_compare_test rtti_test: $(ODIN) run test_rtti.odin -file -vet -strict-style -o:minimal From 1935811b2c6118e633dd5c4cef2e9e70f7b962e5 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Sun, 12 May 2024 19:51:19 -0400 Subject: [PATCH 06/27] Suggest `-all-packages` if testing empty directory --- src/parser.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/parser.cpp b/src/parser.cpp index ee3c56daf..ad962f53e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -5508,11 +5508,15 @@ gb_internal AstPackage *try_add_import_path(Parser *p, String path, String const } } if (files_with_ext == 0 || files_to_reserve == 1) { + ERROR_BLOCK(); if (files_with_ext != 0) { syntax_error(pos, "Directory contains no .odin files for the specified platform: %.*s", LIT(rel_path)); } else { syntax_error(pos, "Empty directory that contains no .odin files: %.*s", LIT(rel_path)); } + if (build_context.command_kind == Command_test) { + error_line("\tSuggestion: Make an .odin file that imports packages to test and use the `-all-packages` flag."); + } return nullptr; } From 971201182abab765bbb99a671eb331b6bedf4bec Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Sun, 12 May 2024 19:52:36 -0400 Subject: [PATCH 07/27] Fix `read_directory()` skipping directories on UNIX-likes --- src/path.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/path.cpp b/src/path.cpp index b07f20870..93f6f5000 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -400,16 +400,13 @@ gb_internal ReadDirectoryError read_directory(String path, Array *fi) continue; } - if (S_ISDIR(dir_stat.st_mode)) { - continue; - } - i64 size = dir_stat.st_size; FileInfo info = {}; info.name = copy_string(a, name); info.fullpath = path_to_full_path(a, filepath); info.size = size; + info.is_dir = S_ISDIR(dir_stat.st_mode); array_add(fi, info); } From facae34354dad8a00caddfb7d224774d9d768414 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 11:53:59 +0100 Subject: [PATCH 08/27] Fix #3584 --- src/check_expr.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 08f488642..4618bf969 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1441,6 +1441,13 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T // return check_is_assignable_to(c, &o, poly); // && is_type_subtype_of_and_allow_polymorphic(o.type, poly); } return false; + + case Type_BitField: + if (source->kind == Type_BitField) { + return is_polymorphic_type_assignable(c, poly->BitField.backing_type, source->BitField.backing_type, true, modify_type); + } + return false; + case Type_Tuple: GB_PANIC("This should never happen"); return false; From 3fb0d52a745ba7215201234e18995e7489cc1f24 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 11:57:04 +0100 Subject: [PATCH 09/27] Fix #3585 --- src/llvm_backend_expr.cpp | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index ad02ff7dd..4c5ff76bc 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -5194,6 +5194,54 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { lbValue ptr = lb_address_from_load_or_generate_local(p, lb_build_expr(p, expr)); return lb_addr(ptr); case_end; + + + case_ast_node(be, OrBranchExpr, expr); + lbBlock *block = nullptr; + + if (be->label != nullptr) { + lbBranchBlocks bb = lb_lookup_branch_blocks(p, be->label); + switch (be->token.kind) { + case Token_or_break: block = bb.break_; break; + case Token_or_continue: block = bb.continue_; break; + } + } else { + for (lbTargetList *t = p->target_list; t != nullptr && block == nullptr; t = t->prev) { + if (t->is_block) { + continue; + } + + switch (be->token.kind) { + case Token_or_break: block = t->break_; break; + case Token_or_continue: block = t->continue_; break; + } + } + } + + GB_ASSERT(block != nullptr); + TypeAndValue tv = expr->tav; + + lbValue lhs = {}; + lbValue rhs = {}; + lb_emit_try_lhs_rhs(p, be->expr, tv, &lhs, &rhs); + Type *type = default_type(tv.type); + if (lhs.value) { + lhs = lb_emit_conv(p, lhs, type); + } else if (type != nullptr && type != t_invalid) { + lhs = lb_const_nil(p->module, type); + } + + lbBlock *then = lb_create_block(p, "or_branch.then"); + lbBlock *else_ = lb_create_block(p, "or_branch.else"); + + lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_); + lb_start_block(p, else_); + lb_emit_defer_stmts(p, lbDeferExit_Branch, block); + lb_emit_jump(p, block); + lb_start_block(p, then); + + return lb_addr(lb_address_from_load_or_generate_local(p, lhs)); + case_end; } TokenPos token_pos = ast_token(expr).pos; From 7905f0533f3fbbffec262a97b083d6aae450e46b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 12:01:16 +0100 Subject: [PATCH 10/27] Fix #3582 by disallowing it --- src/check_type.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 4df0c5d19..8d3c28f06 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -191,9 +191,10 @@ gb_internal void check_struct_fields(CheckerContext *ctx, Ast *node, Slicenames.count > 0) { Type *first_type = fields_array[fields_array.count-1]->type; + bool soa_ptr = is_type_soa_pointer(first_type); Type *t = base_type(type_deref(first_type)); - if (!does_field_type_allow_using(t) && + if ((soa_ptr || !does_field_type_allow_using(t)) && p->names.count >= 1 && p->names[0]->kind == Ast_Ident) { Token name_token = p->names[0]->Ident.token; From f8d235b6f572f4dd0ce3b0abd6eafbac55edc71e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 12:02:02 +0100 Subject: [PATCH 11/27] Fix #3581 due to 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 9caddfb51..3c1a7ee7f 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1180,7 +1180,7 @@ gb_internal lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) { Type *t = addr.bitfield.type; if (do_mask) { - GB_ASSERT(addr.bitfield.bit_size < 8*type_size_of(ct)); + GB_ASSERT(addr.bitfield.bit_size <= 8*type_size_of(ct)); lbValue mask = lb_const_int(p->module, t, (1ull< Date: Mon, 13 May 2024 12:24:50 +0100 Subject: [PATCH 12/27] Minor clean up of `is_terminating` code This does not fix all known issues with it --- src/check_stmt.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index c018077f9..3b836aa3c 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -254,6 +254,13 @@ gb_internal bool check_has_break(Ast *stmt, String const &label, bool implicit) } +String label_from_node(Ast *node, String default_label) { + if (node != nullptr && node->kind == Ast_Ident) { + return node->Ident.token.string; + } + return default_label; +} + // NOTE(bill): The last expression has to be a 'return' statement // TODO(bill): This is a mild hack and should be probably handled properly @@ -264,7 +271,7 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_end; case_ast_node(bs, BlockStmt, node); - return check_is_terminating_list(bs->stmts, label); + return check_is_terminating_list(bs->stmts, label_from_node(bs->label, label)); case_end; case_ast_node(es, ExprStmt, node); @@ -285,9 +292,10 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_end; case_ast_node(is, IfStmt, node); + String new_label = label_from_node(is->label, label); if (is->else_stmt != nullptr) { - if (check_is_terminating(is->body, label) && - check_is_terminating(is->else_stmt, label)) { + if (check_is_terminating(is->body, new_label) && + check_is_terminating(is->else_stmt, new_label)) { return true; } } @@ -320,7 +328,8 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_end; case_ast_node(fs, ForStmt, node); - if (fs->cond == nullptr && !check_has_break(fs->body, label, true)) { + String new_label = label_from_node(fs->label, label); + if (fs->cond == nullptr && !check_has_break(fs->body, new_label, true)) { return true; } case_end; @@ -335,14 +344,15 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_ast_node(ss, SwitchStmt, node); bool has_default = false; + String new_label = label_from_node(ss->label, label); for_array(i, ss->body->BlockStmt.stmts) { Ast *clause = ss->body->BlockStmt.stmts[i]; ast_node(cc, CaseClause, clause); if (cc->list.count == 0) { has_default = true; } - if (!check_is_terminating_list(cc->stmts, label) || - check_has_break_list(cc->stmts, label, true)) { + if (!check_is_terminating_list(cc->stmts, new_label) || + check_has_break_list(cc->stmts, new_label, true)) { return false; } } @@ -351,14 +361,15 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_ast_node(ss, TypeSwitchStmt, node); bool has_default = false; + String new_label = label_from_node(ss->label, label); for_array(i, ss->body->BlockStmt.stmts) { Ast *clause = ss->body->BlockStmt.stmts[i]; ast_node(cc, CaseClause, clause); if (cc->list.count == 0) { has_default = true; } - if (!check_is_terminating_list(cc->stmts, label) || - check_has_break_list(cc->stmts, label, true)) { + if (!check_is_terminating_list(cc->stmts, new_label) || + check_has_break_list(cc->stmts, new_label, true)) { return false; } } From d1217340f57168311cf26311f4d75a94fb26323b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 12:26:01 +0100 Subject: [PATCH 13/27] Fix #3573 --- src/check_expr.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 4618bf969..1fc6eeb52 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1794,6 +1794,13 @@ gb_internal bool check_unary_op(CheckerContext *c, Operand *o, Token op) { gb_string_free(str); return false; } + if (o->mode == Addressing_Type) { + gbString str = type_to_string(o->type); + error(o->expr, "Expected an expression for operator '%.*s', got type '%s'", LIT(op.string), str); + gb_string_free(str); + return false; + } + Type *type = base_type(core_array_type(o->type)); gbString str = nullptr; switch (op.kind) { From 34c8739b69e0778fe19f0593fecb7e7080363862 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 12:42:06 +0100 Subject: [PATCH 14/27] Fix #3578 --- src/check_stmt.cpp | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 3b836aa3c..ad91838b9 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -253,15 +253,17 @@ gb_internal bool check_has_break(Ast *stmt, String const &label, bool implicit) return false; } - -String label_from_node(Ast *node, String default_label) { - if (node != nullptr && node->kind == Ast_Ident) { +String label_string(Ast *node) { + GB_ASSERT(node != nullptr); + if (node->kind == Ast_Ident) { return node->Ident.token.string; + } else if (node->kind == Ast_Label) { + return label_string(node->Label.name); } - return default_label; + GB_ASSERT("INVALID LABEL"); + return {}; } - // NOTE(bill): The last expression has to be a 'return' statement // TODO(bill): This is a mild hack and should be probably handled properly gb_internal bool check_is_terminating(Ast *node, String const &label) { @@ -271,7 +273,12 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_end; case_ast_node(bs, BlockStmt, node); - return check_is_terminating_list(bs->stmts, label_from_node(bs->label, label)); + if (check_is_terminating_list(bs->stmts, label)) { + if (bs->label != nullptr) { + return check_is_terminating_list(bs->stmts, label_string(bs->label)); + } + return true; + } case_end; case_ast_node(es, ExprStmt, node); @@ -292,10 +299,9 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_end; case_ast_node(is, IfStmt, node); - String new_label = label_from_node(is->label, label); if (is->else_stmt != nullptr) { - if (check_is_terminating(is->body, new_label) && - check_is_terminating(is->else_stmt, new_label)) { + if (check_is_terminating(is->body, label) && + check_is_terminating(is->else_stmt, label)) { return true; } } @@ -328,8 +334,10 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_end; case_ast_node(fs, ForStmt, node); - String new_label = label_from_node(fs->label, label); - if (fs->cond == nullptr && !check_has_break(fs->body, new_label, true)) { + if (fs->cond == nullptr && !check_has_break(fs->body, label, true)) { + if (fs->label) { + return !check_has_break(fs->body, label_string(fs->label), false); + } return true; } case_end; @@ -344,15 +352,14 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_ast_node(ss, SwitchStmt, node); bool has_default = false; - String new_label = label_from_node(ss->label, label); for_array(i, ss->body->BlockStmt.stmts) { Ast *clause = ss->body->BlockStmt.stmts[i]; ast_node(cc, CaseClause, clause); if (cc->list.count == 0) { has_default = true; } - if (!check_is_terminating_list(cc->stmts, new_label) || - check_has_break_list(cc->stmts, new_label, true)) { + if (!check_is_terminating_list(cc->stmts, label) || + check_has_break_list(cc->stmts, label, true)) { return false; } } @@ -361,15 +368,14 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { case_ast_node(ss, TypeSwitchStmt, node); bool has_default = false; - String new_label = label_from_node(ss->label, label); for_array(i, ss->body->BlockStmt.stmts) { Ast *clause = ss->body->BlockStmt.stmts[i]; ast_node(cc, CaseClause, clause); if (cc->list.count == 0) { has_default = true; } - if (!check_is_terminating_list(cc->stmts, new_label) || - check_has_break_list(cc->stmts, new_label, true)) { + if (!check_is_terminating_list(cc->stmts, label) || + check_has_break_list(cc->stmts, label, true)) { return false; } } From 8b4a8e4d806a9d8328c3aedf8175c681b42cb324 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 12:49:12 +0100 Subject: [PATCH 15/27] Fix #3569 --- src/check_stmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index ad91838b9..719a0da15 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -751,7 +751,7 @@ gb_internal bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, for (auto const &entry : scope->elements) { String name = entry.key; Entity *decl = entry.value; - if (!is_entity_exported(decl)) continue; + if (!is_entity_exported(decl, true)) continue; Entity *found = scope_insert_with_name(ctx->scope, name, decl); if (found != nullptr) { From 8d687a959d29c0ef0c631103b9775091e37c7e81 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 12:52:28 +0100 Subject: [PATCH 16/27] Fix #3516 --- src/check_expr.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 1fc6eeb52..6a293a97e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -10263,6 +10263,17 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, case Type_Struct: if (is_type_soa_struct(t)) { valid = true; + if (t->Struct.soa_kind == StructSoa_Fixed) { + max_count = t->Struct.soa_count; + if (o->mode != Addressing_Variable && !is_type_pointer(o->type)) { + gbString str = expr_to_string(node); + error(node, "Cannot slice #soa array '%s', value is not addressable", str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + } o->type = make_soa_struct_slice(c, nullptr, nullptr, t->Struct.soa_elem); } break; From 6dc0ee3877d9a192a1e5483d3b80328b53b65bb7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 12:54:01 +0100 Subject: [PATCH 17/27] Fix #3577 --- core/net/common.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/net/common.odin b/core/net/common.odin index 2a6f44602..db969eab8 100644 --- a/core/net/common.odin +++ b/core/net/common.odin @@ -137,8 +137,8 @@ IP4_Address :: distinct [4]u8 IP6_Address :: distinct [8]u16be Address :: union {IP4_Address, IP6_Address} -IP4_Loopback := IP4_Address{127, 0, 0, 1} -IP6_Loopback := IP6_Address{0, 0, 0, 0, 0, 0, 0, 1} +IP4_Loopback :: IP4_Address{127, 0, 0, 1} +IP6_Loopback :: IP6_Address{0, 0, 0, 0, 0, 0, 0, 1} IP4_Any := IP4_Address{} IP6_Any := IP6_Address{} From 4bdc8548bd7ec557797985c548bd846c51ffc926 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 12:55:49 +0100 Subject: [PATCH 18/27] Fix #3554 --- src/llvm_backend_expr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 4c5ff76bc..899b74e56 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4141,7 +4141,7 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) { if (se->high == nullptr) { lbValue offset = base; LLVMValueRef indices[1] = {low.value}; - offset.value = LLVMBuildGEP2(p->builder, lb_type(p->module, offset.type->MultiPointer.elem), offset.value, indices, 1, ""); + offset.value = LLVMBuildGEP2(p->builder, lb_type(p->module, base_type(offset.type)->MultiPointer.elem), offset.value, indices, 1, ""); lb_addr_store(p, res, offset); } else { low = lb_emit_conv(p, low, t_int); @@ -4150,7 +4150,7 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) { lb_emit_multi_pointer_slice_bounds_check(p, se->open, low, high); LLVMValueRef indices[1] = {low.value}; - LLVMValueRef ptr = LLVMBuildGEP2(p->builder, lb_type(p->module, base.type->MultiPointer.elem), base.value, indices, 1, ""); + LLVMValueRef ptr = LLVMBuildGEP2(p->builder, lb_type(p->module, base_type(base.type)->MultiPointer.elem), base.value, indices, 1, ""); LLVMValueRef len = LLVMBuildSub(p->builder, high.value, low.value, ""); LLVMValueRef gep0 = lb_emit_struct_ep(p, res.addr, 0).value; From 54ebfa6179da22688239e218959320866e87a4f9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 12:58:18 +0100 Subject: [PATCH 19/27] Fix hanging on `thread.join` for windows where the thread had not been `start`ed --- core/thread/thread_windows.odin | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin index 4e5e8c07a..314ef5842 100644 --- a/core/thread/thread_windows.odin +++ b/core/thread/thread_windows.odin @@ -100,7 +100,8 @@ _join :: proc(t: ^Thread) { t.flags += {.Joined} if .Started not_in t.flags { - _start(t) + t.flags += {.Started} + win32.ResumeThread(t.win32_thread) } win32.WaitForSingleObject(t.win32_thread, win32.INFINITE) From 8808e5584a4a69e401010cbfe8800e0b2a430941 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 13:26:22 +0100 Subject: [PATCH 20/27] If only warnings exist on `print_all_errors`, next time it is called, clear the error list. This is mostly only syntax errors too --- src/error.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/error.cpp b/src/error.cpp index 688d1b34a..f5123b969 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -672,7 +672,20 @@ gb_internal int error_value_cmp(void const *a, void const *b) { return token_pos_cmp(x->pos, y->pos); } +gb_internal bool errors_already_printed = false; + gb_internal void print_all_errors(void) { + if (errors_already_printed) { + if (global_error_collector.warning_count.load() == global_error_collector.error_values.count) { + for (ErrorValue &ev : global_error_collector.error_values) { + array_free(&ev.msg); + } + array_clear(&global_error_collector.error_values); + errors_already_printed = false; + } + return; + } + auto const &escape_char = [](gbString res, u8 c) -> gbString { switch (c) { case '\n': res = gb_string_append_length(res, "\\n", 2); break; @@ -827,4 +840,6 @@ gb_internal void print_all_errors(void) { } gbFile *f = gb_file_get_standard(gbFileStandard_Error); gb_file_write(f, res, gb_string_length(res)); + + errors_already_printed = true; } \ No newline at end of file From 215ef3d985724fa0ef7092fa8f672cc502db87be Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 13:26:47 +0100 Subject: [PATCH 21/27] Make `core:runtime` etc a warning, and an error with `-vet` --- src/build_settings.cpp | 5 ++++- src/parser.cpp | 25 +++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c6ef33af2..ec7d03a84 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -730,10 +730,11 @@ enum VetFlags : u64 { VetFlag_Semicolon = 1u<<4, VetFlag_UnusedVariables = 1u<<5, VetFlag_UnusedImports = 1u<<6, + VetFlag_Deprecated = 1u<<7, VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports, - VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt, + VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt|VetFlag_Deprecated, VetFlag_Using = VetFlag_UsingStmt|VetFlag_UsingParam, }; @@ -755,6 +756,8 @@ u64 get_vet_flag_from_name(String const &name) { return VetFlag_Style; } else if (name == "semicolon") { return VetFlag_Semicolon; + } else if (name == "deprecated") { + return VetFlag_Deprecated; } return VetFlag_NONE; } diff --git a/src/parser.cpp b/src/parser.cpp index ad962f53e..66e175765 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -11,6 +11,9 @@ gb_internal bool ast_file_vet_style(AstFile *f) { return (ast_file_vet_flags(f) & VetFlag_Style) != 0; } +gb_internal bool ast_file_vet_deprecated(AstFile *f) { + return (ast_file_vet_flags(f) & VetFlag_Deprecated) != 0; +} gb_internal bool file_allow_newline(AstFile *f) { bool is_strict = build_context.strict_style || ast_file_vet_style(f); @@ -5694,8 +5697,26 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node if (collection_name.len > 0) { // NOTE(bill): `base:runtime` == `core:runtime` - if (collection_name == "core" && string_starts_with(file_str, str_lit("runtime"))) { - collection_name = str_lit("base"); + if (collection_name == "core") { + bool replace_with_base = false; + if (string_starts_with(file_str, str_lit("runtime"))) { + replace_with_base = true; + } else if (string_starts_with(file_str, str_lit("intrinsics"))) { + replace_with_base = true; + } if (string_starts_with(file_str, str_lit("builtin"))) { + replace_with_base = true; + } + + if (replace_with_base) { + collection_name = str_lit("base"); + } + if (replace_with_base) { + if (ast_file_vet_deprecated(node->file())) { + syntax_error(node, "import \"core:%.*s\" has been deprecated in favour of \"base:%.*s\"", LIT(file_str), LIT(file_str)); + } else { + syntax_warning(ast_token(node), "import \"core:%.*s\" has been deprecated in favour of \"base:%.*s\"", LIT(file_str), LIT(file_str)); + } + } } if (collection_name == "system") { From 1b593fc1cabb5dba048ef78439b2f6c42ce00be4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 13:27:44 +0100 Subject: [PATCH 22/27] Correct `core:intrinsics` to `base:intrinsics` --- core/simd/x86/abm.odin | 2 +- core/simd/x86/cmpxchg16b.odin | 2 +- core/simd/x86/sse.odin | 2 +- core/simd/x86/sse2.odin | 2 +- core/simd/x86/sse3.odin | 2 +- core/simd/x86/ssse3.odin | 2 +- examples/demo/demo.odin | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/simd/x86/abm.odin b/core/simd/x86/abm.odin index 79b806242..9018a835a 100644 --- a/core/simd/x86/abm.odin +++ b/core/simd/x86/abm.odin @@ -1,7 +1,7 @@ //+build i386, amd64 package simd_x86 -import "core:intrinsics" +import "base:intrinsics" @(require_results, enable_target_feature="lzcnt") _lzcnt_u32 :: #force_inline proc "c" (x: u32) -> u32 { diff --git a/core/simd/x86/cmpxchg16b.odin b/core/simd/x86/cmpxchg16b.odin index d575dd9df..1307a9cf2 100644 --- a/core/simd/x86/cmpxchg16b.odin +++ b/core/simd/x86/cmpxchg16b.odin @@ -1,7 +1,7 @@ //+build amd64 package simd_x86 -import "core:intrinsics" +import "base:intrinsics" cmpxchg16b :: #force_inline proc "c" (dst: ^u128, old, new: u128, $success, $failure: intrinsics.Atomic_Memory_Order) -> (val: u128) { return intrinsics.atomic_compare_exchange_strong_explicit(dst, old, new, success, failure) diff --git a/core/simd/x86/sse.odin b/core/simd/x86/sse.odin index 903a43dfd..4dac50234 100644 --- a/core/simd/x86/sse.odin +++ b/core/simd/x86/sse.odin @@ -1,7 +1,7 @@ //+build i386, amd64 package simd_x86 -import "core:intrinsics" +import "base:intrinsics" import "core:simd" // _MM_SHUFFLE(z, y, x, w) -> (z<<6 | y<<4 | x<<2 | w) diff --git a/core/simd/x86/sse2.odin b/core/simd/x86/sse2.odin index a597122f1..fc2fec300 100644 --- a/core/simd/x86/sse2.odin +++ b/core/simd/x86/sse2.odin @@ -1,7 +1,7 @@ //+build i386, amd64 package simd_x86 -import "core:intrinsics" +import "base:intrinsics" import "core:simd" @(enable_target_feature="sse2") diff --git a/core/simd/x86/sse3.odin b/core/simd/x86/sse3.odin index ca19c3954..a905a7726 100644 --- a/core/simd/x86/sse3.odin +++ b/core/simd/x86/sse3.odin @@ -1,7 +1,7 @@ //+build i386, amd64 package simd_x86 -import "core:intrinsics" +import "base:intrinsics" import "core:simd" @(require_results, enable_target_feature="sse3") diff --git a/core/simd/x86/ssse3.odin b/core/simd/x86/ssse3.odin index 0264a1c93..2026c7f53 100644 --- a/core/simd/x86/ssse3.odin +++ b/core/simd/x86/ssse3.odin @@ -1,7 +1,7 @@ //+build i386, amd64 package simd_x86 -import "core:intrinsics" +import "base:intrinsics" import "core:simd" _ :: simd diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 39345e39c..b3c627808 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -8,7 +8,7 @@ import "core:thread" import "core:time" import "core:reflect" import "base:runtime" -import "core:intrinsics" +import "base:intrinsics" import "core:math/big" /* From 8fa20fb875849774942117af3a23cb676a3fd8d7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 14:44:53 +0100 Subject: [PATCH 23/27] Extra check for `field` being `nullptr` --- src/check_type.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 8d3c28f06..c209a8e09 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -19,10 +19,12 @@ gb_internal void populate_using_array_index(CheckerContext *ctx, Ast *node, AstF } } else { Token tok = make_token_ident(name); - if (field->names.count > 0) { - tok.pos = ast_token(field->names[0]).pos; - } else { - tok.pos = ast_token(field->type).pos; + if (field) { + if (field->names.count > 0) { + tok.pos = ast_token(field->names[0]).pos; + } else { + tok.pos = ast_token(field->type).pos; + } } Entity *f = alloc_entity_array_elem(nullptr, tok, t->Array.elem, idx); add_entity(ctx, ctx->scope, nullptr, f); From 0cf9dcd31441a56856a60e4f73db4b005a1407ee Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 May 2024 18:15:29 +0100 Subject: [PATCH 24/27] Make `..` ranges a complete error rather than a warning now. This should have been an error years ago. --- src/parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser.cpp b/src/parser.cpp index 66e175765..e296e6935 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1572,7 +1572,7 @@ gb_internal Token expect_operator(AstFile *f) { LIT(p)); } if (prev.kind == Token_Ellipsis) { - syntax_warning(prev, "'..' for ranges has now been deprecated, prefer '..='"); + syntax_error(prev, "'..' for ranges are not allowed, did you mean '..<' or '..='?"); f->tokens[f->curr_token_index].flags |= TokenFlag_Replace; } From 20f8f9012d71fa9d95ff65a0badf844c9cbe4ddb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 14 May 2024 00:11:57 +0100 Subject: [PATCH 25/27] Attempt at fixing #3588 --- src/check_stmt.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 719a0da15..ee55ff0d7 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -776,6 +776,8 @@ gb_internal bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, bool is_ptr = is_type_pointer(e->type); Type *t = base_type(type_deref(e->type)); if (t->kind == Type_Struct) { + wait_signal_until_available(&t->Struct.fields_wait_signal); + Scope *found = t->Struct.scope; GB_ASSERT(found != nullptr); for (auto const &entry : found->elements) { From 7734b12f9a494142c59487265e840bc1c8e605d3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 14 May 2024 00:16:32 +0100 Subject: [PATCH 26/27] Fix #3587 --- src/check_stmt.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index ee55ff0d7..875503874 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -169,9 +169,16 @@ gb_internal bool check_has_break_list(Slice const &stmts, String const &l return false; } +gb_internal bool check_has_break_expr(Ast * expr, String const &label) { + if (expr && expr->viral_state_flags & ViralStateFlag_ContainsOrBreak) { + return true; + } + return false; +} + gb_internal bool check_has_break_expr_list(Slice const &exprs, String const &label) { for (Ast *expr : exprs) { - if (expr && expr->viral_state_flags & ViralStateFlag_ContainsOrBreak) { + if (check_has_break_expr(expr, label)) { return true; } } @@ -196,6 +203,13 @@ gb_internal bool check_has_break(Ast *stmt, String const &label, bool implicit) return check_has_break_list(stmt->BlockStmt.stmts, label, implicit); case Ast_IfStmt: + if (stmt->IfStmt.init && check_has_break(stmt->IfStmt.init, label, implicit)) { + return true; + } + if (stmt->IfStmt.cond && check_has_break_expr(stmt->IfStmt.cond, label)) { + return true; + } + if (check_has_break(stmt->IfStmt.body, label, implicit) || (stmt->IfStmt.else_stmt != nullptr && check_has_break(stmt->IfStmt.else_stmt, label, implicit))) { return true; @@ -206,6 +220,9 @@ gb_internal bool check_has_break(Ast *stmt, String const &label, bool implicit) return check_has_break_list(stmt->CaseClause.stmts, label, implicit); case Ast_SwitchStmt: + if (stmt->SwitchStmt.init && check_has_break_expr(stmt->SwitchStmt.init, label)) { + return true; + } if (label != "" && check_has_break(stmt->SwitchStmt.body, label, false)) { return true; } @@ -218,6 +235,16 @@ gb_internal bool check_has_break(Ast *stmt, String const &label, bool implicit) break; case Ast_ForStmt: + if (stmt->ForStmt.init && check_has_break(stmt->ForStmt.init, label, implicit)) { + return true; + } + if (stmt->ForStmt.cond && check_has_break_expr(stmt->ForStmt.cond, label)) { + return true; + } + if (stmt->ForStmt.post && check_has_break(stmt->ForStmt.post, label, implicit)) { + return true; + } + if (label != "" && check_has_break(stmt->ForStmt.body, label, false)) { return true; } From e05315831fe0eda44343a17c38df03cca2be0d65 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 14 May 2024 00:18:38 +0100 Subject: [PATCH 27/27] Fix #3586 --- src/llvm_backend_stmt.cpp | 41 ++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 851433415..b18db4e45 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -2157,6 +2157,16 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) { lb_open_scope(p, is->scope); // Scope #1 defer (lb_close_scope(p, lbDeferExit_Default, nullptr)); + lbBlock *then = lb_create_block(p, "if.then"); + lbBlock *done = lb_create_block(p, "if.done"); + lbBlock *else_ = done; + if (is->else_stmt != nullptr) { + else_ = lb_create_block(p, "if.else"); + } + if (is->label != nullptr) { + lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr); + tl->is_block = true; + } if (is->init != nullptr) { lbBlock *init = lb_create_block(p, "if.init"); lb_emit_jump(p, init); @@ -2164,22 +2174,12 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) { lb_build_stmt(p, is->init); } - lbBlock *then = lb_create_block(p, "if.then"); - lbBlock *done = lb_create_block(p, "if.done"); - lbBlock *else_ = done; - if (is->else_stmt != nullptr) { - else_ = lb_create_block(p, "if.else"); - } lbValue cond = lb_build_cond(p, is->cond, then, else_); // Note `cond.value` only set for non-and/or conditions and const negs so that the `LLVMIsConstant()` // and `LLVMConstIntGetZExtValue()` calls below will be valid and `LLVMInstructionEraseFromParent()` // will target the correct (& only) branch statement - if (is->label != nullptr) { - lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr); - tl->is_block = true; - } if (cond.value && LLVMIsConstant(cond.value)) { // NOTE(bill): Do a compile time short circuit for when the condition is constantly known. @@ -2244,15 +2244,6 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { if (p->debug_info != nullptr) { LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, node)); } - - if (fs->init != nullptr) { - #if 1 - lbBlock *init = lb_create_block(p, "for.init"); - lb_emit_jump(p, init); - lb_start_block(p, init); - #endif - lb_build_stmt(p, fs->init); - } lbBlock *body = lb_create_block(p, "for.body"); lbBlock *done = lb_create_block(p, "for.done"); // NOTE(bill): Append later lbBlock *loop = body; @@ -2264,6 +2255,17 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { post = lb_create_block(p, "for.post"); } + lb_push_target_list(p, fs->label, done, post, nullptr); + + if (fs->init != nullptr) { + #if 1 + lbBlock *init = lb_create_block(p, "for.init"); + lb_emit_jump(p, init); + lb_start_block(p, init); + #endif + lb_build_stmt(p, fs->init); + } + lb_emit_jump(p, loop); lb_start_block(p, loop); @@ -2276,7 +2278,6 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { lb_start_block(p, body); } - lb_push_target_list(p, fs->label, done, post, nullptr); lb_build_stmt(p, fs->body);